///|
priv struct ImageVertices2D {
vertices : Array[Double]
sampler_code : Int
}
///|
fn pack_rect_fill_vertices2d(
rect : @smath.Rect,
transform : @smath.Transform,
color : @render.Color,
) -> Array[Double] {
let (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) = rect_points2d(rect, transform)
let vertices : Array[Double] = []
let (r, g, b, a) = color_rgba01(color)
push_color_vertex2d(vertices, p0x, p0y, r, g, b, a)
push_color_vertex2d(vertices, p1x, p1y, r, g, b, a)
push_color_vertex2d(vertices, p2x, p2y, r, g, b, a)
push_color_vertex2d(vertices, p0x, p0y, r, g, b, a)
push_color_vertex2d(vertices, p2x, p2y, r, g, b, a)
push_color_vertex2d(vertices, p3x, p3y, r, g, b, a)
vertices
}
///|
fn pack_rect_stroke_vertices2d(
rect : @smath.Rect,
transform : @smath.Transform,
color : @render.Color,
) -> Array[Double] {
let (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) = rect_points2d(rect, transform)
let vertices : Array[Double] = []
let (r, g, b, a) = color_rgba01(color)
push_color_vertex2d(vertices, p0x, p0y, r, g, b, a)
push_color_vertex2d(vertices, p1x, p1y, r, g, b, a)
push_color_vertex2d(vertices, p1x, p1y, r, g, b, a)
push_color_vertex2d(vertices, p2x, p2y, r, g, b, a)
push_color_vertex2d(vertices, p2x, p2y, r, g, b, a)
push_color_vertex2d(vertices, p3x, p3y, r, g, b, a)
push_color_vertex2d(vertices, p3x, p3y, r, g, b, a)
push_color_vertex2d(vertices, p0x, p0y, r, g, b, a)
vertices
}
///|
fn pack_gradient_rect_vertices2d(
rect : @smath.Rect,
transform : @smath.Transform,
color_start : @render.Color,
color_end : @render.Color,
) -> Array[Double] {
let (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) = rect_points2d(rect, transform)
let (r0, g0, b0, a0) = color_rgba01(color_start)
let (r1, g1, b1, a1) = color_rgba01(color_end)
let rm = (r0 + r1) * 0.5
let gm = (g0 + g1) * 0.5
let bm = (b0 + b1) * 0.5
let am = (a0 + a1) * 0.5
let vertices : Array[Double] = []
push_color_vertex2d(vertices, p0x, p0y, r0, g0, b0, a0)
push_color_vertex2d(vertices, p1x, p1y, rm, gm, bm, am)
push_color_vertex2d(vertices, p2x, p2y, r1, g1, b1, a1)
push_color_vertex2d(vertices, p0x, p0y, r0, g0, b0, a0)
push_color_vertex2d(vertices, p2x, p2y, r1, g1, b1, a1)
push_color_vertex2d(vertices, p3x, p3y, rm, gm, bm, am)
vertices
}
///|
fn pack_image_vertices2d(
command : @render2d_types.ImageDrawCommand2D,
image_width : Double,
image_height : Double,
) -> ImageVertices2D {
pack_image_vertices2d_raw(
command.destination,
command.transform,
command.source,
command.uv_transform,
command.repeat,
command.color,
image_width,
image_height,
)
}
///|
fn pack_image_vertices2d_raw(
destination : @smath.Rect,
transform : @smath.Transform,
source : @render2d_types.ImageRegion2D?,
uv_transform : @smath.Transform,
repeat : @smath.RepeatMode,
color : @render.Color,
image_width : Double,
image_height : Double,
) -> ImageVertices2D {
let (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) = rect_points2d(
destination, transform,
)
let mut u0 = 0.0
let mut v0 = 0.0
let mut u1 = 1.0
let mut v1 = 1.0
let mut sampler_code = 0
match source {
Some(source) => {
u0 = source.position[X] / image_width
v0 = source.position[Y] / image_height
u1 = (source.position[X] + source.size[X]) / image_width
v1 = (source.position[Y] + source.size[Y]) / image_height
}
None => {
let scale_u = destination.size[X] / image_width
let scale_v = destination.size[Y] / image_height
match repeat {
Repeat => {
u1 = scale_u
v1 = scale_v
sampler_code = 3
}
RepeatX => {
u1 = scale_u
sampler_code = 1
}
RepeatY => {
v1 = scale_v
sampler_code = 2
}
NoRepeat => ()
}
}
}
let (tu0, tv0) = transform_uv2d(uv_transform, u0, v0)
let (tu1, tv0b) = transform_uv2d(uv_transform, u1, v0)
let (tu1b, tv1) = transform_uv2d(uv_transform, u1, v1)
let (tu0b, tv1b) = transform_uv2d(uv_transform, u0, v1)
let (r, g, b, a) = color_rgba01(color)
let vertices : Array[Double] = []
push_tex_vertex2d(vertices, p0x, p0y, tu0, tv0, r, g, b, a)
push_tex_vertex2d(vertices, p1x, p1y, tu1, tv0b, r, g, b, a)
push_tex_vertex2d(vertices, p2x, p2y, tu1b, tv1, r, g, b, a)
push_tex_vertex2d(vertices, p0x, p0y, tu0, tv0, r, g, b, a)
push_tex_vertex2d(vertices, p2x, p2y, tu1b, tv1, r, g, b, a)
push_tex_vertex2d(vertices, p3x, p3y, tu0b, tv1b, r, g, b, a)
{ vertices, sampler_code }
}
///|
fn pack_text_vertices2d(
command : @render2d_types.TextDrawCommand2D,
texture_width : Double,
texture_height : Double,
) -> Array[Double] {
let mut x = command.position[X]
let mut y = command.position[Y]
match command.style.align {
Center => x = x - texture_width / 2.0
Right => x = x - texture_width
Left => ()
}
match command.style.baseline {
Center => y = y - texture_height / 2.0
Bottom => y = y - texture_height
Top => ()
}
pack_text_vertices2d_raw(
{ position: Vec2(x, y), size: Vec2(texture_width, texture_height) },
command.transform,
)
}
///|
fn pack_text_vertices2d_raw(
rect : @smath.Rect,
transform : @smath.Transform,
) -> Array[Double] {
let (p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) = rect_points2d(rect, transform)
let vertices : Array[Double] = []
push_tex_vertex2d(vertices, p0x, p0y, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0)
push_tex_vertex2d(vertices, p1x, p1y, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0)
push_tex_vertex2d(vertices, p2x, p2y, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
push_tex_vertex2d(vertices, p0x, p0y, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0)
push_tex_vertex2d(vertices, p2x, p2y, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
push_tex_vertex2d(vertices, p3x, p3y, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)
vertices
}
///|
fn pack_circle_fill_vertices2d(
center : @smath.Vec2,
radius : Double,
transform : @smath.Transform,
color : @render.Color,
) -> Array[Double] {
let vertices : Array[Double] = []
let (r, g, b, a) = color_rgba01(color)
let center_x = center[X] + transform.tx
let center_y = center[Y] + transform.ty
for index in 0..<40 {
let angle0 = index.to_double() / 40.0 * @math.PI * 2.0
let angle1 = (index + 1).to_double() / 40.0 * @math.PI * 2.0
let (x0, y0) = transformed_local_point2d(
center,
transform,
@math.cos(angle0) * radius,
@math.sin(angle0) * radius,
)
let (x1, y1) = transformed_local_point2d(
center,
transform,
@math.cos(angle1) * radius,
@math.sin(angle1) * radius,
)
push_color_vertex2d(vertices, center_x, center_y, r, g, b, a)
push_color_vertex2d(vertices, x0, y0, r, g, b, a)
push_color_vertex2d(vertices, x1, y1, r, g, b, a)
}
vertices
}
///|
fn pack_circle_stroke_vertices2d(
center : @smath.Vec2,
radius : Double,
transform : @smath.Transform,
color : @render.Color,
) -> Array[Double] {
let vertices : Array[Double] = []
let (r, g, b, a) = color_rgba01(color)
for index in 0..<40 {
let angle0 = index.to_double() / 40.0 * @math.PI * 2.0
let angle1 = (index + 1).to_double() / 40.0 * @math.PI * 2.0
let (x0, y0) = transformed_local_point2d(
center,
transform,
@math.cos(angle0) * radius,
@math.sin(angle0) * radius,
)
let (x1, y1) = transformed_local_point2d(
center,
transform,
@math.cos(angle1) * radius,
@math.sin(angle1) * radius,
)
push_color_vertex2d(vertices, x0, y0, r, g, b, a)
push_color_vertex2d(vertices, x1, y1, r, g, b, a)
}
vertices
}
///|
fn rect_points2d(
rect : @smath.Rect,
transform : @smath.Transform,
) -> (Double, Double, Double, Double, Double, Double, Double, Double) {
let origin = rect.position
let width = rect.size[X]
let height = rect.size[Y]
let (p0x, p0y) = transformed_local_point2d(origin, transform, 0.0, 0.0)
let (p1x, p1y) = transformed_local_point2d(origin, transform, width, 0.0)
let (p2x, p2y) = transformed_local_point2d(origin, transform, width, height)
let (p3x, p3y) = transformed_local_point2d(origin, transform, 0.0, height)
(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y)
}
///|
fn transformed_local_point2d(
origin : @smath.Vec2,
transform : @smath.Transform,
local_x : Double,
local_y : Double,
) -> (Double, Double) {
(
transform.a * local_x + transform.c * local_y + transform.tx + origin[X],
transform.b * local_x + transform.d * local_y + transform.ty + origin[Y],
)
}
///|
fn transform_uv2d(
transform : @smath.Transform,
u : Double,
v : Double,
) -> (Double, Double) {
(
transform.a * u + transform.c * v + transform.tx,
transform.b * u + transform.d * v + transform.ty,
)
}
///|
fn color_rgba01(color : @render.Color) -> (Double, Double, Double, Double) {
(
color.r.reinterpret_as_int().to_double() / 255.0,
color.g.reinterpret_as_int().to_double() / 255.0,
color.b.reinterpret_as_int().to_double() / 255.0,
color.a,
)
}
///|
fn push_color_vertex2d(
vertices : Array[Double],
x : Double,
y : Double,
r : Double,
g : Double,
b : Double,
a : Double,
) -> Unit {
vertices.push(x)
vertices.push(y)
vertices.push(r)
vertices.push(g)
vertices.push(b)
vertices.push(a)
}
///|
fn push_tex_vertex2d(
vertices : Array[Double],
x : Double,
y : Double,
u : Double,
v : Double,
r : Double,
g : Double,
b : Double,
a : Double,
) -> Unit {
vertices.push(x)
vertices.push(y)
vertices.push(u)
vertices.push(v)
vertices.push(r)
vertices.push(g)
vertices.push(b)
vertices.push(a)
}