Various ui improvements proposed by @till++

This commit is contained in:
IntegratedQuantum 2023-04-03 19:01:49 +02:00
parent e17699f9f8
commit e0321c6cbf
20 changed files with 105 additions and 17 deletions

View File

@ -2,14 +2,16 @@
layout (location=0) out vec4 frag_color; layout (location=0) out vec4 frag_color;
in vec2 frag_face_pos; flat in vec4 color;
in vec4 color;
uniform sampler2D texture_sampler; uniform sampler2D texture_sampler;
//in pxls //in pxls
uniform vec4 texture_rect; uniform vec4 texture_rect;
uniform vec2 scene;
uniform vec2 fontSize; uniform vec2 fontSize;
uniform vec2 offset;
uniform float ratio;
uniform int fontEffects; uniform int fontEffects;
vec2 convert2Proportional(vec2 original, vec2 full){ vec2 convert2Proportional(vec2 original, vec2 full){
@ -18,6 +20,7 @@ vec2 convert2Proportional(vec2 original, vec2 full){
void main(){ void main(){
vec2 frag_face_pos = (vec2(0, scene.y) + gl_FragCoord.xy*vec2(1, -1) - offset)/texture_rect.zw/ratio;
vec4 texture_rect_percentage = vec4(convert2Proportional(texture_rect.xy, fontSize), convert2Proportional(texture_rect.zw, fontSize)); vec4 texture_rect_percentage = vec4(convert2Proportional(texture_rect.xy, fontSize), convert2Proportional(texture_rect.zw, fontSize));
vec2 texture_position = vec2( vec2 texture_position = vec2(
texture_rect_percentage.x+ texture_rect_percentage.x+

View File

@ -2,8 +2,7 @@
layout (location=0) in vec2 face_pos; layout (location=0) in vec2 face_pos;
out vec2 frag_face_pos; flat out vec4 color;
out vec4 color;
//in pixel //in pixel
@ -35,6 +34,5 @@ void main() {
vec2 position = vec2(rect.x+vertex_pos.x*rect.z, -rect.y+vertex_pos.y*rect.w)*2+vec2(-1, 1); vec2 position = vec2(rect.x+vertex_pos.x*rect.z, -rect.y+vertex_pos.y*rect.w)*2+vec2(-1, 1);
gl_Position = vec4(position, 0, 1); gl_Position = vec4(position, 0, 1);
frag_face_pos = face_pos;
color = vec4(vec3((fontEffects & 0xff0000)>>16, (fontEffects & 0xff00)>>8, fontEffects & 0xff)/255.0, alpha); color = vec4(vec3((fontEffects & 0xff0000)>>16, (fontEffects & 0xff00)>>8, fontEffects & 0xff)/255.0, alpha);
} }

View File

@ -0,0 +1,19 @@
#version 330
layout (location=0) out vec4 frag_color;
flat in vec4 fColor;
flat in vec2 startCoord;
flat in vec2 endCoord;
uniform vec2 start;
uniform vec2 size;
uniform float scale;
uniform vec2 effectLength;
void main() {
vec2 distanceToBorder = min(gl_FragCoord.xy - startCoord, endCoord - gl_FragCoord.xy)/effectLength/scale;
float reducedDistance = distanceToBorder.x*distanceToBorder.y/(distanceToBorder.x + distanceToBorder.y); // Inspired by the reduced mass from physics, to give a sort of curvy look to the outline.
float opacity = max(1 - reducedDistance, 0);
frag_color = fColor*vec4(1, 1, 1, opacity);
}

View File

@ -0,0 +1,30 @@
#version 330 core
layout (location=0) in vec2 vertex_pos;
flat out vec2 startCoord;
flat out vec2 endCoord;
flat out vec4 fColor;
//in pixel
uniform vec2 start;
uniform vec2 size;
uniform vec2 screen;
uniform int color;
void main() {
// Convert to opengl coordinates:
vec2 position_percentage = (start + vertex_pos*size)/screen;
startCoord.x = start.x;
startCoord.y = screen.y - start.y - size.y;
endCoord.x = start.x + size.x;
endCoord.y = screen.y - start.y;
vec2 position = vec2(position_percentage.x, -position_percentage.y)*2+vec2(-1, 1);
gl_Position = vec4(position, 0, 1);
fColor = vec4((color & 0xff0000)>>16, (color & 0xff00)>>8, color & 0xff, (color>>24) & 255)/255.0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

After

Width:  |  Height:  |  Size: 605 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -95,11 +95,22 @@ var windowUniforms: struct {
image: c_int, image: c_int,
randomOffset: c_int, randomOffset: c_int,
} = undefined; } = undefined;
pub var borderShader: Shader = undefined;
pub var borderUniforms: struct {
screen: c_int,
start: c_int,
size: c_int,
color: c_int,
scale: c_int,
effectLength: c_int,
} = undefined;
pub fn __init() !void { pub fn __init() !void {
shader = try Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", &windowUniforms); shader = try Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", &windowUniforms);
shader.bind(); shader.bind();
graphics.c.glUniform1i(windowUniforms.image, 0); graphics.c.glUniform1i(windowUniforms.image, 0);
borderShader = try Shader.initAndGetUniforms("assets/cubyz/shaders/ui/window_border.vs", "assets/cubyz/shaders/ui/window_border.fs", &borderUniforms);
borderShader.bind();
backgroundTexture = try Texture.initFromFile("assets/cubyz/ui/window_background.png"); backgroundTexture = try Texture.initFromFile("assets/cubyz/ui/window_background.png");
titleTexture = try Texture.initFromFile("assets/cubyz/ui/window_title.png"); titleTexture = try Texture.initFromFile("assets/cubyz/ui/window_title.png");
@ -473,9 +484,15 @@ pub fn render(self: *const GuiWindow, mousePosition: Vec2f) !void {
expandTitleBarTexture.render(.{0, 0}, .{16, 16}); expandTitleBarTexture.render(.{0, 0}, .{16, 16});
} }
} }
if(self.hasBackground or (!main.Window.grabbed and self.titleBarExpanded)) {
draw.setColor(0x80000000);
borderShader.bind();
graphics.c.glUniform2f(borderUniforms.effectLength, 2.5, 2.5);
draw.customShadedRect(borderUniforms, .{0, 0}, self.size/@splat(2, self.scale));
}
draw.restoreTranslation(oldTranslation); draw.restoreTranslation(oldTranslation);
draw.restoreScale(oldScale); draw.restoreScale(oldScale);
if(self.showTitleBar) { if(self.showTitleBar and false) { // TODO: Figure out whether I should even draw titlebar text.
var text = try graphics.TextBuffer.init(gui.allocator, self.title, .{.color=0}, false, .center); var text = try graphics.TextBuffer.init(gui.allocator, self.title, .{.color=0}, false, .center);
defer text.deinit(); defer text.deinit();
const titleDimension = try text.calculateLineBreaks(16*self.scale, self.size[0]); const titleDimension = try text.calculateLineBreaks(16*self.scale, self.size[0]);

View File

@ -66,8 +66,8 @@ pub fn initText(pos: Vec2f, width: f32, text: []const u8, onAction: ?*const fn()
return self; return self;
} }
pub fn initIcon(pos: Vec2f, iconSize: Vec2f, iconTexture: Texture, onAction: ?*const fn() void) Allocator.Error!*Button { pub fn initIcon(pos: Vec2f, iconSize: Vec2f, iconTexture: Texture, hasShadow: bool, onAction: ?*const fn() void) Allocator.Error!*Button {
const icon = try Icon.init(undefined, iconSize, iconTexture); const icon = try Icon.init(undefined, iconSize, iconTexture, hasShadow);
const self = try gui.allocator.create(Button); const self = try gui.allocator.create(Button);
self.* = Button { self.* = Button {
.pos = pos, .pos = pos,

View File

@ -19,7 +19,7 @@ var texture: Texture = undefined;
const border: f32 = 3; const border: f32 = 3;
pos: Vec2f, pos: Vec2f,
size: Vec2f = .{32 + 2*border, 32 + 2*border}, size: Vec2f = .{24 + 2*border, 24 + 2*border},
itemStack: ItemStack, itemStack: ItemStack,
text: TextBuffer, text: TextBuffer,
textSize: Vec2f = .{0, 0}, textSize: Vec2f = .{0, 0},
@ -94,6 +94,9 @@ pub fn render(self: *CraftingResultSlot, _: Vec2f) !void {
if(self.itemStack.item) |item| { if(self.itemStack.item) |item| {
const itemTexture = try item.getTexture(); const itemTexture = try item.getTexture();
itemTexture.bindTo(0); itemTexture.bindTo(0);
draw.setColor(0xff000000);
draw.boundImage(self.pos + @splat(2, border) + Vec2f{1.0, 1.0}, self.size - @splat(2, 2*border));
draw.setColor(0xffffffff);
draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border)); draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border));
if(self.itemStack.amount != 1) { if(self.itemStack.amount != 1) {
try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8); try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8);

View File

@ -18,13 +18,15 @@ const fontSize: f32 = 16;
pos: Vec2f, pos: Vec2f,
size: Vec2f, size: Vec2f,
texture: Texture, texture: Texture,
hasShadow: bool,
pub fn init(pos: Vec2f, size: Vec2f, texture: Texture) Allocator.Error!*Icon { pub fn init(pos: Vec2f, size: Vec2f, texture: Texture, hasShadow: bool) Allocator.Error!*Icon {
const self = try gui.allocator.create(Icon); const self = try gui.allocator.create(Icon);
self.* = Icon { self.* = Icon {
.texture = texture, .texture = texture,
.pos = pos, .pos = pos,
.size = size, .size = size,
.hasShadow = hasShadow,
}; };
return self; return self;
} }
@ -44,6 +46,10 @@ pub fn updateTexture(self: *Icon, newTexture: Texture) !void {
} }
pub fn render(self: *Icon, _: Vec2f) !void { pub fn render(self: *Icon, _: Vec2f) !void {
if(self.hasShadow) {
draw.setColor(0xff000000);
self.texture.render(self.pos + Vec2f{1, 1}, self.size);
}
draw.setColor(0xffffffff); draw.setColor(0xffffffff);
self.texture.render(self.pos, self.size); self.texture.render(self.pos, self.size);
} }

View File

@ -19,7 +19,7 @@ var texture: Texture = undefined;
const border: f32 = 3; const border: f32 = 3;
pos: Vec2f, pos: Vec2f,
size: Vec2f = .{32 + 2*border, 32 + 2*border}, size: Vec2f = .{24 + 2*border, 24 + 2*border},
item: *BaseItem, item: *BaseItem,
amount: u32, amount: u32,
text: TextBuffer, text: TextBuffer,
@ -63,6 +63,9 @@ pub fn render(self: *ImmutableItemSlot, _: Vec2f) !void {
draw.boundImage(self.pos, self.size); draw.boundImage(self.pos, self.size);
const itemTexture = try self.item.getTexture(); const itemTexture = try self.item.getTexture();
itemTexture.bindTo(0); itemTexture.bindTo(0);
draw.setColor(0xff000000);
draw.boundImage(self.pos + @splat(2, border) + Vec2f{1.0, 1.0}, self.size - @splat(2, 2*border));
draw.setColor(0xffffffff);
draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border)); draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border));
if(self.amount != 1) { if(self.amount != 1) {
try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8); try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8);

View File

@ -16,10 +16,10 @@ const GuiComponent = gui.GuiComponent;
const ItemSlot = @This(); const ItemSlot = @This();
var texture: Texture = undefined; var texture: Texture = undefined;
const border: f32 = 3; const border: f32 = 2;
pos: Vec2f, pos: Vec2f,
size: Vec2f = .{32 + 2*border, 32 + 2*border}, size: Vec2f = .{24 + 2*border, 24 + 2*border},
itemStack: *ItemStack, itemStack: *ItemStack,
oldStack: ItemStack, oldStack: ItemStack,
text: TextBuffer, text: TextBuffer,
@ -105,6 +105,9 @@ pub fn render(self: *ItemSlot, _: Vec2f) !void {
if(self.itemStack.item) |item| { if(self.itemStack.item) |item| {
const itemTexture = try item.getTexture(); const itemTexture = try item.getTexture();
itemTexture.bindTo(0); itemTexture.bindTo(0);
draw.setColor(0xff000000);
draw.boundImage(self.pos + @splat(2, border) + Vec2f{1.0, 1.0}, self.size - @splat(2, 2*border));
draw.setColor(0xffffffff);
draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border)); draw.boundImage(self.pos + @splat(2, border), self.size - @splat(2, 2*border));
if(self.itemStack.amount != 1) { if(self.itemStack.amount != 1) {
try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8); try self.text.render(self.pos[0] + self.size[0] - self.textSize[0] - border, self.pos[1] + self.size[1] - self.textSize[1] - border, 8);

View File

@ -458,6 +458,12 @@ pub fn updateAndRenderGui() !void {
for(openWindows.items) |window| { for(openWindows.items) |window| {
try window.update(); try window.update();
} }
if(!main.Window.grabbed) {
draw.setColor(0x80000000);
GuiWindow.borderShader.bind();
graphics.c.glUniform2f(GuiWindow.borderUniforms.effectLength, main.Window.getWindowSize()[0]/6, main.Window.getWindowSize()[1]/6);
draw.customShadedRect(GuiWindow.borderUniforms, .{0, 0}, main.Window.getWindowSize());
}
const oldScale = draw.setScale(scale); const oldScale = draw.setScale(scale);
defer draw.restoreScale(oldScale); defer draw.restoreScale(oldScale);
for(openWindows.items) |window| { for(openWindows.items) |window| {

View File

@ -33,7 +33,7 @@ pub fn onOpen() Allocator.Error!void {
try items.append(Item{.baseItem = item.*}); try items.append(Item{.baseItem = item.*});
} }
var list = try VerticalList.init(.{padding, padding + 16}, 150, 0); var list = try VerticalList.init(.{padding, padding + 16}, 140, 0);
var i: u32 = 0; var i: u32 = 0;
while(i < items.items.len) { while(i < items.items.len) {
var row = try HorizontalList.init(); var row = try HorizontalList.init();

View File

@ -38,7 +38,7 @@ pub fn onOpen() Allocator.Error!void {
// TODO: armor slots, backpack slot + stack-based backpack inventory, other items maybe? // TODO: armor slots, backpack slot + stack-based backpack inventory, other items maybe?
{ {
var row = try HorizontalList.init(); var row = try HorizontalList.init();
try row.add(try Button.initIcon(.{0, 0}, .{32, 32}, craftingIcon, gui.openWindowFunction("cubyz:inventory_crafting"))); // TODO: Replace the text with an icon try row.add(try Button.initIcon(.{0, 0}, .{24, 24}, craftingIcon, true, gui.openWindowFunction("cubyz:inventory_crafting"))); // TODO: Replace the text with an icon
try list.add(row); try list.add(row);
} }
// Inventory: // Inventory:

View File

@ -128,7 +128,7 @@ fn findAvailableRecipes(list: *VerticalList) Allocator.Error!bool {
columnList.finish(.center); columnList.finish(.center);
try rowList.add(columnList); try rowList.add(columnList);
} }
try rowList.add(try Icon.init(.{8, 0}, .{32, 32}, arrowTexture)); try rowList.add(try Icon.init(.{8, 0}, .{32, 32}, arrowTexture, false));
const itemSlot = try CraftingResultSlot.init(.{8, 0}, recipe.resultItem, &onTake, recipeIndex); const itemSlot = try CraftingResultSlot.init(.{8, 0}, recipe.resultItem, &onTake, recipeIndex);
try rowList.add(itemSlot); try rowList.add(itemSlot);
rowList.finish(.{0, 0}, .center); rowList.finish(.{0, 0}, .center);

View File

@ -100,7 +100,7 @@ pub fn onOpen() Allocator.Error!void {
grid.finish(.center); grid.finish(.center);
try list.add(grid); try list.add(grid);
} }
try list.add(try Icon.init(.{8, 0}, .{32, 32}, inventory_crafting.arrowTexture)); try list.add(try Icon.init(.{8, 0}, .{32, 32}, inventory_crafting.arrowTexture, false));
craftingResult = try CraftingResultSlot.init(.{8, 0}, .{}, &onTake, 0); craftingResult = try CraftingResultSlot.init(.{8, 0}, .{}, &onTake, 0);
try list.add(craftingResult); try list.add(craftingResult);
list.finish(.{padding, padding + 16}, .center); list.finish(.{padding, padding + 16}, .center);