From b651922d015f59278cf654b10b9a788b80cc2861 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Mon, 5 Jul 2021 22:26:02 -0500 Subject: [PATCH] starting to work on ui --- res/colors.json | 19 +++++++ server.sh | 3 + site/js/webgl2.js | 48 ++++++++++++---- src/config.onyx | 25 +++++++++ src/main.onyx | 139 +++++++++++++++++++++++++++++++++++++++++++--- 5 files changed, 216 insertions(+), 18 deletions(-) create mode 100644 res/colors.json create mode 100755 server.sh diff --git a/res/colors.json b/res/colors.json new file mode 100644 index 0000000..31095c1 --- /dev/null +++ b/res/colors.json @@ -0,0 +1,19 @@ +{ + "dark_background": [ 0.1, 0.1, 0.1 ], + "background": [ 0.15, 0.15, 0.15 ], + "foreground": [ 0.9, 0.9, 0.9 ], + + "keyword": [ 0.7, 0.7, 1.0 ], + "value": [ 0.8, 1.0, 0.8 ], + "jumppoint": [ 1, 0.5, 0.5 ], + + "primary": [ 0.051, 0.278, 0.631 ], + "primary_light": [ 0.329, 0.451, 0.827 ], + "primary_dark": [ 0, 0.129, 0.443 ], + "primary_text": [ 1, 1, 1 ], + + "secondary": [ 0, 0.376, 0.392 ], + "secondary_light": [ 0.259, 0.557, 0.573 ], + "secondary_dark": [ 0, 0.212, 0.227 ], + "secondary_text": [ 1, 1, 1 ] +} diff --git a/server.sh b/server.sh new file mode 100755 index 0000000..da47832 --- /dev/null +++ b/server.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +$(which python) -m http.server \ No newline at end of file diff --git a/site/js/webgl2.js b/site/js/webgl2.js index bd53399..df8936d 100644 --- a/site/js/webgl2.js +++ b/site/js/webgl2.js @@ -38,10 +38,34 @@ window.ONYX_MODULES.push({ gl.bindBuffer(target, buffers[buffer]); } }, - bindFramebuffer(target, framebuffer) { gl.bindFramebuffer(target, framebuffers[framebuffer]); }, - bindRenderbuffer(target, renderbuffer) { gl.bindRenderbuffer(target, renderbuffers[renderbuffer]); }, - bindTexture(target, texture) { gl.bindTexture(target, textures[texture]); }, - bindVertexArray(vertexArray) { gl.bindVertexArray(vertexArrays[vertexArray]); }, + bindFramebuffer(target, framebuffer) { + if (framebuffer == -1) { + gl.bindFramebuffer(target, null); + } else { + gl.bindFramebuffer(target, framebuffers[framebuffer]); + } + }, + bindRenderbuffer(target, renderbuffer) { + if (renderbuffer == -1) { + gl.bindRenderbuffer(target, null); + } else { + gl.bindRenderbuffer(target, renderbuffers[renderbuffer]); + } + }, + bindTexture(target, texture) { + if (texture == -1) { + gl.bindTexture(target, null); + } else { + gl.bindTexture(target, textures[texture]); + } + }, + bindVertexArray(vertexArray) { + if (vertexArray == -1) { + gl.bindVertexArray(null); + } else { + gl.bindVertexArray(vertexArrays[vertexArray]); + } + }, blendColor(red, green, blue, alpha) { gl.blendColor(red, green, blue, alpha); }, blendEquation(mode) { gl.blendEquation(mode); }, @@ -67,7 +91,7 @@ window.ONYX_MODULES.push({ canvas.width = width; canvas.height = height; }, - checkFrameBufferStatus(target) { return gl.checkFrameBufferStatus(target); }, + checkFramebufferStatus(target) { return gl.checkFramebufferStatus(target); }, clear(bit) { gl.clear(bit); }, clearColor(r, g, b, a) { gl.clearColor(r, g, b, a); }, clearDepth(depth) { gl.clearDepth(depth); }, @@ -83,8 +107,8 @@ window.ONYX_MODULES.push({ gl.compressedSubTexImage2D(target, level, internalformat, xoff, yoff, width, height, format, pixels); }, copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size) { gl.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }, - copyTexImage2D(target, level, internalforamt, x, y, width, height, border) { - gl.copyTexImage2D(target, level, internalforamt, x, y, width, height, border); + copyTexImage2D(target, level, internalformat, x, y, width, height, border) { + gl.copyTexImage2D(target, level, internalformat, x, y, width, height, border); }, copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height) { gl.copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height); @@ -229,8 +253,9 @@ window.ONYX_MODULES.push({ gl.readPixels(x, y, width, height, format, type, pixeldata); }, readBuffer(src) { gl.readBuffer(src); }, - renderbufferStorageMultisample(target, samples, internalforamt, width, height) { - gl.renderbufferStorageMultisample(target, samples, internalforamt, width, height); + renderbufferStorage(target, internalformat, width, height) { gl.renderbufferStorage(target, internalformat, width, height); }, + renderbufferStorageMultisample(target, samples, internalformat, width, height) { + gl.renderbufferStorageMultisample(target, samples, internalformat, width, height); }, sampleCoverage(value, invert) { gl.sampleCoverage(value, invert); }, scissor(x, y, width, height) { gl.scissor(x, y, width, height); }, @@ -248,12 +273,13 @@ window.ONYX_MODULES.push({ stencilMaskSeparate(face, mask) { gl.stencilMaskSeparate(face, mask); }, stencilOp(fail, zfail, mask) { gl.stencilOp(fail, zfail, mask); }, stencilOpSeparate(face, fail, zfail, zpass) { gl.stencilOpSeparate(face, fail, zfail, zpass); }, - texImage2D(target, level, internalforamt, width, height, border, format, type, pixels, pixelslen) { + texImage2D(target, level, internalformat, width, height, border, format, type, pixels, pixelslen) { const data = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); - gl.texImage2D(target, level, internalforamt, width, height, border, format, type, data); + gl.texImage2D(target, level, internalformat, width, height, border, format, type, data); }, texParameterf(target, pname, param) { gl.texParameterf(target, pname, param); }, texParameteri(target, pname, param) { gl.texParameteri(target, pname, param); }, + texStorage2D(target, levels, internalformat, width, height) { gl.texStorage2D(target, levels, internalformat, width, height); }, texSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels, pixelslen) { const data = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); gl.texSubImage2D(target, level, xoff, yoff, width, height, format, type, data); diff --git a/src/config.onyx b/src/config.onyx index f3921b0..fc36fac 100644 --- a/src/config.onyx +++ b/src/config.onyx @@ -1,2 +1,27 @@ package config +#if (package runtime).Runtime != (package runtime).Runtime_Wasi { + +use package immediate_mode { Color4 } + + +Colors : struct { + dark_background : Color4; + background : Color4; + foreground : Color4; + + keyword : Color4; + value : Color4; + jumppoint : Color4; + + primary : Color4; + primary_light : Color4; + primary_dark : Color4; + primary_text : Color4; + secondary : Color4; + secondary_light : Color4; + secondary_dark : Color4; + secondary_text : Color4; +} + +} diff --git a/src/main.onyx b/src/main.onyx index 8e08565..1ce5393 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -14,17 +14,87 @@ main :: (args: [] cstr) { start_loop(); } +test_canvas : gfx.Canvas; + init :: () { gl.init("main_canvas"); events.init(); gfx.immediate_renderer_init(); + load_colors(); ui.init_ui(); gl.enable(gl.BLEND); gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + + test_canvas = gfx.create_canvas(1000, 1000); + { + time_now :: () -> i32 #foreign "decompiler" "time_now" --- + random.set_seed(time_now() / 1000); + + gfx.use_canvas(^test_canvas); + defer gfx.use_canvas(null); + + gl.clearColor(0, 0, 0, 0.6); + gl.clear(gl.COLOR_BUFFER_BIT); + + gfx.set_mode(.Lines); + gfx.set_texture(); + gl.lineWidth(10); + + pv := gfx.Vector2.{ 0, 0 }; + for i: 11 { + pv = .{ ~~random.between(0, 1000), ~~random.between(0, 1000) }; + gfx.vertex(pv, config.Colors.primary); + + pv = .{ ~~random.between(0, 1000), ~~random.between(0, 1000) }; + gfx.vertex(pv, config.Colors.primary); + } + + gfx.set_mode(.Triangles); + } + + load_colors :: () { + json :: package json + + @DynamicLoading // Currently, this file is just baked into the binary. When a mechanism + // is added to easily ask JS to make a fetch request for a file, that can be used here. + colors_json := #file_contents "res/colors.json"; + + arena := alloc.arena.make(context.allocator, 4096); + defer alloc.arena.free(^arena); + colors := json.decode(colors_json, alloc.arena.make_allocator(^arena)); + defer json.free(colors); + + config.Colors.dark_background = decode_color(colors.root["dark_background"]); + config.Colors.background = decode_color(colors.root["background"]); + config.Colors.foreground = decode_color(colors.root["foreground"]); + + config.Colors.keyword = decode_color(colors.root["keyword"]); + config.Colors.value = decode_color(colors.root["value"]); + config.Colors.jumppoint = decode_color(colors.root["jumppoint"]); + + config.Colors.primary = decode_color(colors.root["primary"]); + config.Colors.primary_light = decode_color(colors.root["primary_light"]); + config.Colors.primary_dark = decode_color(colors.root["primary_dark"]); + config.Colors.primary_text = decode_color(colors.root["primary_text"]); + + config.Colors.secondary = decode_color(colors.root["secondary"]); + config.Colors.secondary_light = decode_color(colors.root["secondary_light"]); + config.Colors.secondary_dark = decode_color(colors.root["secondary_dark"]); + config.Colors.secondary_text = decode_color(colors.root["secondary_text"]); + + decode_color :: (v: ^json.Value) -> gfx.Color4 { + return .{ + r = ~~v[0]->as_float(), + g = ~~v[1]->as_float(), + b = ~~v[2]->as_float(), + }; + } + } } + last_time := 0; #export "loop" () { time_now :: () -> i32 #foreign "decompiler" "time_now" --- @@ -94,8 +164,7 @@ poll_events :: () -> bool { window_height = event.resize.height; gl.setSize(event.resize.width, event.resize.height); - gl.viewport(0, 0, event.resize.width, event.resize.height); - gfx.use_ortho_projection(0, ~~window_width, 0, ~~window_height); + gfx.set_window_size(event.resize.width, event.resize.height); } } } @@ -106,15 +175,71 @@ poll_events :: () -> bool { update :: (dt: f32) { } -red := 1.0f; draw :: () { - gl.clearColor(red, 0, 0, 1); + bg_color := config.Colors.background; + gl.clearColor(bg_color.r, bg_color.g, bg_color.b, bg_color.a); gl.clear(gl.COLOR_BUFFER_BIT); - if ui.button(.{ 100, 100, 300, 200 }, "Test") { - red = 1 - red; - } + window_rectangle := ui.Rectangle.{ 0, 0, ~~window_width, ~~window_height }; + + draw_background_lines(~~window_width, ~~window_height, 0, 0, line_color=config.Colors.dark_background); + draw_menu_bar(window_rectangle); + + gfx.set_texture(^test_canvas.color_texture); + gfx.textured_rect(.{ 300, 100 }, .{ 800, 400 }, .{ 0, 0 }, .{ 1, 1 }); + gfx.set_texture(); gfx.flush(); ui.clear_buttons(); } + +#private_file +draw_menu_bar :: (window_rectangle: ui.Rectangle) { + menu_bar, _ := ui.Flow.split_horizontal(window_rectangle, top_height=32); + + ui.draw_rect(menu_bar, color=.{ 0.2, 0.2, 0.2 }); + + menu_button_theme := ui.default_button_theme; + menu_button_theme.border_width = 2; + menu_button_theme.font_size = .9; + + button_rect : ui.Rectangle; + + button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100); + ui.button(button_rect, "File", theme=^menu_button_theme); + button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100); + ui.button(button_rect, "Edit", theme=^menu_button_theme); + button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100); + ui.button(button_rect, "View", theme=^menu_button_theme); + button_rect, menu_bar = ui.Flow.split_vertical(menu_bar, left_width=100); + ui.button(button_rect, "Help", theme=^menu_button_theme); +} + +#private_file +draw_background_lines :: (width: f32, height: f32, offset_x: f32, offset_y: f32, line_color := gfx.Color4.{0.2, 0.2, 0.2}, line_spacing := 32.0f) { + gl :: package gl + + gfx.set_mode(.Lines); + gfx.set_texture(); + gl.lineWidth(4); + + // "Modulus" to the nearest (-line_spacing, line_spacing) for both x and y. + offset_x /= line_spacing; + offset_y /= line_spacing; + offset_x = line_spacing * (offset_x - math.trunc(offset_x)); + offset_y = line_spacing * (offset_y - math.trunc(offset_y)); + + for i: cast(i32) (math.ceil(width / line_spacing)) + 1 { + x := offset_x + ~~i * line_spacing; + gfx.vertex(.{ x, 0 }, line_color); + gfx.vertex(.{ x, height }, line_color); + } + + for i: cast(i32) (math.ceil(height / line_spacing)) + 1 { + y := offset_y + ~~i * line_spacing; + gfx.vertex(.{ 0, y }, line_color); + gfx.vertex(.{ width, y }, line_color); + } + + gfx.set_mode(.Triangles); +} -- 2.25.1