From 2c6ac54c667a5d643bdaccaf109f5a30a2a504f4 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sat, 26 Feb 2022 20:17:06 -0600 Subject: [PATCH] updated tag syntax; scene renders in middle --- run_tree/scenes/default.items | 1 - run_tree/scenes/quick_save_new.scene | 42 ++++++++++++++-------------- src/build.onyx | 1 + src/entity/editor.onyx | 30 ++++++++++++-------- src/entity/items.onyx | 7 +++-- src/entity/manager.onyx | 23 +++++++++++---- src/entity/player.onyx | 24 ++++++++++------ src/game.onyx | 28 ++++++++++++++++++- src/gfx/canvas.onyx | 39 +++++++++++++++++++++++++- src/gfx/shader.onyx | 8 ++++-- src/main.onyx | 8 ++---- src/utils/vecmath.onyx | 12 ++++++-- 12 files changed, 159 insertions(+), 64 deletions(-) diff --git a/run_tree/scenes/default.items b/run_tree/scenes/default.items index 9940899..5b797fe 100644 --- a/run_tree/scenes/default.items +++ b/run_tree/scenes/default.items @@ -1,6 +1,5 @@ :beer name="Beer" texture_path="./assets/images/beer-1.png" -weight=12.34 diff --git a/run_tree/scenes/quick_save_new.scene b/run_tree/scenes/quick_save_new.scene index 4b15a33..ce7e1f9 100644 --- a/run_tree/scenes/quick_save_new.scene +++ b/run_tree/scenes/quick_save_new.scene @@ -1,26 +1,26 @@ [Wall] id = 10 flags = 2 -pos.x = 168.0000 -pos.y = 320.0000 -size.x = 336.0000 -size.y = 32.0000 +pos.x = 176.0000 +pos.y = 312.0000 +size.x = 352.0000 +size.y = 16.0000 [Wall] id = 11 flags = 2 -pos.x = 448.0000 -pos.y = 168.0000 -size.x = 32.0000 -size.y = 336.0000 +pos.x = 440.0000 +pos.y = 160.0000 +size.x = 16.0000 +size.y = 320.0000 [Player] id = 12 flags = 2 -pos.x = 342.9302 -pos.y = 205.3930 -size.x = 48.0000 -size.y = 48.0000 +pos.x = 452.6227 +pos.y = 356.0881 +size.x = 32.0000 +size.y = 32.0000 :PlayerComponent color.r = 1.0000 color.g = 1.0000 @@ -34,27 +34,27 @@ controls.left = 65 controls.right = 68 controls.interact = 70 controls.pick_up = 71 -facing = 4 +facing = 1 [Door] id = 13 flags = 3 pos.x = 352.0000 -pos.y = 320.0000 +pos.y = 312.0000 size.x = 160.0000 -size.y = 32.0000 +size.y = 16.0000 :DoorComponent max_openness = 0.8000 -target_openness = 0.0000 -openness = 0.0000 +target_openness = 0.8000 +openness = 0.8000 [Item_Entity] id = 14 flags = 4 -pos.x = 386.9302 -pos.y = 205.3930 -size.x = 32.0000 -size.y = 32.0000 +pos.x = 508.3851 +pos.y = 375.2260 +size.x = 16.0000 +size.y = 16.0000 :ItemComponent item = "beer" diff --git a/src/build.onyx b/src/build.onyx index cea7606..b949ecf 100644 --- a/src/build.onyx +++ b/src/build.onyx @@ -23,6 +23,7 @@ DEBUG :: false #load "entity/player" #load "entity/store" +#load "gfx/canvas" #load "gfx/font" #load "gfx/immediate" #load "gfx/mesh" diff --git a/src/entity/editor.onyx b/src/entity/editor.onyx index 4ec0f08..dcf2cf7 100644 --- a/src/entity/editor.onyx +++ b/src/entity/editor.onyx @@ -13,6 +13,7 @@ use package glfw3 Editor_Range :: struct {min, max: f32;} Editor_Disabled :: struct {} +Editor_Hidden :: struct {} Editor_Custom_Field :: struct { func: () -> void; } editor_init :: () { @@ -22,6 +23,7 @@ editor_init :: () { } editor_shown :: () => editor_openness != 0.0f || editor_target_openness != 0.0f; +editor_open_percent :: () => editor_openness; editor_toggle :: () { editor_target_openness = 1.0f - editor_target_openness; @@ -52,7 +54,7 @@ editor_update :: (dt: f32) { #local handle_placing_entities :: () { if active_index < 0 do return; - mouse_pos := mouse_get_position_vector(); + mouse_pos := mouse_get_position_vector() - scene_render_offset; if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) && mouse_pos.x < ~~window_width - sidebar_width && mouse_pos.y > menubar_height { schematic := scene.schematics.entries[active_index].value; @@ -66,7 +68,7 @@ editor_update :: (dt: f32) { } #local handle_entity_selction_and_dragging :: (dt: f32) { - mouse_pos := mouse_get_position_vector(); + mouse_pos := mouse_get_position_vector() - scene_render_offset; if mouse_pos.x < ~~window_width - sidebar_width && mouse_pos.y > menubar_height { if is_button_just_down(GLFW_MOUSE_BUTTON_LEFT) || is_button_just_down(GLFW_MOUSE_BUTTON_RIGHT) { @@ -98,7 +100,7 @@ editor_update :: (dt: f32) { if dragging { if editor_grid_shown { - new_top_left := mouse_get_position_vector(); + new_top_left := mouse_get_position_vector() - scene_render_offset; new_top_left.x = editor_grid_size * math.floor(new_top_left.x / editor_grid_size); new_top_left.y = editor_grid_size * math.floor(new_top_left.y / editor_grid_size); @@ -120,7 +122,7 @@ editor_update :: (dt: f32) { if resizing { if editor_grid_shown { rect := Entity.get_rect(selected_entity); - new_size := mouse_get_position_vector() - Rect.top_left(rect); + new_size := mouse_get_position_vector() - Rect.top_left(rect) - scene_render_offset; new_size.x = editor_grid_size * math.floor(new_size.x / editor_grid_size); new_size.y = editor_grid_size * math.floor(new_size.y / editor_grid_size); new_rect := Rect.{ rect.x, rect.y, new_size.x, new_size.y }; @@ -141,30 +143,31 @@ editor_update :: (dt: f32) { editor_draw :: () { if editor_grid_shown { - width := cast(f32) window_width; - height := cast(f32) window_height; + width := cast(f32) scene_canvas.width; + height := cast(f32) scene_canvas.height; xcount := cast(i32) math.ceil(height / editor_grid_size); ycount := cast(i32) math.ceil(width / editor_grid_size); immediate_set_color(.{1,1,0}); for xcount { - y := ~~it * editor_grid_size; - immediate_line(0, y, width, y); + y := ~~it * editor_grid_size + scene_render_offset.y; + immediate_line(scene_render_offset.x, y, width + scene_render_offset.x, y); } for ycount { - x := ~~it * editor_grid_size; - immediate_line(x, 0, x, height); + x := ~~it * editor_grid_size + scene_render_offset.x; + immediate_line(x, scene_render_offset.y, x, height + scene_render_offset.y); } } - scene->draw(); immediate_flush(); if selected_entity_id != Entity_Nothing { selected_entity := scene->get(selected_entity_id); r := Entity.get_rect(selected_entity); + r.x += scene_render_offset.x; + r.y += scene_render_offset.y; immediate_set_color(.{1,1,0,0.5}); immediate_rectangle(r.x-2, r.y-2, r.w+4, r.h+4); immediate_rectangle(r.x, r.y, r.w, r.h); @@ -284,6 +287,11 @@ editor_draw :: () { info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(v.type); for^ info.members { + for^ it.tags { + if it.type != type_expr do continue; + if *cast(^type_expr) it.data == Editor_Hidden do continue continue; + } + i += 1; y += Field_Height; diff --git a/src/entity/items.onyx b/src/entity/items.onyx index c53bb90..5229cca 100644 --- a/src/entity/items.onyx +++ b/src/entity/items.onyx @@ -4,7 +4,6 @@ use package core Item :: struct { name: str; - weight := 10.0f; color := Color.{ 1, 1, 1 }; texture_path : str; @@ -87,7 +86,9 @@ item_store_get_item :: (use this: ^Item_Store, id: str) -> ^Item { return items[id]; } -#local Item_Entity :: struct [Entity_Schematic.{create}] { +#local Item_Entity :: struct { + #struct_tag Entity_Schematic.{create} + create :: (scene) => { this := scene->make(); this.pos = .{0, 0}; @@ -123,7 +124,7 @@ item_store_get_item :: (use this: ^Item_Store, id: str) -> ^Item { ItemComponent :: struct { use base: Component; - [Editor_Custom_Field.{render_item_picker}] + #tag Editor_Custom_Field.{render_item_picker} item: str; } diff --git a/src/entity/manager.onyx b/src/entity/manager.onyx index 1f0dd33..d1b5787 100644 --- a/src/entity/manager.onyx +++ b/src/entity/manager.onyx @@ -21,8 +21,11 @@ Entity_ID :: #distinct u32 } Component :: struct { - [Entity_Store.Skip] use vtable: ^Component_Vtable; - [Entity_Store.Skip] type: type_expr; + #tag Editor_Hidden, Entity_Store.Skip + use vtable: ^Component_Vtable; + + #tag Editor_Hidden, Entity_Store.Skip + type: type_expr; } IsComponent :: interface (c: $C) { @@ -32,23 +35,30 @@ IsComponent :: interface (c: $C) { RenderComponent :: struct { use base: Component; func : (e: ^Entity) -> void; + + #struct_tag Entity_Store.Skip } -SizeComponent :: struct [Entity_Store.Skip] { +SizeComponent :: struct { use base: Component; func : (e: ^Entity) -> Rect; + + #struct_tag Entity_Store.Skip } -InteractableComponent :: struct [Entity_Store.Skip] { +InteractableComponent :: struct { use base: Component; interact: (e: ^Entity, interactor: ^Entity) -> void; + + #struct_tag Entity_Store.Skip } Entity :: struct { id: Entity_ID; flags: Entity_Flags; - [Entity_Store.Skip] schematic: type_expr; + #tag Entity_Store.Skip + schematic: type_expr; pos: Vector2; @@ -60,8 +70,9 @@ Entity :: struct { return Rect.{ pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y }; }; - [Entity_Store.Skip] + #tag Entity_Store.Skip components: Map(type_expr, ^Component); + has :: (use this: ^Entity, component_type: type_expr) => components->has(component_type); get :: (use this: ^Entity, $component_type: type_expr) => cast(^component_type) components[component_type]; add :: (use this: ^Entity, component: ^Component) => { diff --git a/src/entity/player.onyx b/src/entity/player.onyx index d4dad61..9118d79 100644 --- a/src/entity/player.onyx +++ b/src/entity/player.onyx @@ -45,7 +45,8 @@ facing_to_direction_vector :: macro (f: Facing) -> Vector2 { } } -#local Player :: struct [Entity_Schematic.{create}] { +#local Player :: struct { + #struct_tag Entity_Schematic.{create} create :: (scene: ^Entity_Manager) => player_create(scene, .{0,0}); } @@ -193,15 +194,17 @@ PlayerComponent :: struct { } } -#local Wall :: struct [Entity_Schematic.{create}] { - create :: (scene) => wall_create(scene, .{0,0}, .{0,0}); - - draw :: (use this: ^Entity) { +#local Wall :: struct { + render :: (use this: ^Entity) { immediate_set_color(.{1,1,1}); r := Entity.get_rect(this); immediate_rectangle(r.x, r.y, r.w, r.h); } + + #struct_tag Entity_Schematic.{ + (scene) => wall_create(scene, .{0,0}, .{0,0}) + } } wall_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity { @@ -211,18 +214,19 @@ wall_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity { this.flags |= .Solid; scene->create_and_add(this, RenderComponent) { - comp.func = Wall.draw; + comp.func = Wall.render; } return this; } player_assets: struct { - ["assets/images/player.png"] texture: Texture; + #tag "assets/images/player.png" + texture: Texture; } -#local Door :: struct [Entity_Schematic.{create}] { - create :: (scene) => door_create(scene, .{0, 0}, .{0, 0}); +#local Door :: struct { + create :: (scene) => door_create(scene, .Zero, .Zero); render :: (use this: ^Entity) { immediate_set_color(.{0.7, 0.7, 0.1}); @@ -244,6 +248,8 @@ player_assets: struct { door->toggle_open(); } } + + #struct_tag Entity_Schematic.{create} } DoorComponent :: struct { diff --git a/src/game.onyx b/src/game.onyx index d2ca9f5..29d421a 100644 --- a/src/game.onyx +++ b/src/game.onyx @@ -1,6 +1,7 @@ use package core use package glfw3 +use package opengles // // Game Global Variables @@ -9,7 +10,12 @@ use package glfw3 scene: Entity_Manager; item_store: Item_Store; +scene_render_offset: Vector2; +scene_canvas: Canvas; + game_init :: () { + scene_canvas = canvas_make(800, 600); + // This process of queueing the asset bucket should // be made automatic somehow... queue_assets(^player_assets); @@ -45,6 +51,27 @@ game_update :: (dt: f32) { } game_draw :: () { + canvas_use(^scene_canvas); + immediate_clear(.{0.15, 0.15, 0.2}); + scene->draw(); + immediate_flush(); + canvas_use(null); + + immediate_clear(.{0, 0, 0}); + + texture := canvas_to_texture(^scene_canvas); + view_rect: Rect; + view_rect.x = math.lerp(editor_open_percent(), cast(f32) ((window_width - scene_canvas.width) / 2), 0); + view_rect.y = ~~ ((window_height - scene_canvas.height) / 2); + view_rect.w = ~~ scene_canvas.width; + view_rect.h = ~~ scene_canvas.height; + scene_render_offset = Rect.top_left(view_rect); + + glDisable(GL_CULL_FACE); + immediate_image(^texture, view_rect.x, ~~window_height - view_rect.y, view_rect.w, -view_rect.h); + immediate_flush(); + glEnable(GL_CULL_FACE); + update_world_matrix(); update_model_matrix(.{0,0}); @@ -53,5 +80,4 @@ game_draw :: () { return; } - scene->draw(); } diff --git a/src/gfx/canvas.onyx b/src/gfx/canvas.onyx index d2f08e4..eb2af3f 100644 --- a/src/gfx/canvas.onyx +++ b/src/gfx/canvas.onyx @@ -4,21 +4,58 @@ use package opengles Canvas :: struct { + width, height: i32; + framebuffer: GLint; depth_stencil_buffer: GLint; color_texture: GLint; } -canvas_make :: () -> Canvas { +canvas_make :: (width, height: i32) -> Canvas { canvas: Canvas; + canvas.width = width; + canvas.height = height; + + glGenFramebuffers(1, ^canvas.framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, canvas.framebuffer); + + glGenTextures(1, ^canvas.color_texture); + glBindTexture(GL_TEXTURE_2D, canvas.color_texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, null); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas.color_texture, 0); + + glGenRenderbuffers(1, ^canvas.depth_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, canvas.depth_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, canvas.depth_stencil_buffer); + + if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE { + debug_log(.Error, "Framebuffer is not complete!"); + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return canvas; +} + +canvas_free :: (use canvas: ^Canvas) { + glDeleteFramebuffers(1, ^canvas.framebuffer); + glDeleteTextures(1, ^canvas.color_texture); + glDeleteRenderbuffers(1, ^canvas.depth_stencil_buffer); } canvas_use :: (use canvas: ^Canvas) { if canvas == null { glBindFramebuffer(GL_FRAMEBUFFER, 0); + update_view_matrix(window_width, window_height); } else { glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); + update_view_matrix(width, height); } } +canvas_to_texture :: (canvas: ^Canvas) => Texture.{ canvas.color_texture, canvas.width, canvas.height, 3, "" }; diff --git a/src/gfx/shader.onyx b/src/gfx/shader.onyx index 246c3d1..d2b05e7 100644 --- a/src/gfx/shader.onyx +++ b/src/gfx/shader.onyx @@ -74,12 +74,12 @@ shader_set_uniform :: (shader: Shader, uniform: cstr, value: $T) { } } -update_view_matrix :: () { +update_view_matrix :: (width, height: u32) { matrix : [16] f32; top := 0.0f; left := 0.0f; - right := cast(f32) window_width; - bottom := cast(f32) window_height; + right := cast(f32) width; + bottom := cast(f32) height; far := 10.0f; near := 0f; @@ -94,6 +94,8 @@ update_view_matrix :: () { glBindBuffer(GL_UNIFORM_BUFFER, window_matrix_block_buffer); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof typeof matrix, ^matrix); glBindBuffer(GL_UNIFORM_BUFFER, -1); + + glViewport(0, 0, width, height); } update_world_matrix :: () { diff --git a/src/main.onyx b/src/main.onyx index 12cdd27..3c7c6dd 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -34,8 +34,7 @@ init :: () { game_init(); glfwGetWindowSize(window, ^window_width, ^window_height); - glViewport(0, 0, window_width, window_height); - update_view_matrix(); + update_view_matrix(window_width, window_height); #if DEBUG { debug_font = font_lookup(.{"./assets/fonts/calibri.ttf", 16}); } } @@ -127,7 +126,7 @@ create_window :: () => { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); } - window := glfwCreateWindow(800, 600, #cstr "Bar simulator"); + window := glfwCreateWindow(1200, 900, #cstr "Bar simulator"); glfwMakeContextCurrent(window); glfwSwapInterval(1); @@ -136,10 +135,9 @@ create_window :: () => { } #export "on_resize" (window: GLFWwindow_p, width, height: u32) { - glViewport(0, 0, width, height); window_width = width; window_height = height; - update_view_matrix(); + update_view_matrix(width, height); } main :: (args) => { diff --git a/src/utils/vecmath.onyx b/src/utils/vecmath.onyx index 07423f5..9dbf7c1 100644 --- a/src/utils/vecmath.onyx +++ b/src/utils/vecmath.onyx @@ -1,14 +1,18 @@ -Vector2 :: struct [conv.Custom_Format.{format_vector2}] { +Vector2 :: struct { x, y: f32; mag :: macro (v: Vector2) => math.sqrt(v.x * v.x + v.y * v.y); + Zero :: Vector2.{0, 0} + + #struct_tag conv.Custom_Format.{format_vector2} } -Vector3i :: struct [conv.Custom_Format.{format_vector3i}] { +Vector3i :: struct { x, y, z: i32; + #struct_tag conv.Custom_Format.{format_vector3i} } -Vector3 :: struct [conv.Custom_Format.{format_vector3}] { +Vector3 :: struct { x, y, z: f32; mag :: macro (v: Vector3) => math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); @@ -39,6 +43,8 @@ Vector3 :: struct [conv.Custom_Format.{format_vector3}] { math.clamp(v.z, min.z, max.z), }; } + + #struct_tag conv.Custom_Format.{format_vector3} } #operator + macro (v1, v2: Vector2) => (typeof v1).{ v1.x + v2.x, v1.y + v2.y }; -- 2.25.1