// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. // Use of this source code is governed by an MIT license // that can be found in the LICENSE file. module gg2 import ( glm gx os sokol sokol.sapp sokol.sgl sokol.gfx sokol.sfons ) const ( default_font_size = 24 ) pub struct Config { pub: width int height int use_ortho bool retina bool resizable bool user_data voidptr font_size int font_path string create_window bool // window_user_ptr voidptr window_title string always_on_top bool scale int frame_fn fn(voidptr) bg_color gx.Color } pub struct GG { scale int // retina = 2 , normal = 1 pub mut: width int height int clear_pass C.sg_pass_action window C.sapp_desc render_fn fn() //////////// font fields fons &C.FONScontext font_normal int } // TODO remove globals __global g_fons &C.FONScontext __global g_font_normal int __global g_font_path string fn init_sokol_window() { desc := sg_desc{ mtl_device: sapp.metal_get_device() mtl_renderpass_descriptor_cb: sapp.metal_get_renderpass_descriptor mtl_drawable_cb: sapp.metal_get_drawable d3d11_device: sapp.d3d11_get_device() d3d11_device_context: sapp.d3d11_get_device_context() d3d11_render_target_view_cb: sapp.d3d11_get_render_target_view d3d11_depth_stencil_view_cb: sapp.d3d11_get_depth_stencil_view } gfx.setup(&desc) sgl_desc := sgl_desc_t{} sgl.setup(&sgl_desc) g_fons = sfons.create(512, 512, 1) if g_font_path.len == 0 || !os.exists(g_font_path) { println('failed to load font "$g_font_path"') return } bytes := os.read_bytes(g_font_path) or { println('failed to load font "$g_font_path"') return } g_font_normal = C.fonsAddFontMem(g_fons, 'sans', bytes.data, bytes.len, false) } pub fn new_context(cfg Config) &GG { //C.printf('new_context() %p\n', cfg.user_data) window := sapp_desc{ user_data: cfg.user_data init_userdata_cb: init_sokol_window frame_userdata_cb: cfg.frame_fn window_title: cfg.window_title.str html5_canvas_name: cfg.window_title.str width: cfg.width height: cfg.height high_dpi: true } g_font_path = cfg.font_path if cfg.use_ortho {} else {} return &GG{ width: cfg.width height: cfg.height window: window clear_pass: gfx.create_clear_pass(f32(cfg.bg_color.r) / 255.0, f32(cfg.bg_color.g) / 255.0, f32(cfg.bg_color.b) / 255.0, 1.0) scale: 1 // scale fons:0 } } pub fn (gg &GG) draw_text(x, y int, text string, cfg gx.TextCfg) { gg.fons.set_font(gg.font_normal) gg.fons.set_size(cfg.size) ascender := f32(0.0) descender := f32(0.0) lh := f32(0.0) gg.fons.vert_metrics(&ascender, &descender, &lh) color:= C.sfons_rgba(cfg.color.r, cfg.color.g, cfg.color.b, 255) C.fonsSetColor(gg.fons, color) C.fonsDrawText(gg.fons, x, y, text.str, 0) } pub fn (ctx &GG) draw_text_def(x, y int, text string) { cfg := gx.TextCfg { color: gx.Black size: default_font_size align: gx.align_left } ctx.draw_text(x, y, text, cfg) } pub fn (gg mut GG) init_font() { // TODO gg.fons =g_fons gg.font_normal=g_font_normal } pub fn (gg &GG) run() { sapp.run(&gg.window) } pub fn (ctx &GG) draw_rect(x, y, w, h f32, c gx.Color) { sgl.c4b(c.r, c.g, c.b, 128) sgl.begin_quads() sgl.v2f(x, y) sgl.v2f(x + w, y) sgl.v2f(x + w, y + h) sgl.v2f(x, y + h) sgl.end() } pub fn draw_rect(x, y, w, h f32, c gx.Color) { sgl.c4b(c.r, c.g, c.b, 128) sgl.begin_quads() sgl.v2f(x, y) sgl.v2f(x + w, y) sgl.v2f(x + w, y + h) sgl.v2f(x, y + h) sgl.end() } pub fn (gg &GG) draw_empty_rect(x, y, w, h f32, c gx.Color) { sgl.c4b(c.r, c.g, c.b, 128) sgl.begin_line_strip() sgl.v2f(x, y) sgl.v2f(x + w, y) sgl.v2f(x + w, y + h) sgl.v2f(x, y + h) sgl.v2f(x, y) sgl.end() } pub fn create_image(file string) u32 { // println('gg create image "$file"') if !os.exists(file) { println('gg create image no such file "$file"') return u32(0) } // img := stbi.load(file) // img.free() return 0 // texture } pub fn create_image_from_memory(buf byteptr) u32 { // texture := gl.gen_texture() // img := stbi.load_from_memory(buf) // img.free() return 0 // texture } pub fn (gg &GG) begin() { sgl.defaults() sgl.matrix_mode_projection() sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0) } pub fn (gg &GG) end() { gfx.begin_default_pass(gg.clear_pass, sapp.width(), sapp.height()) sgl.draw() gfx.end_pass() gfx.commit() wait_events() } pub fn (ctx &GG) draw_line(x, y, x2, y2 f32, color gx.Color) {} fn C.WaitMessage() pub fn wait_events() { unsafe { $if macos { # NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny # untilDate:[NSDate distantFuture] # inMode:NSDefaultRunLoopMode # dequeue:YES]; # [NSApp sendEvent:event]; } $if windows { C.WaitMessage() } } }