diff --git a/Luxe/assets/AdventureButtons.image.lx b/Luxe/assets/AdventureButtons.image.lx new file mode 100644 index 0000000..d841dee --- /dev/null +++ b/Luxe/assets/AdventureButtons.image.lx @@ -0,0 +1,3 @@ +image = { + source = "assets/AdventureButtons.png" +} \ No newline at end of file diff --git a/Luxe/assets/AdventureButtons.png b/Luxe/assets/AdventureButtons.png new file mode 100644 index 0000000..e6cc41c Binary files /dev/null and b/Luxe/assets/AdventureButtons.png differ diff --git a/Luxe/assets/fonts/BabyBlocks.font.lx b/Luxe/assets/fonts/BabyBlocks.font.lx new file mode 100644 index 0000000..7860f10 --- /dev/null +++ b/Luxe/assets/fonts/BabyBlocks.font.lx @@ -0,0 +1,7 @@ +font = { + source = "assets/fonts/src/BabyBlocks.ttf" + ranges = [ + "0020-007F" + "00A0-00FF" + ] +} \ No newline at end of file diff --git a/Luxe/assets/fonts/src/BabyBlocks.ttf b/Luxe/assets/fonts/src/BabyBlocks.ttf new file mode 100644 index 0000000..bdf6269 Binary files /dev/null and b/Luxe/assets/fonts/src/BabyBlocks.ttf differ diff --git a/Luxe/assets/materials/WipButton.material.lx b/Luxe/assets/materials/WipButton.material.lx new file mode 100644 index 0000000..86cb525 --- /dev/null +++ b/Luxe/assets/materials/WipButton.material.lx @@ -0,0 +1,7 @@ +material = { + basis = "luxe: material_basis/sprite_pixelated" + inputs = { + sprite.color = [1 1 1 1] + sprite.uv = [0 0 1 1] + } +} \ No newline at end of file diff --git a/Luxe/assets/wip/Room.image.lx b/Luxe/assets/wip/Room.image.lx new file mode 100644 index 0000000..2070d31 --- /dev/null +++ b/Luxe/assets/wip/Room.image.lx @@ -0,0 +1,3 @@ +image = { + source = "assets/wip/Room.png" +} \ No newline at end of file diff --git a/Luxe/assets/wip/Room.png b/Luxe/assets/wip/Room.png new file mode 100644 index 0000000..a851a33 Binary files /dev/null and b/Luxe/assets/wip/Room.png differ diff --git a/Luxe/blocks/debug.wren b/Luxe/blocks/debug.wren index 642bd90..55de206 100644 --- a/Luxe/blocks/debug.wren +++ b/Luxe/blocks/debug.wren @@ -13,6 +13,14 @@ class DrawDebug{ Draw.commit(__context) } + static rect(r){ + rect(r.x, r.y, r.width, r.height) + } + + static rect(r, color){ + rect(r.x, r.y, r.width, r.height, color) + } + static rect(x, y, w, h){ rect(x, y, w, h, [1, 0, 0, 1]) } @@ -24,7 +32,7 @@ class DrawDebug{ static rect(x, y, w, h, col){ var style = PathStyle.new() style.color = col - Draw.quad(__context, x, y, 0, w, h, 0, col) + Draw.rect(__context, x, y, 0, w, h, 0, style) } } diff --git a/Luxe/blocks/tooltip.wren b/Luxe/blocks/tooltip.wren new file mode 100644 index 0000000..9a7351d --- /dev/null +++ b/Luxe/blocks/tooltip.wren @@ -0,0 +1,38 @@ +import "luxe: world" for Entity, Text, Transform +import "luxe: assets" for Assets + +import "globals" for Globals +import "math/vector" for Vector + +class Tooltip{ + construct new(app){ + _ent = Entity.create(app.ui) + _mat_font = Assets.material("luxe: material/font") + Text.create(_ent, _mat_font, 8, "assets/fonts/BabyBlocks", [1, 1, 1, 1]) + + Transform.create(_ent) + Transform.set_pos(_ent, 64, 128, 12) + Transform.set_snap(_ent, 1, 1, 0) + + _size = 8 + } + + tick(){ + var pos = Vector.new(Globals["UiMouse"]) + if(_active && pos){ + Transform.set_pos(_ent, pos.x, pos.y, 12) + } + } + + set(text){ + Text.set_text_buffer(_ent, text) + Text.commit(_ent) + _active = true + } + + clear(){ + Text.set_text_buffer(_ent, "") + Text.commit(_ent) + _active = false + } +} \ No newline at end of file diff --git a/Luxe/blocks/ui.wren b/Luxe/blocks/ui.wren index b5bc9a0..8c1684d 100644 --- a/Luxe/blocks/ui.wren +++ b/Luxe/blocks/ui.wren @@ -2,27 +2,60 @@ import "luxe: draw" for Draw, PathStyle import "luxe: world" for Entity, Transform, UI, UIRenderMode import "luxe: ui/control" for Control import "luxe: ui/panel" for UIPanel +import "luxe: ui/list" for UIList +import "luxe: ui/button" for UIButton +import "luxe: ui/image" for UIImage +import "luxe: assets" for Assets + +import "globals" for Globals +import "blocks/ui/image_button" for ImageButton class Ui{ + construct new(app){ + _ui = Entity.create(app.ui, "UI Root") - static setup(app){ - __ui = Entity.create(app.ui, "UI Root") - - var x = 0 - var y = app.width - var w = app.width - var h = app.height - app.width - + var ui_rect = Globals["UiRect"] - UI.create(__ui, x, y, w, h, 0, app.ui_camera) - UI.set_render_mode(__ui, UIRenderMode.world) + UI.create(_ui, ui_rect.x, ui_rect.y, ui_rect.width, ui_rect.height, 0, app.ui_camera) + UI.set_render_mode(_ui, UIRenderMode.world) + var list = UIList.create(_ui) + //todo: make list horizontal? + Control.set_pos(list, 0, ui_rect.height-16) + Control.set_size(list, ui_rect.width, 16) - var panel = UIPanel.create(__ui) - UIPanel.set_color(panel, [1, 0, 0, 1]) - Control.set_size(panel, w, h) + var adventureButtons = Assets.image("assets/AdventureButtons") + var tiles = 10 - //UI.commit(__ui) + for(i in 0...6){ + var button = UIButton.create(_ui) + Control.set_size(button, 16, 16) + UIButton.set_text(button, "%(i)") + UIButton.set_text_size(button, 10) + Control.set_pos(button, i*16, 0) + + var image = UIImage.create(_ui) + UIImage.set_image(image, adventureButtons) + UIImage.set_uv(image, i/tiles, 0, (i+1)/tiles, 1) + Control.child_add(button, image) + + UIList.add(list, button) + } + //UIList.refresh(list) //uncomment this when list learns not to be vertical + + _test = ImageButton.create(_ui) + UIImage.set_image(_test, adventureButtons) + ImageButton.set_state_change(_test) {|state, element| + if(state["press"]) { + System.print("heck %(element)") + } + } + + UI.commit(_ui) } + + test(){ + ImageButton.get_data(_test) + } } \ No newline at end of file diff --git a/Luxe/blocks/ui/image_button.wren b/Luxe/blocks/ui/image_button.wren new file mode 100644 index 0000000..71db4e1 --- /dev/null +++ b/Luxe/blocks/ui/image_button.wren @@ -0,0 +1,53 @@ +import "luxe: ui/image" for UIImage +import "luxe: world" for UIEvent +import "luxe: ui/control" for Control + +class ImageButton{ + static create(ent){ + var button = UIImage.create(ent) + var data = { + "hover": false, + "press": false, + "state_change": null + } + Control.set_state_data(button, data) + + Control.set_events(button) {|event| + var change = true + var data + if(event.type == UIEvent.enter){ + data = Control.get_state_data(button) + data["hover"] = true + } else if(event.type == UIEvent.exit) { + data = Control.get_state_data(button) + data["hover"] = false + } else if(event.type == UIEvent.press) { + data = Control.get_state_data(button) + data["press"] = true + } else if(event.type == UIEvent.release) { + data = Control.get_state_data(button) + data["press"] = false + } else { + change = false + } + if(change){ + var func = data["state_change"] + if(func){ + func.call(data, button) + } + } + } + + return button + } + + static set_state_change(control, fn){ + var data = Control.get_state_data(control) + data["state_change"] = fn + } + + static get_data(control){ + //System.print(Control.get_state_data(control)) + } +} + diff --git a/Luxe/game.wren b/Luxe/game.wren index ef7e96a..a388782 100644 --- a/Luxe/game.wren +++ b/Luxe/game.wren @@ -5,13 +5,17 @@ import "luxe: world" for World, Entity, Transform, Sprite, Values, Tags, Camera import "luxe: math" for Math import "luxe: draw" for Draw import "luxe: io" for IO +import "luxe: color" for Color import "outline/app" for App import "outline/Renderer" for Renderer import "blocks/ui" for Ui import "blocks/debug" for DrawDebug, Holder -import "globals" for ActiveRenderer +import "globals" for Globals import "math/vector" for Vector +import "math/rect" for AABB +import "math/util" for Util +import "blocks/tooltip" for Tooltip class game is Game { @@ -20,36 +24,38 @@ class game is Game { System.print("ready!") app = App.new() - Ui.setup(app) - - System.print("render size: %(app.width) x %(app.height) @ %(app.scale)x") + _ui = Ui.new(app) + _tooltip = Tooltip.new(app) + _tooltip.set("TEST") + setup() DrawDebug.setup(app.world) - _logo = Entity.create(app.world, "sprite") - Transform.create(_logo) - Transform.set_pos(_logo, app.width/2, app.height/2, 0) - Sprite.create(_logo, Assets.material("luxe: material/logo"), 16, 16) - - ActiveRenderer.x.events.listen(Renderer.on_change) { app.update_cam() } + Globals["Renderer"].events.listen(Renderer.on_change) { app.update_cam() } } //ready tick(delta) { var mouse_pos = Vector.new(Input.mouse_x(), Input.mouse_y()) - mouse_pos = ActiveRenderer.x.game_mouse(mouse_pos) - var pos = Camera.screen_point_to_world(app.camera, mouse_pos.x, mouse_pos.y) - - Transform.set_pos(_logo, pos.x + 5, pos.y-8, 0) + var game_mouse = Globals["Renderer"].game_mouse(mouse_pos) + Globals["GameMouse"] = Camera.screen_point_to_world(app.camera, game_mouse.x, game_mouse.y) + var ui_mouse = Globals["Renderer"].ui_mouse(mouse_pos) + Globals["UiMouse"] = Camera.screen_point_to_world(app.ui_camera, ui_mouse.x, ui_mouse.y) if(Input.key_state_released(Key.escape)) { IO.shutdown() } - app.tick(delta) + if(Input.key_state_pressed(Key.key_q)) { + _tooltip.cycle_size() + } + _ui.test() + DrawDebug.commit() + _tooltip.tick() + app.tick(delta) } //tick destroy() { @@ -59,6 +65,17 @@ class game is Game { } //destroy + setup(){ + var game_rect = Globals["GameRect"] + + var bg = Entity.create(app.world, "background") + Transform.create(bg) + Transform.set_pos(bg, 64, 64, -10) + + var material = Util.material_from_image_path("assets/wip/Room") + Sprite.create(bg, material, 128, 128) + } + app { _app } app=(v) { _app=v } diff --git a/Luxe/globals.wren b/Luxe/globals.wren index 23d88b6..b0d7653 100644 --- a/Luxe/globals.wren +++ b/Luxe/globals.wren @@ -1,3 +1,3 @@ -var ActiveRenderer = [null] +var Globals = {} \ No newline at end of file diff --git a/Luxe/math/rect.wren b/Luxe/math/rect.wren index f1704c6..c4f75a7 100644 --- a/Luxe/math/rect.wren +++ b/Luxe/math/rect.wren @@ -46,6 +46,10 @@ class AABB{ _height = height } + static ONE(){ + return new(0, 0, 1, 1) + } + static min_max(min, max){ return min_max(min.x, min.y, max.x, max.y) } @@ -64,4 +68,12 @@ class AABB{ static contains(one, other){ return one.max > other.max && one.min < other.min } + + static shrink(rect, amount){ + if(amount is Num){ + amount = [amount, amount] + } + var half_amount = [amount.x/2, amount.y/2] + return AABB.new(rect.pos + half_amount, rect.size - amount) + } } \ No newline at end of file diff --git a/Luxe/math/util.wren b/Luxe/math/util.wren new file mode 100644 index 0000000..0b33410 --- /dev/null +++ b/Luxe/math/util.wren @@ -0,0 +1,21 @@ +import "luxe: assets" for Assets +import "luxe: render" for Material + +class Util{ + static material_from_image_path(path){ + var image = Assets.image("assets/wip/Room") + return material_from_image(image) + } + + static material_from_image(image){ + var material = Material.create("luxe: material_basis/sprite_pixelated") + Material.set_image(material, 0, image) + return material + } + + static copy_list(from, to){ + for(i in 0...from.count){ + to[i] = from[i] + } + } +} \ No newline at end of file diff --git a/Luxe/math/vector.wren b/Luxe/math/vector.wren index ba7f6d8..4c29e49 100644 --- a/Luxe/math/vector.wren +++ b/Luxe/math/vector.wren @@ -14,9 +14,14 @@ class Vector { _y = y } - construct new(list){ - _x = list.x - _y = list.x + construct new(arg){ + if(arg is Num){ + _x = arg + _y = arg + } else { + _x = arg.x + _y = arg.y + } } construct new(){ @@ -24,6 +29,11 @@ class Vector { _y = 0 } + floor(){ + _x = _x.floor + _y = _y.floor + return this + } invert_x(){ _x = -_x @@ -42,11 +52,22 @@ class Vector { static or_gt(one, other){ return one.x > other.x || one.y > other.y } + + y0(){ + _y = 0 + return this + } + + x0(){ + _x = 0 + return this + } +(other){ - if(other is Vector || other is List) { - return Vector.new(x + other.x, y + other.y) + if(other is Num) { + return Vector.new(x + other, y + other) } + return Vector.new(x + other.x, y + other.y) } -(other){ diff --git a/Luxe/outline/app.wren b/Luxe/outline/app.wren index e32c2aa..d83ad38 100644 --- a/Luxe/outline/app.wren +++ b/Luxe/outline/app.wren @@ -1,7 +1,11 @@ import "luxe: world" for World, Camera, Entity, Transform import "luxe: render" for Render +import "luxe: bytes" for Floats + import "outline/Renderer" for Renderer -import "globals" for ActiveRenderer +import "globals" for Globals +import "math/rect" for AABB + class App { @@ -33,17 +37,19 @@ class App { Transform.create(_camera) Camera.create(_camera) Camera.set_default(_world, _camera) - Camera.ortho(_camera, 0, ActiveRenderer.x.height, ActiveRenderer.x.width, 0, -20, 20) _ui_camera = Entity.create(_ui_world, "app.ui_camera") Transform.create(_ui_camera) Camera.create(_ui_camera) Camera.set_default(_ui_world, _ui_camera) + update_cam() + } //new update_cam(){ - Camera.ortho(_camera, 0, ActiveRenderer.x.height, ActiveRenderer.x.width, 0, -20, 20) + Camera.ortho(_camera, 0, 128, 128, 0, -2000, 2000) + Camera.ortho(_ui_camera, 0, Globals["Renderer"].height, Globals["Renderer"].width, 0, -2000, 2000) } destroy() { @@ -74,10 +80,25 @@ class App { World.tick_world(_ui_world, delta) //render worlds - - World.render(_world, _camera, "game", {"clear_color":_color}) + render_empty("clear") + World.render(_world, _camera, "game", "", Globals["RelativeGameRect"].pos_size_list, {"clear_color":_color}) World.render(_ui_world, _ui_camera, "ui") + render_empty("copy_to_screen") } //tick + render_empty(path){ + //prepare data + if(!_empty_set) _empty_set = Render.create_set() + var floats = Floats.new(16) + + //and submit + Render.submit( + _empty_set, //empty render set + path, //render path pass to your renderer (origin of #1) + "", //the render target resource name + [0, 0, 1, 1], //region to render to + floats, floats) //matrices + } + } // diff --git a/Luxe/outline/renderer.wren b/Luxe/outline/renderer.wren index 98b88c3..4fef171 100644 --- a/Luxe/outline/renderer.wren +++ b/Luxe/outline/renderer.wren @@ -2,12 +2,14 @@ import "luxe: render" for Render, RenderLayerDesc, PassLayerDesc, LoadAction import "luxe: render" for SortType, ImageDesc, ImageType, PixelFormat, Image import "luxe: math" for Math import "luxe: io" for IO -import "globals" for ActiveRenderer +import "luxe: events" for Events + +import "math/math" for M +import "math/util" for Util import "math/vector" for Vector import "math/rect" for AABB +import "globals" for Globals import "blocks/debug" for Holder -import "math/math" for M -import "luxe: events" for Events class Renderer { @@ -26,7 +28,7 @@ class Renderer { events{_events} construct new() { - ActiveRenderer.x = this + Globals["Renderer"] = this _events = Events.new() @@ -50,6 +52,13 @@ class Renderer { System.print("game is now %(res.x) x %(res.y)") + Globals["GameRect"] = AABB.new((_gameRes.x - pixel_width) / 2, _gameRes.y - pixel_width, pixel_width, pixel_width) + Globals["UiRect"] = AABB.new(0, 0, _gameRes.x, _gameRes.y - pixel_width) + + + var relGameRect = AABB.new(Globals["GameRect"].pos.y0() / _gameRes, Vector.new(pixel_width) / _gameRes) + Globals["RelativeGameRect"] = relGameRect + _desc.width = res.x _desc.height = res.y @@ -66,6 +75,12 @@ class Renderer { return M.remap(screen.min, screen.max, window.min, window.max, mouse_pos) } + ui_mouse(mouse_pos){ + var window = AABB.new(0, 0, Render.window_w(), Render.window_h()) + var screen = AABB.new(_gameRect.min_x, Render.window_h() - _gameRect.max_y, _gameRect.width, _gameRect.height) //Y- mouse positions are the bane of my existance + return M.remap(screen.min, screen.max, window.min, window.max, mouse_pos) + } + ready() { update_targets() IO.on("engine.runtime.window.size_changed") {|type, data| @@ -83,6 +98,10 @@ class Renderer { game_render_path(ctx) } else if(ctx.path == "ui") { ui_render_path(ctx) + } else if(ctx.path == "copy_to_screen") { + target_to_screen(ctx) + } else if(ctx.path == "clear"){ + clear(ctx) } } //render_path @@ -97,6 +116,20 @@ class Renderer { ctx.layer_render("default", layer) + } //game_render_path + + ui_render_path(ctx) { + + var layer = RenderLayerDesc.new() + layer.dest.color[0].render_target = target + layer.dest.color[0].load_action = LoadAction.dont_care + layer.dest.depth.load_action = LoadAction.clear + + ctx.layer_render("default", layer) + + } //ui_render_path + + target_to_screen(ctx){ var out_pass = PassLayerDesc.new() out_pass.library = "shaders/upscale" out_pass.function = "upscale_top_center" @@ -111,17 +144,16 @@ class Renderer { } ctx.layer_pass(out_pass) + } - } //game_render_path - - ui_render_path(ctx) { - + clear(ctx){ var layer = RenderLayerDesc.new() - layer.dest.color[0].load_action = LoadAction.dont_care - layer.dest.depth.load_action = LoadAction.clear + layer.dest.color[0].render_target = target + layer.dest.color[0].clear_color = [0,0,0,1] + layer.dest.color[0].load_action = LoadAction.clear + layer.dest.depth.load_action = LoadAction.clear ctx.layer_render("default", layer) - - } //ui_render_path + } } //Renderer diff --git a/Luxe/outline/settings.settings.lx b/Luxe/outline/settings.settings.lx index f92c7cf..4f27870 100644 --- a/Luxe/outline/settings.settings.lx +++ b/Luxe/outline/settings.settings.lx @@ -9,8 +9,8 @@ engine = { } render = { - antialiasing = 2 - stencil = 8 - depth = 24 + antialiasing = 0 + stencil = 0 + depth = 0 } } \ No newline at end of file diff --git a/Luxe/shaders/clear.emsl b/Luxe/shaders/clear.emsl new file mode 100644 index 0000000..c9dbd7f --- /dev/null +++ b/Luxe/shaders/clear.emsl @@ -0,0 +1,38 @@ +input View { + mat4 mvp, + mat4 proj, + mat4 proj_inverse, + mat4 view, + mat4 world, //geometry.world atm + float2 fov, //fov.x, fov.y + float2 resolution, + float4 target_region, + float4 target_region_size +} + +input UniformShaderData { + #0 image2D image, + float4 rect, + bool flipy +} + +stage vertex vert_layer_pass( + input {}, + vertex in { + #0 float2 pos, + #1 float2 uv + }, + fragment out { float2 uv } +) { + out.uv = in.uv; + stage.pos = float4(in.pos, 0.0, 1.0); +} + +stage fragment clear( + input { View view, UniformShaderData pass }, + fragment in { float2 uv } +) { + + stage.color[0] = float4(1, 0, 0, 1) + return; +} \ No newline at end of file diff --git a/Luxe/shaders/wip_button.emsl b/Luxe/shaders/wip_button.emsl new file mode 100644 index 0000000..e69de29