From 769cda1d1fa628a583c193293b3c9e627cd1502f Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 19 Jul 2019 13:27:44 +0200 Subject: [PATCH] simplify gg; remove forced OpenGL dependency; graph builder /w hot code reloading --- compiler/parser.v | 13 +++++++- examples/hot_code_reloading/graph.v | 48 +++++++++++++-------------- examples/tetris/tetris.v | 44 +++++++++++-------------- vlib/gg/gg.v | 50 ++++++++++++++++++++++++++--- 4 files changed, 98 insertions(+), 57 deletions(-) diff --git a/compiler/parser.v b/compiler/parser.v index 0e40d9d382..547ff461ea 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -68,6 +68,7 @@ mut: can_chash bool attr string v_script bool // "V bash", import all os functions into global space + var_decl_name string // To allow declaring the variable so that it can be used in the struct initialization } const ( @@ -1173,6 +1174,7 @@ fn (p mut Parser) var_decl() { } // println('var decl tok=${p.strtok()} ismut=$is_mut') name := p.check_name() + p.var_decl_name = name // Don't allow declaring a variable with the same name. Even in a child scope // (shadowing is not allowed) if !p.builtin_pkg && p.cur_fn.known_var(name) { @@ -1186,6 +1188,7 @@ fn (p mut Parser) var_decl() { // Generate expression to tmp because we need its type first // [TYP .name =] bool_expression() pos := p.cgen.add_placeholder() + mut typ := p.bool_expression() // Option check ? or { or_else := p.tok == .key_orelse @@ -1228,6 +1231,7 @@ fn (p mut Parser) var_decl() { } p.cgen.set_placeholder(pos, nt_gen) } + p.var_decl_name = '' } fn (p mut Parser) bool_expression() string { @@ -1362,7 +1366,14 @@ fn (p mut Parser) name_expr() string { name = p.prepend_pkg(name) } // Variable - v := p.cur_fn.find_var(name) + mut v := p.cur_fn.find_var(name) + // A hack to allow `newvar := Foo{ field: newvar }` + // Declare the variable so that it can be used in the initialization + if name == 'main__' + p.var_decl_name { + v.name = p.var_decl_name + v.typ = 'voidptr' + v.is_mut = true + } if v.name.len != 0 { if ptr { p.gen('& /*vvar*/ ') diff --git a/examples/hot_code_reloading/graph.v b/examples/hot_code_reloading/graph.v index 387dcc38cc..18d6ebf6cd 100644 --- a/examples/hot_code_reloading/graph.v +++ b/examples/hot_code_reloading/graph.v @@ -1,9 +1,9 @@ module main import gx -import gl import gg -import glfw +import time +import glfw const ( WIDTH = 1000 @@ -12,36 +12,30 @@ const ( ) struct Context { - mut: gg *gg.GG } fn main() { glfw.init() - mut ctx := &Context{gg: 0} - window := glfw.create_window(glfw.WinCfg{ - title: 'graph builder' - width: 1000 - height: 1000 - ptr: ctx - }) - window.make_context_current() - gg.init() - ctx.gg = gg.new_context(gg.Cfg { - width: 1000 - height: 1000 - use_ortho: true - }) - for { - gl.clear() - gl.clear_color(255, 255, 255, 255) + ctx:= &Context{ + gg: gg.new_context(gg.Cfg { + width: WIDTH + height: HEIGHT + use_ortho: true + create_window: true + window_title: 'graph builder' + window_user_ptr: ctx + }) + } + for { + gg.clear(gx.White) ctx.draw() - window.swap_buffers() - glfw.wait_events() + ctx.gg.render() } } -fn (ctx mut Context) draw() { +[live] +fn (ctx & Context) draw() { // x axis ctx.gg.draw_line(0, HEIGHT / 2, WIDTH, HEIGHT / 2) // y axis @@ -50,9 +44,11 @@ fn (ctx mut Context) draw() { mut prev_y := f64(0) center := f64(WIDTH / 2) for x := f64(- 10); x <= f64(10); x += 0.01 { - y := x * x * f64(SCALE) - // gx.draw_line_c(center + prev_x, center+prev_y, center + int(x*float(10)), center+y, gx.BLACK) - ctx.gg.draw_rect(int(center) + int(x * f64(SCALE)), int(center - y), 1, 1, gx.Black) + //y := (x * x - 2) * f64(SCALE) + y := (1.0 / x) * f64(SCALE) + //ctx.gg.draw_line(int(center + prev_x), int(center+prev_y), + //int(center + x*f64(10)), int(center+y)) + ctx.gg.draw_rect(int(center) + int(x * f64(SCALE)), int(center - y), 2, 1, gx.Black) // gx.draw_rect_f(center + (x * f64(SCALE)), center - y, 1, 1, gx.BLACK) prev_x = x prev_y = y diff --git a/examples/tetris/tetris.v b/examples/tetris/tetris.v index 86d5713229..2a502f0d3d 100644 --- a/examples/tetris/tetris.v +++ b/examples/tetris/tetris.v @@ -104,41 +104,33 @@ struct Game { fn main() { glfw.init() - mut game := &Game{gg: 0} // TODO - game.parse_tetros() + mut game := &Game{ + gg: gg.new_context(gg.Cfg { + width: WinWidth + height: WinHeight + use_ortho: true // This is needed for 2D drawing + create_window: true + window_title: 'V Tetris' + window_user_ptr: game + }) + } game.init_game() - mut window := glfw.create_window(glfw.WinCfg { - width: WinWidth - height: WinHeight - title: 'V Tetris' - ptr: game // glfw user pointer - }) - window.make_context_current() - window.onkeydown(key_down) - gg.init() - game.gg = gg.new_context(gg.Cfg { - width: WinWidth - height: WinHeight - use_ortho: true // This is needed for 2D drawing - }) + game.gg.window.onkeydown(key_down) go game.run() // Run the game loop in a new thread - gl.clear() // For some reason this is necessary to avoid an intial flickering - gl.clear_color(255, 255, 255, 255) + gg.clear(gx.White) for { - gl.clear() - gl.clear_color(255, 255, 255, 255) + gg.clear(gx.White) game.draw_scene() - window.swap_buffers() - glfw.wait_events() - if window.should_close() { - window.destroy() - glfw.terminate() - exit(0) + game.gg.render() + if game.gg.window.should_close() { + game.gg.window.destroy() + return } } } fn (g mut Game) init_game() { + g.parse_tetros() rand.seed(time.now().uni) g.generate_tetro() g.field = []array_int // TODO: g.field = [][]int diff --git a/vlib/gg/gg.v b/vlib/gg/gg.v index 4a395b406b..9d1f8158fa 100644 --- a/vlib/gg/gg.v +++ b/vlib/gg/gg.v @@ -9,6 +9,7 @@ import glm import gl import gx import os +import glfw struct Vec2 { x int @@ -36,6 +37,7 @@ pub fn vec2(x, y int) Vec2 { } pub fn init() { + glfw.init() println(gl.TEXT_VERT) gl.init_glad() } @@ -49,7 +51,11 @@ struct Cfg { height int use_ortho bool retina bool + font_size int + create_window bool + window_user_ptr voidptr + window_title string } struct GG { @@ -64,12 +70,25 @@ struct GG { line_vbo u32 VBO u32 scale int // retina = 2 , normal = 1 +pub mut: + window *glfw.Window + render_fn fn() } + // fn new_context(width, height int, use_ortho bool, font_size int) *GG { pub fn new_context(cfg Cfg) *GG { - // println('new context orhto=$cfg.use_ortho') - // # glScissor(0,0,300,300); + mut window := &glfw.Window{!} + if cfg.create_window { + window = glfw.create_window(glfw.WinCfg{ + title: cfg.window_title + width: cfg.width + height: cfg.height + ptr: cfg.window_user_ptr + }) + window.make_context_current() + init() + } shader := gl.new_shader('simple') shader.use() if cfg.use_ortho { @@ -122,22 +141,45 @@ pub fn new_context(cfg Cfg) *GG { //gl.enable_vertex_attrib_array(0) //gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0) todo_remove_me(cfg, scale) - mut ctx := &GG { + return &GG { shader: shader width: cfg.width height: cfg.height VAO: vao VBO: vbo + window: window + // /line_vao: gl.gen_vertex_array() // /line_vbo: gl.gen_buffer() //text_ctx: new_context_text(cfg, scale), scale: scale // use_ortho: use_ortho } + // ctx.init_rect_vao() - return ctx + //return ctx } +/* +pub fn (gg &GG) render_loop() bool { + for !gg.window.show_close() { + gg.render_fn() + gg.window.swap_buffers() + glfw.wait_events() + } +} +*/ + +pub fn clear(color gx.Color) { + gl.clear() + gl.clear_color(255, 255, 255, 255) +} + +pub fn (gg &GG) render() { + gg.window.swap_buffers() + glfw.wait_events() +} + pub fn (ctx &GG) draw_triangle(x1, y1, x2, y2, x3, y3 f32, c gx.Color) { // println('draw_triangle $x1,$y1 $x2,$y2 $x3,$y3') ctx.shader.use()