diff --git a/lib/ugui.c3l/src/widgets/button.c3 b/lib/ugui.c3l/src/widgets/button.c3 index eeb1484..b671620 100644 --- a/lib/ugui.c3l/src/widgets/button.c3 +++ b/lib/ugui.c3l/src/widgets/button.c3 @@ -145,7 +145,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t if (*active) { Sprite* sprite = ctx.sprite_atlas.get(tick_sprite)!; Id tex_id = ctx.sprite_atlas.id; - ctx.push_sprite(sprite.rect().center_to(check_bounds), sprite.uv(), tex_id, parent.z_index, type: sprite.type)!; + ctx.push_sprite(check_bounds, sprite.uv(), tex_id, parent.z_index, type: sprite.type)!; } } else { if (*active) { diff --git a/lib/ugui.c3l/src/widgets/sprite.c3 b/lib/ugui.c3l/src/widgets/sprite.c3 index ab54dc3..ab15797 100644 --- a/lib/ugui.c3l/src/widgets/sprite.c3 +++ b/lib/ugui.c3l/src/widgets/sprite.c3 @@ -4,9 +4,9 @@ struct ElemSprite { Id id; } -macro Ctx.sprite(&ctx, String name, ...) - => ctx.sprite_id(@compute_id($vasplat), name); -fn void? Ctx.sprite_id(&ctx, Id id, String name) +macro Ctx.sprite(&ctx, String name, short size = 0, ...) + => ctx.sprite_id(@compute_id($vasplat), name, size); +fn void? Ctx.sprite_id(&ctx, Id id, String name, short size = 0) { id = ctx.gen_id(id)!; Elem* parent, elem; @@ -16,11 +16,26 @@ fn void? Ctx.sprite_id(&ctx, Id id, String name) Sprite* sprite = ctx.sprite_atlas.get(name)!; elem.sprite.id = ctx.get_sprite_atlas_id(name); - elem.layout.w = elem.layout.children.w = @exact(sprite.w); - elem.layout.h = elem.layout.children.h = @exact(sprite.h); + // scale the sprite so that the biggest dimension becomes "size" + short width = sprite.w; + short height = sprite.h; + if (size > 0) { + if (sprite.w >= sprite.h) { + width = size; + height = (short)(size * (float)height/width); + } else { + width = (short)(size * (float)width/height); + height = size; + } + } + + elem.layout.w = elem.layout.children.w = @exact(width); + elem.layout.h = elem.layout.children.h = @exact(height); + elem.layout.content_offset = style.margin + style.border + style.padding; update_parent_size(elem, parent); Id tex_id = ctx.sprite_atlas.id; - return ctx.push_sprite(elem.bounds, sprite.uv(), tex_id, parent.z_index, type: sprite.type)!; + Rect content_bounds = elem.bounds.pad(elem.layout.content_offset); + return ctx.push_sprite(content_bounds, sprite.uv(), tex_id, parent.z_index, type: sprite.type)!; } diff --git a/resources/shaders/source/ugui.frag.glsl b/resources/shaders/source/ugui.frag.glsl index a5b6a50..2618c2e 100644 --- a/resources/shaders/source/ugui.frag.glsl +++ b/resources/shaders/source/ugui.frag.glsl @@ -64,7 +64,7 @@ void sprite_main() { ivec2 ts = textureSize(sprite_atlas, 0); vec2 fts = vec2(ts); - vec2 real_uv = in_uv / fts; + vec2 real_uv = in_uv.xy / fts; fragColor = texture(sprite_atlas, real_uv); } @@ -74,7 +74,7 @@ void font_main() { ivec2 ts = textureSize(font_atlas, 0); vec2 fts = vec2(ts); - vec2 real_uv = in_uv / fts; + vec2 real_uv = in_uv.xy / fts; vec4 opacity = texture(font_atlas, real_uv); fragColor = vec4(in_color.rgb, in_color.a*opacity.r); @@ -85,7 +85,7 @@ void font_main() void msdf_main() { ivec2 ts = textureSize(sprite_atlas, 0); vec2 fts = vec2(ts); - vec2 real_uv = in_uv / fts; + vec2 real_uv = in_uv.xy / fts; vec3 msd = texture(sprite_atlas, real_uv).rgb; float sd = median(msd.r, msd.g, msd.b); diff --git a/resources/shaders/source/ugui.vert.glsl b/resources/shaders/source/ugui.vert.glsl index ae78ec8..ee29724 100644 --- a/resources/shaders/source/ugui.vert.glsl +++ b/resources/shaders/source/ugui.vert.glsl @@ -10,7 +10,7 @@ layout(set = 1, binding = 0) uniform Viewport { // inputs layout(location = 0) in ivec2 in_position; layout(location = 1) in ivec4 in_attr; // quad x,y,w,h -layout(location = 2) in ivec2 in_uv; +layout(location = 2) in ivec4 in_uv; layout(location = 3) in uvec4 in_color; layout(location = 4) in uint in_type; @@ -35,7 +35,7 @@ void main() out_color = vec4(in_color) / 255.0; // uv output. only useful if the type is SPRITE - vec2 px_uv = in_uv.xy + in_position.xy * in_attr.zw; + vec2 px_uv = in_uv.xy + in_position.xy * in_uv.zw; out_uv = vec2(px_uv); // quad size and radius output, only useful if type is RECT diff --git a/src/renderer.c3 b/src/renderer.c3 index f2a8f60..2794c36 100644 --- a/src/renderer.c3 +++ b/src/renderer.c3 @@ -55,7 +55,7 @@ struct QuadAttributes { short x, y, w, h; } struct uv { - short u, v; + short u, v, w, h; } uint color; uint type; @@ -483,7 +483,7 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type) } }, .num_vertex_buffers = 2, - // the description of each vertex + // the description of each vertex, quad and bindings .vertex_attributes = (GPUVertexAttribute[]){ { // at location zero there is the position of the vertex .location = 0, @@ -500,7 +500,7 @@ fn void Renderer.create_pipeline(&self, String shader_name, PipelineType type) { // at location two there are the per-quad uv coordinates .location = 2, .buffer_slot = 1, - .format = GPU_VERTEXELEMENTFORMAT_SHORT2, + .format = GPU_VERTEXELEMENTFORMAT_SHORT4, .offset = QuadAttributes.uv.offsetof, }, { // at location three there is the quad color @@ -713,11 +713,11 @@ const uint TYPE_FONT = 1; const uint TYPE_SPRITE = 2; const uint TYPE_MSDF = 3; -fn bool Renderer.push_sprite(&self, short x, short y, short w, short h, short u, short v, uint color = 0xffffffff, uint type) +fn bool Renderer.push_sprite(&self, short x, short y, short w, short h, short u, short v, short sw, short sh, uint color = 0xffffffff, uint type) { QuadAttributes qa = { .pos = {.x = x, .y = y, .w = w, .h = h}, - .uv = {.u = u, .v = v}, + .uv = {.u = u, .v = v, .w = sw, .h = sh}, .color = color, .type = type, }; @@ -980,7 +980,7 @@ fn void Renderer.render_ugui(&self, CmdQueue* queue) } else { unreachable("unrecognized command type"); } - self.push_sprite(s.rect.x, s.rect.y, s.texture_rect.w, s.texture_rect.h, s.texture_rect.x, s.texture_rect.y, s.hue.to_uint(), type); + self.push_sprite(s.rect.x, s.rect.y, s.rect.w, s.rect.h, s.texture_rect.x, s.texture_rect.y, s.texture_rect.w, s.texture_rect.h, s.hue.to_uint(), type); } } self.upload_quads();