Primitive border drawing and rounded corners

This commit is contained in:
David Gonzalez Martin 2024-12-24 18:56:25 -06:00 committed by David
parent b063d570b1
commit 9dec588ec1
17 changed files with 262 additions and 246 deletions

View File

@ -56,43 +56,28 @@ typedef enum Corner
CORNER_COUNT, CORNER_COUNT,
} Corner; } Corner;
STRUCT(U32Vec2) typedef float float2 __attribute__((ext_vector_type(2)));
{ typedef float float3 __attribute__((ext_vector_type(3)));
struct typedef float float4 __attribute__((ext_vector_type(4)));
{ typedef float2 vec2;
u32 x; typedef float3 vec3;
u32 y; typedef float4 vec4;
};
u32 v[2];
};
STRUCT(F32Vec4) typedef u32 uint2 __attribute__((ext_vector_type(2)));
{ typedef u32 uint3 __attribute__((ext_vector_type(3)));
f32 v[4]; typedef u32 uint4 __attribute__((ext_vector_type(4)));
};
typedef F32Vec4 Color;
UNION(F32Vec2)
{
struct
{
f32 x;
f32 y;
};
f32 v[2];
};
UNION(F32Interval2) UNION(F32Interval2)
{ {
struct struct
{ {
F32Vec2 min; float2 min;
F32Vec2 max; float2 max;
}; };
struct struct
{ {
F32Vec2 p0; float2 p0;
F32Vec2 p1; float2 p1;
}; };
struct struct
{ {
@ -101,9 +86,11 @@ UNION(F32Interval2)
f32 x1; f32 x1;
f32 y1; f32 y1;
}; };
F32Vec2 v[2]; float2 v[2];
}; };
static_assert(sizeof(F32Interval2) == 4 * sizeof(f32));
typedef enum Axis2 typedef enum Axis2
{ {
AXIS2_X, AXIS2_X,

View File

@ -37,4 +37,4 @@ STRUCT(TextureAtlasCreate)
#include <std/render.h> #include <std/render.h>
EXPORT TextureAtlas font_texture_atlas_create(Arena* arena, Renderer* renderer, TextureAtlasCreate create); EXPORT TextureAtlas font_texture_atlas_create(Arena* arena, Renderer* renderer, TextureAtlasCreate create);
EXPORT U32Vec2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas); EXPORT uint2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas);

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <std/base.h> #include <std/base.h>
typedef struct Renderer Renderer; typedef struct Renderer Renderer;
@ -11,41 +10,18 @@ typedef struct Renderer Renderer;
typedef struct RenderWindow RenderWindow; typedef struct RenderWindow RenderWindow;
typedef struct Pipeline Pipeline; typedef struct Pipeline Pipeline;
STRUCT(RenderRect)
{
u32 x0;
u32 y0;
u32 x1;
u32 y1;
};
STRUCT(RectColors)
{
F32Vec4 v[4];
};
STRUCT(RectDraw) STRUCT(RectDraw)
{ {
RenderRect vertex; F32Interval2 vertex;
RenderRect texture; F32Interval2 texture;
RectColors colors; vec4 colors[4];
u32 texture_index; u32 texture_index;
}; };
STRUCT(RectVertex) #include "../std/shaders/rect.inc"
{ typedef struct RectVertex RectVertex;
f32 x;
f32 y;
f32 uv_x;
f32 uv_y;
RectColors colors;
u32 texture_index;
u32 reserved[3];
};
decl_vb(RectVertex); decl_vb(RectVertex);
#define Color4(r, g, b, a) ((F32Vec4){ .v = { r, g, b, a } })
typedef enum BBPipeline typedef enum BBPipeline
{ {
BB_PIPELINE_RECT, BB_PIPELINE_RECT,
@ -187,7 +163,7 @@ EXPORT PipelineLayoutIndex renderer_pipeline_get_layout(PipelineIndex pipeline);
EXPORT void renderer_window_frame_begin(Renderer* renderer, RenderWindow* window); EXPORT void renderer_window_frame_begin(Renderer* renderer, RenderWindow* window);
EXPORT void renderer_window_frame_end(Renderer* renderer, RenderWindow* window); EXPORT void renderer_window_frame_end(Renderer* renderer, RenderWindow* window);
EXPORT TextureIndex renderer_texture_create(Renderer* renderer, TextureMemory texture_memory); EXPORT TextureIndex renderer_texture_create(Renderer* renderer, TextureMemory texture_memory);
EXPORT U32Vec2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string); EXPORT uint2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string);
EXPORT void window_command_begin(RenderWindow* window); EXPORT void window_command_begin(RenderWindow* window);
EXPORT void window_command_end(RenderWindow* window); EXPORT void window_command_end(RenderWindow* window);
EXPORT void window_render_begin(RenderWindow* window); EXPORT void window_render_begin(RenderWindow* window);
@ -203,4 +179,4 @@ EXPORT void window_rect_texture_update_end(Renderer* renderer, RenderWindow* win
EXPORT u32 window_pipeline_add_vertices(RenderWindow* window, BBPipeline pipeline_index, String vertex_memory, u32 vertex_count); EXPORT u32 window_pipeline_add_vertices(RenderWindow* window, BBPipeline pipeline_index, String vertex_memory, u32 vertex_count);
EXPORT void window_pipeline_add_indices(RenderWindow* window, BBPipeline pipeline_index, Slice(u32) indices); EXPORT void window_pipeline_add_indices(RenderWindow* window, BBPipeline pipeline_index, Slice(u32) indices);
EXPORT void window_render_rect(RenderWindow* window, RectDraw draw); EXPORT void window_render_rect(RenderWindow* window, RectDraw draw);
EXPORT void window_render_text(Renderer* renderer, RenderWindow* window, String string, Color color, RenderFontType font_type, u32 x_offset, u32 y_offset); EXPORT void window_render_text(Renderer* renderer, RenderWindow* window, String string, float4 color, RenderFontType font_type, u32 x_offset, u32 y_offset);

View File

@ -87,19 +87,19 @@ STRUCT(UI_Widget)
UI_WidgetFlags flags; UI_WidgetFlags flags;
// Data known after size determination happens // Data known after size determination happens
F32Vec2 computed_size; float2 computed_size;
F32Vec2 computed_relative_position; float2 computed_relative_position;
// Data known after layout computation happens // Data known after layout computation happens
F32Interval2 relative_rect; F32Interval2 relative_rect;
F32Interval2 rect; F32Interval2 rect;
F32Vec2 relative_corner_delta[CORNER_COUNT]; float2 relative_corner_delta[CORNER_COUNT];
// Persistent data across frames // Persistent data across frames
u64 last_build_touched; u64 last_build_touched;
F32Vec2 view_offset; float2 view_offset;
Color background_color; float4 background_color;
Color text_color; float4 text_color;
}; };
decl_vbp(UI_Widget); decl_vbp(UI_Widget);
@ -111,7 +111,7 @@ STRUCT(UI_WidgetSlot)
declare_slice(UI_WidgetSlot); declare_slice(UI_WidgetSlot);
decl_vb(Axis2); decl_vb(Axis2);
decl_vb(Color); decl_vb(float4);
STRUCT(UI_StateStackAutoPops) STRUCT(UI_StateStackAutoPops)
{ {
@ -131,8 +131,8 @@ STRUCT(UI_StateStackNulls)
UI_Size pref_width; UI_Size pref_width;
UI_Size pref_height; UI_Size pref_height;
Axis2 child_layout_axis; Axis2 child_layout_axis;
Color text_color; float4 text_color;
Color background_color; float4 background_color;
f32 font_size; f32 font_size;
}; };
@ -142,8 +142,8 @@ STRUCT(UI_StateStacks)
VirtualBuffer(UI_Size) pref_width; VirtualBuffer(UI_Size) pref_width;
VirtualBuffer(UI_Size) pref_height; VirtualBuffer(UI_Size) pref_height;
VirtualBuffer(Axis2) child_layout_axis; VirtualBuffer(Axis2) child_layout_axis;
VirtualBuffer(Color) text_color; VirtualBuffer(float4) text_color;
VirtualBuffer(Color) background_color; VirtualBuffer(float4) background_color;
VirtualBuffer(f32) font_size; VirtualBuffer(f32) font_size;
}; };

View File

@ -1,21 +0,0 @@
#version 450
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_EXT_debug_printf : require
#extension GL_GOOGLE_include_directive : require
#include "rect.h"
layout (location = 0) in flat uint texture_index;
layout (location = 1) in FragmentShaderInput inputs;
layout (location = 0) out vec4 color;
layout(set = 0, binding = 0) uniform sampler2D textures[];
void main()
{
vec2 texture_size = textureSize(textures[nonuniformEXT(texture_index)], 0);
vec2 uv = vec2(inputs.uv.x / texture_size.x, inputs.uv.y / texture_size.y);
vec4 sampled = texture(textures[nonuniformEXT(texture_index)], uv);
color = inputs.color * sampled;
}

View File

@ -1,5 +0,0 @@
struct FragmentShaderInput
{
vec4 color;
vec2 uv;
};

View File

@ -1,47 +0,0 @@
#version 450
#extension GL_EXT_buffer_reference : require
#extension GL_EXT_debug_printf : require
#extension GL_GOOGLE_include_directive : require
#include "rect.h"
layout (location = 0) out uint texture_index;
layout (location = 1) out FragmentShaderInput outputs;
struct Vertex {
float x;
float y;
float uv_x;
float uv_y;
vec4 colors[4];
uint texture_index;
uint r[3];
};
layout(buffer_reference, std430) readonly buffer VertexBuffer{
Vertex vertices[];
};
//push constants block
layout(push_constant) uniform constants
{
VertexBuffer vertex_buffer;
float width;
float height;
} PushConstants;
void main()
{
Vertex v = PushConstants.vertex_buffer.vertices[gl_VertexIndex];
float width = PushConstants.width;
float height = PushConstants.height;
gl_Position = vec4(2 * v.x / width - 1, 2 * v.y / height - 1, 0, 1);
outputs.uv = vec2(v.uv_x, v.uv_y);
outputs.color = v.colors[gl_VertexIndex % 4];
texture_index = v.texture_index;
//debugPrintfEXT("Vertex index: (%u)\n", gl_VertexIndex);
//debugPrintfEXT("UV: (%f, %f)\n", v.uv_x, v.uv_y);
}

View File

@ -108,7 +108,7 @@ TextureAtlas font_texture_atlas_create(Arena* arena, Renderer* renderer, Texture
return result; return result;
} }
U32Vec2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas) uint2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atlas)
{ {
auto height = atlas->ascent - atlas->descent; auto height = atlas->ascent - atlas->descent;
u32 x_offset = 0; u32 x_offset = 0;
@ -122,5 +122,5 @@ U32Vec2 texture_atlas_compute_string_rect(String string, const TextureAtlas* atl
x_offset += character->advance + kerning; x_offset += character->advance + kerning;
} }
return (U32Vec2) { .x = x_offset, .y = y_offset }; return (uint2) { x_offset, y_offset };
} }

View File

@ -7,7 +7,6 @@
#include <stb_image.h> #include <stb_image.h>
#pragma clang diagnostic pop #pragma clang diagnostic pop
EXPORT TextureMemory texture_load_from_file(Arena* arena, String path) EXPORT TextureMemory texture_load_from_file(Arena* arena, String path)
{ {
auto file = file_read(arena, path); auto file = file_read(arena, path);

View File

@ -313,11 +313,15 @@ void buffer_copy_to_host(VulkanBuffer buffer, Slice(HostBufferCopy) regions)
auto region = regions.pointer[i]; auto region = regions.pointer[i];
auto* destination = buffer_pointer + region.destination_offset; auto* destination = buffer_pointer + region.destination_offset;
assert(destination + region.source.length <= (u8*)buffer.address + buffer.size); assert(destination + region.source.length <= (u8*)buffer.address + buffer.size);
#define USE_MEMCPY 1
#if USE_MEMCPY
memcpy(destination, region.source.pointer, region.source.length);
#else
for (u64 i = 0; i < region.source.length; i += 1) for (u64 i = 0; i < region.source.length; i += 1)
{ {
destination[i] = region.source.pointer[i]; destination[i] = region.source.pointer[i];
} }
// memcpy(destination, region.source.pointer, region.source.length); #endif
} }
} }
@ -1095,8 +1099,8 @@ Renderer* renderer_initialize(Arena* arena)
} }
String shader_source_paths[] = { String shader_source_paths[] = {
strlit("bootstrap/shaders/rect.vert"), strlit("bootstrap/std/shaders/rect.vert"),
strlit("bootstrap/shaders/rect.frag"), strlit("bootstrap/std/shaders/rect.frag"),
}; };
PipelineLayoutCreate pipeline_layouts[] = { PipelineLayoutCreate pipeline_layouts[] = {
@ -2201,38 +2205,53 @@ void window_pipeline_add_indices(RenderWindow* window, BBPipeline pipeline_index
void window_render_rect(RenderWindow* window, RectDraw draw) void window_render_rect(RenderWindow* window, RectDraw draw)
{ {
auto p0 = draw.vertex.p0;
auto uv0 = draw.texture.p0;
if (draw.texture.p1.x != 0)
{
assert(draw.texture.p1.x - draw.texture.p0.x == draw.vertex.p1.x - draw.vertex.p0.x);
assert(draw.texture.p1.y - draw.texture.p0.y == draw.vertex.p1.y - draw.vertex.p0.y);
}
auto corner_radius = 10.0f;
auto extent = draw.vertex.p1 - p0;
RectVertex vertices[] = { RectVertex vertices[] = {
(RectVertex) { (RectVertex) {
.x = draw.vertex.x0, .p0 = p0,
.y = draw.vertex.y0, .uv0 = uv0,
.uv_x = draw.texture.x0, .extent = extent,
.uv_y = draw.texture.y0,
.colors = draw.colors,
.texture_index = draw.texture_index, .texture_index = draw.texture_index,
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
.softness = 1.0,
.corner_radius = corner_radius,
}, },
(RectVertex) { (RectVertex) {
.x = draw.vertex.x1, .p0 = p0,
.y = draw.vertex.y0, .uv0 = uv0,
.uv_x = draw.texture.x1, .extent = extent,
.uv_y = draw.texture.y0,
.colors = draw.colors,
.texture_index = draw.texture_index, .texture_index = draw.texture_index,
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
.softness = 1.0,
.corner_radius = corner_radius,
}, },
(RectVertex) { (RectVertex) {
.x = draw.vertex.x0, .p0 = p0,
.y = draw.vertex.y1, .uv0 = uv0,
.uv_x = draw.texture.x0, .extent = extent,
.uv_y = draw.texture.y1,
.colors = draw.colors,
.texture_index = draw.texture_index, .texture_index = draw.texture_index,
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
.softness = 1.0,
.corner_radius = corner_radius,
}, },
(RectVertex) { (RectVertex) {
.x = draw.vertex.x1, .p0 = p0,
.y = draw.vertex.y1, .uv0 = uv0,
.uv_x = draw.texture.x1, .extent = extent,
.uv_y = draw.texture.y1,
.colors = draw.colors,
.texture_index = draw.texture_index, .texture_index = draw.texture_index,
.colors = { draw.colors[0], draw.colors[1], draw.colors[2], draw.colors[3] },
.softness = 1.0,
.corner_radius = corner_radius,
}, },
}; };
@ -2250,63 +2269,63 @@ void window_render_rect(RenderWindow* window, RectDraw draw)
window_pipeline_add_indices(window, BB_PIPELINE_RECT, (Slice(u32))array_to_slice(indices)); window_pipeline_add_indices(window, BB_PIPELINE_RECT, (Slice(u32))array_to_slice(indices));
} }
void window_render_text(Renderer* renderer, RenderWindow* window, String string, Color color, RenderFontType font_type, u32 x_offset, u32 y_offset) // TODO: support gradient
void window_render_text(Renderer* renderer, RenderWindow* window, String string, float4 color, RenderFontType font_type, u32 x_offset, u32 y_offset)
{ {
auto* texture_atlas = &renderer->fonts[font_type]; auto* texture_atlas = &renderer->fonts[font_type];
auto height = texture_atlas->ascent - texture_atlas->descent; auto height = texture_atlas->ascent - texture_atlas->descent;
auto texture_index = texture_atlas->texture.value; auto texture_index = texture_atlas->texture.value;
// TODO: support gradient
RectColors colors = {
.v = { color, color, color, color }
};
for (u64 i = 0; i < string.length; i += 1) for (u64 i = 0; i < string.length; i += 1)
{ {
auto ch = string.pointer[i]; auto ch = string.pointer[i];
auto* character = &texture_atlas->characters[ch]; auto* character = &texture_atlas->characters[ch];
auto pos_x = x_offset;
auto pos_y = y_offset + character->y_offset + height + texture_atlas->descent; // Offset of the height to render the character from the bottom (y + height) up (y)
//
auto uv_x = character->x; auto uv_x = character->x;
auto uv_y = character->y; auto uv_y = character->y;
auto uv_width = character->width; auto char_width = character->width;
auto uv_height = character->height; auto char_height = character->height;
auto pos_x = x_offset;
auto pos_y = y_offset + character->y_offset + height + texture_atlas->descent; // Offset of the height to render the character from the bottom (y + height) up (y)
vec2 p0 = { pos_x, pos_y };
vec2 uv0 = { uv_x, uv_y };
vec2 extent = { char_width, char_height };
// print("P0: ({u32}, {u32}). P1: ({u32}, {u32})\n", (u32)p0.x, (u32)p0.y, (u32)p1.x, (u32)p1.y);
RectVertex vertices[] = { RectVertex vertices[] = {
(RectVertex) { (RectVertex) {
.x = pos_x, .p0 = p0,
.y = pos_y, .uv0 = uv0,
.uv_x = (f32)uv_x, .extent = extent,
.uv_y = (f32)uv_y,
.colors = colors,
.texture_index = texture_index, .texture_index = texture_index,
.colors = { color, color, color, color },
.softness = 1.0,
}, },
(RectVertex) { (RectVertex) {
.x = pos_x + character->width, .p0 = p0,
.y = pos_y, .uv0 = uv0,
.uv_x = (f32)(uv_x + uv_width), .extent = extent,
.uv_y = (f32)uv_y,
.colors = colors,
.texture_index = texture_index, .texture_index = texture_index,
.colors = { color, color, color, color },
.softness = 1.0,
}, },
(RectVertex) { (RectVertex) {
.x = pos_x, .p0 = p0,
.y = pos_y + character->height, .uv0 = uv0,
.uv_x = (f32)uv_x, .extent = extent,
.uv_y = (f32)(uv_y + uv_height),
.colors = colors,
.texture_index = texture_index, .texture_index = texture_index,
.colors = { color, color, color, color },
.softness = 1.0,
}, },
(RectVertex) { (RectVertex) {
.x = pos_x + character->width, .p0 = p0,
.y = pos_y + character->height, .uv0 = uv0,
.uv_x = (f32)(uv_x + uv_width), .extent = extent,
.uv_y = (f32)(uv_y + uv_height), .colors = { color, color, color, color },
.colors = colors,
.texture_index = texture_index, .texture_index = texture_index,
.softness = 1.0,
}, },
}; };
@ -2328,7 +2347,7 @@ void window_render_text(Renderer* renderer, RenderWindow* window, String string,
} }
} }
U32Vec2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string) uint2 renderer_font_compute_string_rect(Renderer* renderer, RenderFontType type, String string)
{ {
auto* texture_atlas = &renderer->fonts[type]; auto* texture_atlas = &renderer->fonts[type];
auto result = texture_atlas_compute_string_rect(string, texture_atlas); auto result = texture_atlas_compute_string_rect(string, texture_atlas);

View File

@ -89,7 +89,6 @@ fn SpirVBinary compileShaderToSPIRV_Vulkan(Arena* arena, glslang_stage_t stage,
String compile_shader(Arena* arena, String path, ShaderStage shader_stage) String compile_shader(Arena* arena, String path, ShaderStage shader_stage)
{ {
print("Compile shader\n");
#if SHADER_COMPILATION_USE_SOURCE #if SHADER_COMPILATION_USE_SOURCE
auto file = file_read(arena, path); auto file = file_read(arena, path);

View File

@ -0,0 +1,35 @@
#version 450
#extension GL_EXT_nonuniform_qualifier : require
#extension GL_EXT_debug_printf : require
#extension GL_GOOGLE_include_directive : require
#include "rect.inc"
layout (location = 0) in flat uint texture_index;
layout (location = 1) in RectFragmentShaderInput inputs;
layout (location = 0) out vec4 color;
layout(set = 0, binding = 0) uniform sampler2D textures[];
float rounded_rect_sdf(vec2 position, vec2 center, vec2 half_size, float radius)
{
vec2 d2 = abs(center - position) - half_size + vec2(radius, radius);
float result = min(max(d2.x, d2.y), 0.0) + length(max(d2, 0.0)) - radius;
return result;
}
void main()
{
uint sampler_index = nonuniformEXT(texture_index);
vec2 texture_size = textureSize(textures[sampler_index], 0);
vec2 uv = vec2(inputs.uv.x / texture_size.x, inputs.uv.y / texture_size.y);
vec4 sampled = texture(textures[sampler_index], uv);
float softness = inputs.softness;
float softness_padding_scalar = max(0, softness * 2 - 1);
vec2 softness_padding = vec2(softness_padding_scalar, softness_padding_scalar);
float distance = rounded_rect_sdf(inputs.position, inputs.center, inputs.half_size - softness_padding, inputs.corner_radius);
float sdf_factor = 1.0 - smoothstep(0, 2 * softness, distance);
color = inputs.color * sampled * sdf_factor;
}

View File

@ -0,0 +1,22 @@
struct RectVertex
{
vec2 p0;
vec2 uv0;
vec2 extent;
float corner_radius;
float softness;
vec4 colors[4];
uint texture_index;
uint reserved[3];
};
struct RectFragmentShaderInput
{
vec4 color;
vec2 uv;
vec2 position;
vec2 center;
vec2 half_size;
float corner_radius;
float softness;
};

View File

@ -0,0 +1,61 @@
#version 450
#extension GL_EXT_buffer_reference : require
#extension GL_EXT_debug_printf : require
#extension GL_GOOGLE_include_directive : require
#include "rect.inc"
layout (location = 0) out uint texture_index;
layout (location = 1) out RectFragmentShaderInput outputs;
layout(buffer_reference, std430) readonly buffer VertexBuffer{
RectVertex vertices[];
};
layout(push_constant) uniform constants
{
VertexBuffer vertex_buffer;
float width;
float height;
} PushConstants;
const vec2 vertices[] = {
{ -1, -1 },
{ +1, -1 },
{ -1, +1 },
{ +1, +1 },
};
void main()
{
RectVertex v = PushConstants.vertex_buffer.vertices[gl_VertexIndex];
uint vertex_id = gl_VertexIndex % 4;
float width = PushConstants.width;
float height = PushConstants.height;
vec2 extent = v.extent;
vec2 p0 = v.p0;
vec2 p1 = p0 + extent;
vec2 position_center = (p1 + p0) / 2;
vec2 half_size = (p1 - p0) / 2;
vec2 position = vertices[vertex_id] * half_size + position_center;
//debugPrintfEXT("Vertex index: (%u). P0: (%f, %f). P1: (%f, %f). Center: (%f, %f). Half size: (%f, %f). Position: (%f, %f)\n", gl_VertexIndex, p0.x, p0.y, p1.x, p1.y, center.x, center.y, half_size.x, half_size.y, position.x, position.y);
gl_Position = vec4(2 * position.x / width - 1, 2 * position.y / height - 1, 0, 1);
vec2 uv0 = v.uv0;
vec2 uv1 = uv0 + extent;
vec2 texture_center = (uv1 + uv0) / 2;
vec2 uv = vertices[vertex_id] * half_size + texture_center;
texture_index = v.texture_index;
outputs.color = v.colors[vertex_id];
outputs.uv = uv;
outputs.position = position;
outputs.center = position_center;
outputs.half_size = half_size;
outputs.corner_radius = v.corner_radius;
outputs.softness = v.softness;
}

View File

@ -248,8 +248,8 @@ UI_Widget* ui_widget_make_from_key(UI_WidgetFlags flags, UI_Key key)
auto color = count % 3 == 0; auto color = count % 3 == 0;
widget->key = key; widget->key = key;
widget->background_color = Color4(color, color, color, 1); widget->background_color = (float4) { color, color, color, 1 };
widget->text_color = Color4(!color, !color, !color, 1); widget->text_color = (float4) { !color, !color, !color, 1 };
widget->flags = flags; widget->flags = flags;
widget->first = 0; widget->first = 0;
widget->last = 0; widget->last = 0;
@ -462,8 +462,8 @@ u8 ui_build_begin(OSWindow os_window, f64 frame_time, OSEventQueue* event_queue)
ui_push(parent, root); ui_push(parent, root);
ui_push(font_size, 12); ui_push(font_size, 12);
ui_push(text_color, Color4(1, 1, 1, 1)); ui_push(text_color, ((float4) { 1, 1, 1, 1 }));
ui_push(background_color, Color4(0, 0, 0, 1)); ui_push(background_color, ((float4) { 0, 0, 0, 1 }));
ui_push(pref_width, ui_percentage(1.0, 0.0)); ui_push(pref_width, ui_percentage(1.0, 0.0));
ui_push(pref_height, ui_percentage(1.0, 0.0)); ui_push(pref_height, ui_percentage(1.0, 0.0));
// ui_push(pref_height, ui_em(1.8, 0.0)); // ui_push(pref_height, ui_em(1.8, 0.0));
@ -482,7 +482,7 @@ fn void ui_compute_independent_sizes(UI_Widget* widget)
default: break; case UI_SIZE_COUNT: unreachable(); default: break; case UI_SIZE_COUNT: unreachable();
case UI_SIZE_PIXEL_COUNT: case UI_SIZE_PIXEL_COUNT:
{ {
widget->computed_size.v[axis] = floorf(widget->pref_size[axis].value); widget->computed_size[axis] = floorf(widget->pref_size[axis].value);
} break; } break;
} }
} }
@ -508,7 +508,7 @@ fn void ui_compute_upward_dependent_sizes(UI_Widget* widget)
{ {
if (ancestor->pref_size[axis].kind != UI_SIZE_BY_CHILDREN) if (ancestor->pref_size[axis].kind != UI_SIZE_BY_CHILDREN)
{ {
widget->computed_size.v[axis] = floorf(ancestor->computed_size.v[axis] * widget->pref_size[axis].value); widget->computed_size[axis] = floorf(ancestor->computed_size[axis] * widget->pref_size[axis].value);
break; break;
} }
} }
@ -547,7 +547,7 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
{ {
for (Axis2 axis = 0; axis < AXIS2_COUNT; axis += 1) for (Axis2 axis = 0; axis < AXIS2_COUNT; axis += 1)
{ {
auto available_space = widget->computed_size.v[axis]; auto available_space = widget->computed_size[axis];
f32 taken_space = 0; f32 taken_space = 0;
f32 total_fixup_budget = 0; f32 total_fixup_budget = 0;
@ -559,13 +559,13 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
{ {
if (axis == widget->child_layout_axis) if (axis == widget->child_layout_axis)
{ {
taken_space += child_widget->computed_size.v[axis]; taken_space += child_widget->computed_size[axis];
} }
else else
{ {
taken_space = MAX(taken_space, child_widget->computed_size.v[axis]); taken_space = MAX(taken_space, child_widget->computed_size[axis]);
} }
auto fixup_budget_this_child = child_widget->computed_size.v[axis] * (1 - child_widget->pref_size[axis].strictness); auto fixup_budget_this_child = child_widget->computed_size[axis] * (1 - child_widget->pref_size[axis].strictness);
total_fixup_budget += fixup_budget_this_child; total_fixup_budget += fixup_budget_this_child;
} }
} }
@ -578,7 +578,7 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
{ {
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis))) if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
{ {
auto fixup_budget_this_child = child_widget->computed_size.v[axis] * (1 - child_widget->pref_size[axis].strictness); auto fixup_budget_this_child = child_widget->computed_size[axis] * (1 - child_widget->pref_size[axis].strictness);
f32 fixup_size_this_child = 0; f32 fixup_size_this_child = 0;
if (axis == widget->child_layout_axis) if (axis == widget->child_layout_axis)
@ -587,11 +587,11 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
} }
else else
{ {
fixup_size_this_child = child_widget->computed_size.v[axis] - available_space; fixup_size_this_child = child_widget->computed_size[axis] - available_space;
} }
fixup_size_this_child = CLAMP(0, fixup_size_this_child, fixup_budget_this_child); fixup_size_this_child = CLAMP(0, fixup_size_this_child, fixup_budget_this_child);
child_widget->computed_size.v[axis] = floorf(child_widget->computed_size.v[axis] - fixup_size_this_child); child_widget->computed_size[axis] = floorf(child_widget->computed_size[axis] - fixup_size_this_child);
} }
} }
} }
@ -605,8 +605,8 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
{ {
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis))) if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
{ {
child_widget->computed_relative_position.v[axis] = p; child_widget->computed_relative_position[axis] = p;
p += child_widget->computed_size.v[axis]; p += child_widget->computed_size[axis];
} }
} }
} }
@ -616,7 +616,7 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
{ {
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis))) if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
{ {
child_widget->computed_relative_position.v[axis] = 0; child_widget->computed_relative_position[axis] = 0;
} }
} }
} }
@ -624,26 +624,26 @@ fn void ui_resolve_conflicts(UI_Widget* widget)
for (UI_Widget* child_widget = widget->first; child_widget; child_widget = child_widget->next) for (UI_Widget* child_widget = widget->first; child_widget; child_widget = child_widget->next)
{ {
auto last_relative_rect = child_widget->relative_rect; auto last_relative_rect = child_widget->relative_rect;
child_widget->relative_rect.p0.v[axis] = child_widget->computed_relative_position.v[axis]; child_widget->relative_rect.p0[axis] = child_widget->computed_relative_position[axis];
child_widget->relative_rect.p1.v[axis] = child_widget->relative_rect.p0.v[axis] + child_widget->computed_size.v[axis]; child_widget->relative_rect.p1[axis] = child_widget->relative_rect.p0[axis] + child_widget->computed_size[axis];
F32Vec2 last_corner_01 = { .x = last_relative_rect.x0, .y = last_relative_rect.y1 }; float2 last_corner_01 = { last_relative_rect.x0, last_relative_rect.y1 };
F32Vec2 last_corner_10 = { .x = last_relative_rect.x1, .y = last_relative_rect.y0 }; float2 last_corner_10 = { last_relative_rect.x1, last_relative_rect.y0 };
F32Vec2 this_corner_01 = { .x = child_widget->relative_rect.x0, .y = child_widget->relative_rect.y1 }; float2 this_corner_01 = { child_widget->relative_rect.x0, child_widget->relative_rect.y1 };
F32Vec2 this_corner_10 = { .x = child_widget->relative_rect.x1, .y = child_widget->relative_rect.y0 }; float2 this_corner_10 = { child_widget->relative_rect.x1, child_widget->relative_rect.y0 };
child_widget->relative_corner_delta[CORNER_00].v[axis] = child_widget->relative_rect.p0.v[axis] - last_relative_rect.p0.v[axis]; child_widget->relative_corner_delta[CORNER_00][axis] = child_widget->relative_rect.p0[axis] - last_relative_rect.p0[axis];
child_widget->relative_corner_delta[CORNER_01].v[axis] = this_corner_01.v[axis] - last_corner_01.v[axis]; child_widget->relative_corner_delta[CORNER_01][axis] = this_corner_01[axis] - last_corner_01[axis];
child_widget->relative_corner_delta[CORNER_10].v[axis] = this_corner_10.v[axis] - last_corner_10.v[axis]; child_widget->relative_corner_delta[CORNER_10][axis] = this_corner_10[axis] - last_corner_10[axis];
child_widget->relative_corner_delta[CORNER_11].v[axis] = child_widget->relative_rect.p1.v[axis] - last_relative_rect.p1.v[axis]; child_widget->relative_corner_delta[CORNER_11][axis] = child_widget->relative_rect.p1[axis] - last_relative_rect.p1[axis];
child_widget->rect.p0.v[axis] = widget->rect.p0.v[axis] + child_widget->relative_rect.p0.v[axis] - widget->view_offset.v[axis]; child_widget->rect.p0[axis] = widget->rect.p0[axis] + child_widget->relative_rect.p0[axis] - widget->view_offset[axis];
child_widget->rect.p1.v[axis] = child_widget->rect.p0.v[axis] + child_widget->computed_size.v[axis]; child_widget->rect.p1[axis] = child_widget->rect.p0[axis] + child_widget->computed_size[axis];
if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis))) if (!(child_widget->flags.v & (UI_WIDGET_FLAG_FLOATING_X << axis)))
{ {
child_widget->rect.p0.v[axis] = floorf(child_widget->rect.p0.v[axis]); child_widget->rect.p0[axis] = floorf(child_widget->rect.p0[axis]);
child_widget->rect.p1.v[axis] = floorf(child_widget->rect.p1.v[axis]); child_widget->rect.p1[axis] = floorf(child_widget->rect.p1[axis]);
} }
} }
@ -674,16 +674,6 @@ void ui_build_end()
ui_resolve_conflicts(ui_state->root); ui_resolve_conflicts(ui_state->root);
} }
fn RenderRect render_rect(F32Interval2 rect)
{
return (RenderRect) {
.x0 = rect.x0,
.y0 = rect.y0,
.x1 = rect.x1,
.y1 = rect.y1,
};
}
STRUCT(WidgetIterator) STRUCT(WidgetIterator)
{ {
UI_Widget* next; UI_Widget* next;
@ -734,8 +724,8 @@ void ui_draw()
if (widget->flags.draw_background) if (widget->flags.draw_background)
{ {
window_render_rect(window, (RectDraw) { window_render_rect(window, (RectDraw) {
.colors = (RectColors) { .v = { Color4(1, 1, 1, 1), Color4(1, 1, 1, 1), widget->background_color, widget->background_color } }, .colors = { (float4) {1, 1, 1, 1 }, (float4) {1, 1, 1, 1}, widget->background_color, widget->background_color },
.vertex = render_rect(widget->rect), .vertex = widget->rect,
}); });
} }

View File

@ -105,6 +105,7 @@ cmake . \
$CXX_COMPILER_OPT_ARG \ $CXX_COMPILER_OPT_ARG \
$ASM_COMPILER_OPT_ARG $ASM_COMPILER_OPT_ARG
export VK_LAYER_PRINTF_BUFFER_SIZE=1000000
cd $BUILD_DIR cd $BUILD_DIR
ninja -v ninja -v
cd $ORIGINAL_DIR/build cd $ORIGINAL_DIR/build