Various ui improvements proposed by @till++
@ -2,14 +2,16 @@
|
||||
|
||||
layout (location=0) out vec4 frag_color;
|
||||
|
||||
in vec2 frag_face_pos;
|
||||
in vec4 color;
|
||||
flat in vec4 color;
|
||||
|
||||
uniform sampler2D texture_sampler;
|
||||
|
||||
//in pxls
|
||||
uniform vec4 texture_rect;
|
||||
uniform vec2 scene;
|
||||
uniform vec2 fontSize;
|
||||
uniform vec2 offset;
|
||||
uniform float ratio;
|
||||
uniform int fontEffects;
|
||||
|
||||
vec2 convert2Proportional(vec2 original, vec2 full){
|
||||
@ -18,6 +20,7 @@ vec2 convert2Proportional(vec2 original, vec2 full){
|
||||
|
||||
|
||||
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));
|
||||
vec2 texture_position = vec2(
|
||||
texture_rect_percentage.x+
|
||||
|
@ -2,8 +2,7 @@
|
||||
|
||||
layout (location=0) in vec2 face_pos;
|
||||
|
||||
out vec2 frag_face_pos;
|
||||
out vec4 color;
|
||||
flat out vec4 color;
|
||||
|
||||
|
||||
//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);
|
||||
|
||||
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);
|
||||
}
|
19
assets/cubyz/shaders/ui/window_border.fs
Normal 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);
|
||||
}
|
30
assets/cubyz/shaders/ui/window_border.vs
Normal 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;
|
||||
}
|
Before Width: | Height: | Size: 588 B After Width: | Height: | Size: 675 B |
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 605 B |
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 602 B |
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 603 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 1.5 KiB |
@ -95,11 +95,22 @@ var windowUniforms: struct {
|
||||
image: c_int,
|
||||
randomOffset: c_int,
|
||||
} = 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 {
|
||||
shader = try Shader.initAndGetUniforms("assets/cubyz/shaders/ui/button.vs", "assets/cubyz/shaders/ui/button.fs", &windowUniforms);
|
||||
shader.bind();
|
||||
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");
|
||||
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});
|
||||
}
|
||||
}
|
||||
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.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);
|
||||
defer text.deinit();
|
||||
const titleDimension = try text.calculateLineBreaks(16*self.scale, self.size[0]);
|
||||
|
@ -66,8 +66,8 @@ pub fn initText(pos: Vec2f, width: f32, text: []const u8, onAction: ?*const fn()
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn initIcon(pos: Vec2f, iconSize: Vec2f, iconTexture: Texture, onAction: ?*const fn() void) Allocator.Error!*Button {
|
||||
const icon = try Icon.init(undefined, iconSize, iconTexture);
|
||||
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, hasShadow);
|
||||
const self = try gui.allocator.create(Button);
|
||||
self.* = Button {
|
||||
.pos = pos,
|
||||
|
@ -19,7 +19,7 @@ var texture: Texture = undefined;
|
||||
const border: f32 = 3;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f = .{32 + 2*border, 32 + 2*border},
|
||||
size: Vec2f = .{24 + 2*border, 24 + 2*border},
|
||||
itemStack: ItemStack,
|
||||
text: TextBuffer,
|
||||
textSize: Vec2f = .{0, 0},
|
||||
@ -94,6 +94,9 @@ pub fn render(self: *CraftingResultSlot, _: Vec2f) !void {
|
||||
if(self.itemStack.item) |item| {
|
||||
const itemTexture = try item.getTexture();
|
||||
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));
|
||||
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);
|
||||
|
@ -18,13 +18,15 @@ const fontSize: f32 = 16;
|
||||
pos: Vec2f,
|
||||
size: Vec2f,
|
||||
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);
|
||||
self.* = Icon {
|
||||
.texture = texture,
|
||||
.pos = pos,
|
||||
.size = size,
|
||||
.hasShadow = hasShadow,
|
||||
};
|
||||
return self;
|
||||
}
|
||||
@ -44,6 +46,10 @@ pub fn updateTexture(self: *Icon, newTexture: Texture) !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);
|
||||
self.texture.render(self.pos, self.size);
|
||||
}
|
@ -19,7 +19,7 @@ var texture: Texture = undefined;
|
||||
const border: f32 = 3;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f = .{32 + 2*border, 32 + 2*border},
|
||||
size: Vec2f = .{24 + 2*border, 24 + 2*border},
|
||||
item: *BaseItem,
|
||||
amount: u32,
|
||||
text: TextBuffer,
|
||||
@ -63,6 +63,9 @@ pub fn render(self: *ImmutableItemSlot, _: Vec2f) !void {
|
||||
draw.boundImage(self.pos, self.size);
|
||||
const itemTexture = try self.item.getTexture();
|
||||
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));
|
||||
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);
|
||||
|
@ -16,10 +16,10 @@ const GuiComponent = gui.GuiComponent;
|
||||
const ItemSlot = @This();
|
||||
|
||||
var texture: Texture = undefined;
|
||||
const border: f32 = 3;
|
||||
const border: f32 = 2;
|
||||
|
||||
pos: Vec2f,
|
||||
size: Vec2f = .{32 + 2*border, 32 + 2*border},
|
||||
size: Vec2f = .{24 + 2*border, 24 + 2*border},
|
||||
itemStack: *ItemStack,
|
||||
oldStack: ItemStack,
|
||||
text: TextBuffer,
|
||||
@ -105,6 +105,9 @@ pub fn render(self: *ItemSlot, _: Vec2f) !void {
|
||||
if(self.itemStack.item) |item| {
|
||||
const itemTexture = try item.getTexture();
|
||||
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));
|
||||
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);
|
||||
|
@ -458,6 +458,12 @@ pub fn updateAndRenderGui() !void {
|
||||
for(openWindows.items) |window| {
|
||||
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);
|
||||
defer draw.restoreScale(oldScale);
|
||||
for(openWindows.items) |window| {
|
||||
|
@ -33,7 +33,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
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;
|
||||
while(i < items.items.len) {
|
||||
var row = try HorizontalList.init();
|
||||
|
@ -38,7 +38,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
// TODO: armor slots, backpack slot + stack-based backpack inventory, other items maybe?
|
||||
{
|
||||
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);
|
||||
}
|
||||
// Inventory:
|
||||
|
@ -128,7 +128,7 @@ fn findAvailableRecipes(list: *VerticalList) Allocator.Error!bool {
|
||||
columnList.finish(.center);
|
||||
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);
|
||||
try rowList.add(itemSlot);
|
||||
rowList.finish(.{0, 0}, .center);
|
||||
|
@ -100,7 +100,7 @@ pub fn onOpen() Allocator.Error!void {
|
||||
grid.finish(.center);
|
||||
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);
|
||||
try list.add(craftingResult);
|
||||
list.finish(.{padding, padding + 16}, .center);
|
||||
|