gg: make the Sokol based gg the default
parent
dd7ebf7fac
commit
6b6c9d6738
|
@ -108,10 +108,10 @@ jobs:
|
||||||
run: ./v build-examples
|
run: ./v build-examples
|
||||||
# - name: Test vsh
|
# - name: Test vsh
|
||||||
# run: ./v examples/v_script.vsh
|
# run: ./v examples/v_script.vsh
|
||||||
## - name: Test vid
|
- name: Test vid
|
||||||
## run: |
|
run: |
|
||||||
## git clone --depth 1 https://github.com/vlang/vid.git
|
git clone --depth 1 https://github.com/vlang/vid
|
||||||
## cd vid && ../v -o vid .
|
cd vid && ../v -o vid .
|
||||||
- name: Build V UI examples
|
- name: Build V UI examples
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 https://github.com/vlang/ui
|
git clone --depth 1 https://github.com/vlang/ui
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import gg2 as gg
|
import gg
|
||||||
import gx
|
import gx
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import gg
|
import gg
|
||||||
import freetype
|
import gg.ft
|
||||||
import gx
|
import gx
|
||||||
import glfw
|
import os
|
||||||
import time
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
win_width = 600
|
win_width = 600
|
||||||
|
@ -60,52 +59,46 @@ lines = text.split('\n')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
struct Context {
|
struct App {
|
||||||
mut:
|
mut:
|
||||||
gg &gg.GG
|
gg &gg.GG
|
||||||
ft &freetype.FreeType
|
ft &ft.FT
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_gui(mut game App){
|
||||||
|
x := ft.new({
|
||||||
|
font_size: 13
|
||||||
|
scale: 2
|
||||||
|
font_path: os.resource_abs_path('../assets/fonts/RobotoMono-Regular.ttf')
|
||||||
|
}) or { panic(err) }
|
||||||
|
game.ft = x
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
glfw.init_glfw()
|
mut app := &App{}
|
||||||
mut ctx := &Context{
|
app.gg = gg.new_context({
|
||||||
gg: gg.new_context(gg.Cfg {
|
|
||||||
width: win_width
|
width: win_width
|
||||||
height: win_height
|
height: win_height
|
||||||
use_ortho: true // This is needed for 2D drawing
|
use_ortho: true // This is needed for 2D drawing
|
||||||
create_window: true
|
create_window: true
|
||||||
window_title: 'Empty window'
|
window_title: 'Empty window'
|
||||||
|
user_data: app
|
||||||
|
bg_color: bg_color
|
||||||
|
init_fn: init_gui
|
||||||
|
frame_fn: frame
|
||||||
//window_user_ptr: ctx
|
//window_user_ptr: ctx
|
||||||
})
|
})
|
||||||
}
|
app.gg.run()
|
||||||
ctx.gg.window.set_user_ptr(ctx) // TODO remove this when `window_user_ptr:` works
|
|
||||||
gg.clear(bg_color)
|
|
||||||
// Try to load font
|
|
||||||
ctx.ft = freetype.new_context(gg.Cfg{
|
|
||||||
width: win_width
|
|
||||||
height: win_height
|
|
||||||
use_ortho: true
|
|
||||||
font_size: 13
|
|
||||||
scale: 2
|
|
||||||
})
|
|
||||||
for {
|
|
||||||
t := time.ticks()
|
|
||||||
gg.clear(bg_color)
|
|
||||||
ctx.draw()
|
|
||||||
ctx.gg.render()
|
|
||||||
println(time.ticks()-t)
|
|
||||||
if ctx.gg.window.should_close() {
|
|
||||||
ctx.gg.window.destroy()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut ctx Context) draw() {
|
fn frame(mut app App) {
|
||||||
|
app.ft.flush()
|
||||||
|
app.gg.begin()
|
||||||
mut y := 10
|
mut y := 10
|
||||||
for line in lines {
|
for line in lines {
|
||||||
ctx.ft.draw_text_def(10,y, line)
|
app.ft.draw_text_def(10,y, line)
|
||||||
y += 15
|
y += 30
|
||||||
}
|
}
|
||||||
|
app.gg.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ import os
|
||||||
import rand
|
import rand
|
||||||
import time
|
import time
|
||||||
import gx
|
import gx
|
||||||
import gg2 as gg
|
import gg
|
||||||
import gg2.ft
|
import gg.ft
|
||||||
import sokol.sapp
|
import sokol.sapp
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -139,7 +139,7 @@ struct Game {
|
||||||
|
|
||||||
const ( fpath = os.resource_abs_path('../assets/fonts/RobotoMono-Regular.ttf') )
|
const ( fpath = os.resource_abs_path('../assets/fonts/RobotoMono-Regular.ttf') )
|
||||||
fn init_gui(mut game Game){
|
fn init_gui(mut game Game){
|
||||||
x := ft.new({ font_path: fpath }) or {panic(err)}
|
x := ft.new({ font_path: fpath, scale: 2 }) or {panic(err)}
|
||||||
game.ft = x
|
game.ft = x
|
||||||
game.font_loaded = true
|
game.font_loaded = true
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,7 @@ fn main() {
|
||||||
init_fn: init_gui
|
init_fn: init_gui
|
||||||
frame_fn: frame
|
frame_fn: frame
|
||||||
event_fn: on_event
|
event_fn: on_event
|
||||||
|
scale: 2
|
||||||
)
|
)
|
||||||
game.init_game()
|
game.init_game()
|
||||||
go game.run() // Run the game loop in a new thread
|
go game.run() // Run the game loop in a new thread
|
||||||
|
|
|
@ -155,6 +155,8 @@ FONS_DEF void fonsDrawDebug(FONScontext* s, float x, float y);
|
||||||
|
|
||||||
#define FONS_NOTUSED(v) (void)sizeof(v)
|
#define FONS_NOTUSED(v) (void)sizeof(v)
|
||||||
|
|
||||||
|
#define FONS_USE_FREETYPE
|
||||||
|
|
||||||
#ifdef FONS_USE_FREETYPE
|
#ifdef FONS_USE_FREETYPE
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import gx
|
||||||
import os
|
import os
|
||||||
|
|
||||||
const (
|
const (
|
||||||
default_font_size = 24
|
default_font_size = 20
|
||||||
)
|
)
|
||||||
// TODO remove globals
|
// TODO remove globals
|
||||||
/*
|
/*
|
||||||
|
@ -18,14 +18,21 @@ __global g_font_path string
|
||||||
pub struct FT {
|
pub struct FT {
|
||||||
pub:
|
pub:
|
||||||
fons &C.FONScontext
|
fons &C.FONScontext
|
||||||
|
|
||||||
font_normal int
|
font_normal int
|
||||||
|
scale f32 = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
font_path string
|
font_path string
|
||||||
|
scale f32 = 1.0
|
||||||
|
font_size int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(c Config) ?&FT{
|
pub fn new(c Config) ?&FT{
|
||||||
|
if c.font_path == '' {
|
||||||
|
// Load default font
|
||||||
|
}
|
||||||
if c.font_path == '' || !os.exists(c.font_path) {
|
if c.font_path == '' || !os.exists(c.font_path) {
|
||||||
println('failed to load font "$c.font_path"')
|
println('failed to load font "$c.font_path"')
|
||||||
return none
|
return none
|
||||||
|
@ -38,13 +45,14 @@ pub fn new(c Config) ?&FT{
|
||||||
return &FT{
|
return &FT{
|
||||||
fons : fons
|
fons : fons
|
||||||
font_normal: C.fonsAddFontMem(fons, 'sans', bytes.data, bytes.len, false)
|
font_normal: C.fonsAddFontMem(fons, 'sans', bytes.data, bytes.len, false)
|
||||||
|
scale: c.scale
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ft &FT) draw_text(x, y int, text string, cfg gx.TextCfg) {
|
pub fn (ft &FT) draw_text(x, y int, text string, cfg gx.TextCfg) {
|
||||||
ft.fons.set_font(ft.font_normal)
|
ft.fons.set_font(ft.font_normal)
|
||||||
ft.fons.set_size(2*f32(cfg.size)) // TODO: is this 2* needed?
|
ft.fons.set_size(2.0 * ft.scale * f32(cfg.size))
|
||||||
C.fonsSetAlign(ft.fons, C.FONS_ALIGN_LEFT | C.FONS_ALIGN_TOP)
|
C.fonsSetAlign(ft.fons, C.FONS_ALIGN_LEFT | C.FONS_ALIGN_TOP)
|
||||||
color := C.sfons_rgba(cfg.color.r, cfg.color.g, cfg.color.b, 255)
|
color := C.sfons_rgba(cfg.color.r, cfg.color.g, cfg.color.b, 255)
|
||||||
C.fonsSetColor(ft.fons, color)
|
C.fonsSetColor(ft.fons, color)
|
633
vlib/gg/gg.v
633
vlib/gg/gg.v
|
@ -1,553 +1,210 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
module gg
|
module gg
|
||||||
|
|
||||||
import stbi
|
|
||||||
import glm
|
|
||||||
import gl
|
|
||||||
import gx
|
import gx
|
||||||
import os
|
import os
|
||||||
import glfw
|
import sokol
|
||||||
|
import sokol.sapp
|
||||||
|
import sokol.sgl
|
||||||
|
import sokol.gfx
|
||||||
|
|
||||||
pub struct Vec2 {
|
type FNvoidptr1 fn(voidptr)
|
||||||
pub:
|
type FNvoidptr2 fn(voidptr,voidptr)
|
||||||
x int
|
type FNFail fn(string,voidptr)
|
||||||
y int
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (v Vec2) str() string {
|
pub struct Config {
|
||||||
return 'Vec2{ x: $v.x y: $v.y }'
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn vec2(x, y int) Vec2 {
|
|
||||||
res := Vec2 {
|
|
||||||
x: x
|
|
||||||
y: y
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_gg() {
|
|
||||||
glfw.init_glfw()
|
|
||||||
gl.init_glad()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub struct Cfg {
|
|
||||||
pub:
|
pub:
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
use_ortho bool
|
use_ortho bool
|
||||||
retina bool
|
retina bool
|
||||||
resizable bool
|
resizable bool
|
||||||
decorated bool = true
|
user_data voidptr
|
||||||
|
|
||||||
font_size int
|
font_size int
|
||||||
font_path string
|
|
||||||
create_window bool
|
create_window bool
|
||||||
window_user_ptr voidptr
|
// window_user_ptr voidptr
|
||||||
window_title string
|
window_title string
|
||||||
always_on_top bool
|
always_on_top bool
|
||||||
scale int
|
scale f32 = 1.0
|
||||||
|
bg_color gx.Color
|
||||||
|
init_fn FNvoidptr1 = voidptr(0)
|
||||||
|
frame_fn FNvoidptr1 = voidptr(0)
|
||||||
|
event_fn FNvoidptr2 = voidptr(0)
|
||||||
|
cleanup_fn FNvoidptr1 = voidptr(0)
|
||||||
|
fail_fn FNFail = voidptr(0)
|
||||||
|
wait_events bool = false // set this to true for UIs, to save power
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type RenderFn fn()
|
|
||||||
pub struct GG {
|
pub struct GG {
|
||||||
shader gl.Shader
|
scale f32 = 1.0// retina = 2 , normal = 1
|
||||||
// use_ortho bool
|
|
||||||
vao u32
|
|
||||||
rect_vao u32
|
|
||||||
rect_vbo u32
|
|
||||||
line_vao u32
|
|
||||||
line_vbo u32
|
|
||||||
vbo u32
|
|
||||||
scale int // retina = 2 , normal = 1
|
|
||||||
//pub:
|
|
||||||
pub mut:
|
pub mut:
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
window &glfw.Window
|
clear_pass C.sg_pass_action
|
||||||
render_fn RenderFn
|
window C.sapp_desc
|
||||||
|
config Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gg_init_sokol_window(user_data voidptr) {
|
||||||
|
mut g := &GG(user_data)
|
||||||
|
desc := C.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 := C.sgl_desc_t{}
|
||||||
|
sgl.setup(&sgl_desc)
|
||||||
|
if g.config.init_fn != voidptr(0) {
|
||||||
|
g.config.init_fn( g.config.user_data )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// fn new_context(width, height int, use_ortho bool, font_size int) *GG {
|
fn gg_frame_fn(user_data voidptr) {
|
||||||
pub fn new_context(cfg Cfg) &GG {
|
mut g := &GG(user_data)
|
||||||
mut window := &glfw.Window(0)
|
if g.config.frame_fn != voidptr(0) {
|
||||||
if cfg.create_window {
|
g.config.frame_fn( g.config.user_data )
|
||||||
if cfg.resizable {
|
|
||||||
glfw.window_hint(C.GLFW_RESIZABLE, 1)
|
|
||||||
} else {
|
|
||||||
glfw.window_hint(C.GLFW_RESIZABLE, 0)
|
|
||||||
}
|
}
|
||||||
if cfg.decorated {
|
|
||||||
glfw.window_hint(C.GLFW_DECORATED, 1)
|
|
||||||
} else {
|
|
||||||
glfw.window_hint(C.GLFW_DECORATED, 0)
|
|
||||||
}
|
}
|
||||||
window = glfw.create_window(glfw.WinCfg{
|
|
||||||
title: cfg.window_title
|
fn gg_event_fn(e &C.sapp_event, user_data voidptr){
|
||||||
|
mut g := &GG(user_data)
|
||||||
|
if g.config.event_fn != voidptr(0) {
|
||||||
|
g.config.event_fn(e, g.config.user_data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gg_cleanup_fn(user_data voidptr){
|
||||||
|
mut g := &GG(user_data)
|
||||||
|
if g.config.cleanup_fn != voidptr(0) {
|
||||||
|
g.config.cleanup_fn(g.config.user_data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gg_fail_fn(msg charptr, user_data voidptr){
|
||||||
|
mut g := &GG(user_data)
|
||||||
|
vmsg := tos3(msg)
|
||||||
|
if g.config.fail_fn != voidptr(0) {
|
||||||
|
g.config.fail_fn(vmsg, g.config.user_data)
|
||||||
|
}else{
|
||||||
|
eprintln('gg error: $vmsg')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
pub fn new_context(cfg Config) &GG {
|
||||||
|
mut g := &GG{
|
||||||
width: cfg.width
|
width: cfg.width
|
||||||
height: cfg.height
|
height: cfg.height
|
||||||
ptr: cfg.window_user_ptr
|
clear_pass: gfx.create_clear_pass( f32(cfg.bg_color.r) / 255.0, f32(cfg.bg_color.g) / 255.0,
|
||||||
always_on_top: cfg.always_on_top
|
f32(cfg.bg_color.b) / 255.0, 1.0)
|
||||||
})
|
scale: cfg.scale //sapp.dpi_scale()// cfg.scale
|
||||||
window.make_context_current()
|
config: cfg
|
||||||
init_gg()
|
|
||||||
}
|
}
|
||||||
shader := gl.new_shader('simple')
|
|
||||||
shader.use()
|
//C.printf('new_context() %p\n', cfg.user_data)
|
||||||
if cfg.use_ortho {
|
window := C.sapp_desc{
|
||||||
projection := glm.ortho(0, f32(cfg.width), f32(cfg.height), 0)
|
user_data: g
|
||||||
shader.set_mat4('projection', projection)
|
init_userdata_cb: gg_init_sokol_window
|
||||||
}
|
frame_userdata_cb: gg_frame_fn
|
||||||
else {
|
event_userdata_cb: gg_event_fn
|
||||||
// TODO move to function (allow volt functions to return arrays without allocations)
|
fail_userdata_cb: gg_fail_fn
|
||||||
// i := glm.identity3()
|
cleanup_userdata_cb: gg_cleanup_fn
|
||||||
shader.set_mat4('projection', glm.identity())
|
window_title: cfg.window_title.str
|
||||||
}
|
html5_canvas_name: cfg.window_title.str
|
||||||
vao := gl.gen_vertex_array()
|
|
||||||
//println('new gg context VAO=$VAO')
|
|
||||||
vbo := gl.gen_buffer()
|
|
||||||
mut scale := 1
|
|
||||||
if cfg.retina {
|
|
||||||
scale = 2
|
|
||||||
}
|
|
||||||
gl.enable(C.GL_SCISSOR_TEST)
|
|
||||||
//gl.enable(GL_BLEND)
|
|
||||||
//# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
//println('new gg text context VAO=$VAO')
|
|
||||||
//gl.bind_vao(VAO)
|
|
||||||
//gl.bind_buffer(GL_ARRAY_BUFFER, VBO)
|
|
||||||
//gl.enable_vertex_attrib_array(0)
|
|
||||||
//gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0)
|
|
||||||
todo_remove_me(cfg, scale)
|
|
||||||
return &GG {
|
|
||||||
shader: shader
|
|
||||||
width: cfg.width
|
width: cfg.width
|
||||||
height: cfg.height
|
height: cfg.height
|
||||||
vao: vao
|
high_dpi: cfg.scale > 1
|
||||||
vbo: vbo
|
}
|
||||||
window: window
|
//b := sapp.high_dpi()
|
||||||
|
//println('scale=$g.scale high_dpi=$b')
|
||||||
// /line_vao: gl.gen_vertex_array()
|
if cfg.use_ortho {}
|
||||||
// /line_vbo: gl.gen_buffer()
|
else {}
|
||||||
//text_ctx: new_context_text(cfg, scale),
|
g.window = window
|
||||||
scale: scale
|
return g
|
||||||
// use_ortho: use_ortho
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ctx.init_rect_vao()
|
pub fn (gg &GG) run() {
|
||||||
//return ctx
|
sapp.run(&gg.window)
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
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_color(color.r, color.g, color.b, 255)
|
|
||||||
gl.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
ctx.shader.set_color('color', c)
|
|
||||||
vertices := [
|
|
||||||
x1, y1, 0,
|
|
||||||
x2, y2, 0,
|
|
||||||
x3, y3, 0,
|
|
||||||
] !
|
|
||||||
// bind the Vertex Array Object first, then bind and set vertex buffer(s),
|
|
||||||
// and then configure vertex attributes(s).
|
|
||||||
gl.bind_vao(ctx.vao)
|
|
||||||
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
|
||||||
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 3, 0)
|
|
||||||
gl.enable_vertex_attrib_array(0)
|
|
||||||
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
|
||||||
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO,
|
|
||||||
// but this rarely happens. Modifying other
|
|
||||||
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs
|
|
||||||
// (nor VBOs) when it's not directly necessary.
|
|
||||||
// gl.bind_vertex_array(uint(0))
|
|
||||||
// gl.bind_vertex_array(ctx.VAO)
|
|
||||||
gl.draw_arrays(C.GL_TRIANGLES, 0, 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_triangle_tex(x1, y1, x2, y2, x3, y3 f32, c gx.Color) {
|
|
||||||
ctx.shader.use()
|
|
||||||
ctx.shader.set_color('color', c)
|
|
||||||
ctx.shader.set_int('has_texture', 1)
|
|
||||||
vertices := [
|
|
||||||
x1, y1, 0, 0, 0, 0, 1, 1,
|
|
||||||
x2, y2, 0, 0, 0, 0, 1, 0,
|
|
||||||
x3, y3, 0, 0, 0, 0, 0, 0,
|
|
||||||
] !
|
|
||||||
gl.bind_vao(ctx.vao)
|
|
||||||
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
|
||||||
// position attribute
|
|
||||||
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 3, 0)
|
|
||||||
gl.enable_vertex_attrib_array(0)
|
|
||||||
// color attribute
|
|
||||||
gl.vertex_attrib_pointer(1, 3, C.GL_FLOAT, false, 8, 3)
|
|
||||||
gl.enable_vertex_attrib_array(1)
|
|
||||||
// texture attribute
|
|
||||||
gl.vertex_attrib_pointer(2, 2, C.GL_FLOAT, false, 8, 6)
|
|
||||||
gl.enable_vertex_attrib_array(2)
|
|
||||||
// /
|
|
||||||
// gl.draw_arrays(GL_TRIANGLES, 0, 3)
|
|
||||||
gl.draw_elements(C.GL_TRIANGLES, 6, C.GL_UNSIGNED_INT, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_rect(x, y, w, h f32, c gx.Color) {
|
pub fn (ctx &GG) draw_rect(x, y, w, h f32, c gx.Color) {
|
||||||
// println('gg.draw_rect($x,$y,$w,$h)')
|
sgl.c4b(c.r, c.g, c.b, 128)
|
||||||
// wrong order
|
sgl.begin_quads()
|
||||||
// // ctx.draw_triangle(x, y, x + w, y, x + w, y + h, c)
|
sgl.v2f(x * ctx.scale, y * ctx.scale)
|
||||||
// // ctx.draw_triangle(x, y, x, y + h, x + w, y + h, c)
|
sgl.v2f((x + w) * ctx.scale, y * ctx.scale)
|
||||||
// good order. counter clockwise
|
sgl.v2f((x + w) * ctx.scale, (y + h) * ctx.scale)
|
||||||
// ctx.draw_triangle(x, y, x, y + h, x + w, y + h, c)
|
sgl.v2f(x * ctx.scale, (y + h) * ctx.scale)
|
||||||
// ctx.draw_triangle(x, y, x + w, y + h, x + w, y, c)
|
sgl.end()
|
||||||
ctx.draw_rect2(x, y, w, h, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Useful for debugging meshes.
|
pub fn (gg &GG) draw_empty_rect(x, y, w, h f32, c gx.Color) {
|
||||||
pub fn set_mode_wireframe() {
|
sgl.c4b(c.r, c.g, c.b, 128)
|
||||||
C.glPolygonMode(C.GL_FRONT_AND_BACK, C.GL_LINE)
|
sgl.begin_line_strip()
|
||||||
}
|
sgl.v2f(x, y)
|
||||||
pub fn set_mode_point() {
|
sgl.v2f(x + w, y)
|
||||||
C.glPolygonMode(C.GL_FRONT_AND_BACK, C.GL_POINT)
|
sgl.v2f(x + w, y + h)
|
||||||
}
|
sgl.v2f(x, y + h)
|
||||||
pub fn set_mode_fill() {
|
sgl.v2f(x, y)
|
||||||
C.glPolygonMode(C.GL_FRONT_AND_BACK, C.GL_FILL)
|
sgl.end()
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
fn (mut ctx GG) init_rect_vao() {
|
|
||||||
|
|
||||||
ctx.rect_vao = gl.gen_vertex_array()
|
|
||||||
ctx.rect_vbo = gl.gen_buffer()
|
|
||||||
vertices := [
|
|
||||||
x + w, y, 0,
|
|
||||||
x + w, y + h, 0,
|
|
||||||
x, y + h, 0,
|
|
||||||
x, y, 0,
|
|
||||||
] !
|
|
||||||
indices := [
|
|
||||||
0, 1, 3,// first triangle
|
|
||||||
1, 2, 3// second triangle
|
|
||||||
] !
|
|
||||||
gl.bind_vao(ctx.rect_vao)
|
|
||||||
gl.set_vbo(ctx.rect_vbo, vertices, C.GL_STATIC_DRAW)
|
|
||||||
ebo := gl.gen_buffer()
|
|
||||||
// ///////
|
|
||||||
gl.set_ebo(ebo, indices, C.GL_STATIC_DRAW)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
pub fn (ctx &GG) draw_rect2(x, y, w, h f32, c gx.Color) {
|
|
||||||
C.glDeleteBuffers(1, &ctx.vao)
|
|
||||||
C.glDeleteBuffers(1, &ctx.vbo)
|
|
||||||
ctx.shader.use()
|
|
||||||
ctx.shader.set_color('color', c)
|
|
||||||
ctx.shader.set_int('has_texture', 0)
|
|
||||||
// 4--1
|
|
||||||
// 3--2
|
|
||||||
$if linux {
|
|
||||||
// y += h
|
|
||||||
}
|
|
||||||
vertices := [
|
|
||||||
x + w, y, 0,
|
|
||||||
x + w, y + h, 0,
|
|
||||||
x, y + h, 0,
|
|
||||||
x, y, 0,
|
|
||||||
] !
|
|
||||||
indices := [
|
|
||||||
0, 1, 3,// first triangle
|
|
||||||
1, 2, 3// second triangle
|
|
||||||
] !
|
|
||||||
gl.bind_vao(ctx.vao)
|
|
||||||
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
|
||||||
ebo := gl.gen_buffer()
|
|
||||||
// ///////
|
|
||||||
gl.set_ebo(ebo, indices, C.GL_STATIC_DRAW)// !!! LEAKS
|
|
||||||
// /////
|
|
||||||
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 3, 0)
|
|
||||||
gl.enable_vertex_attrib_array(0)
|
|
||||||
// gl.bind_vao(ctx.rect_vao)
|
|
||||||
gl.bind_vao(ctx.vao)
|
|
||||||
gl.draw_elements(C.GL_TRIANGLES, 6, C.GL_UNSIGNED_INT, 0)
|
|
||||||
C.glDeleteBuffers(1, &ebo)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn todo_remove_me(cfg Cfg, scale int) {
|
|
||||||
// Can only have text in ortho mode
|
|
||||||
if !cfg.use_ortho {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
width := cfg.width * scale
|
|
||||||
height := cfg.height * scale
|
|
||||||
//font_size := cfg.font_size * scale
|
|
||||||
gl.enable(C.GL_BLEND)
|
|
||||||
//# glBlendFunc(C.GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
shader := gl.new_shader('text')
|
|
||||||
shader.use()
|
|
||||||
projection := glm.ortho(0, f32(width), 0, f32(height))// 0 at BOT
|
|
||||||
// projection_new := ortho(0, width, 0, height)// 0 at BOT
|
|
||||||
// projection := gl.ortho(0, width,height,0) // 0 at TOP
|
|
||||||
shader.set_mat4('projection', projection)
|
|
||||||
vao := gl.gen_vertex_array()
|
|
||||||
//println('new gg text context VAO=$VAO')
|
|
||||||
vbo := gl.gen_buffer()
|
|
||||||
gl.bind_vao(vao)
|
|
||||||
gl.bind_buffer(C.GL_ARRAY_BUFFER, vbo)
|
|
||||||
gl.enable_vertex_attrib_array(0)
|
|
||||||
gl.vertex_attrib_pointer(0, 4, C.GL_FLOAT, false, 4, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update() {
|
|
||||||
// # ui__post_empty_event();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post_empty_event() {
|
|
||||||
glfw.post_empty_event()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (c GG) circle(x, y, r int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) fill_color(color gx.Color) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) fill() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) move_to(x, y int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) line_to(x, y int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) stroke_width(size int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) stroke_color(color gx.Color) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) stroke() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) save() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) restore() {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) intersect_scissor(x, y, w, h int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) translate(x, y int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) create_font(name, file string) int {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) text(x, y int, text string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) text_box(x, y, max int, text string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) font_face(f string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) font_size(size int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (c GG) text_align(a int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (ctx &GG) create_image(file string) u32 {
|
|
||||||
return create_image(file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_image(file string) u32 {
|
pub fn create_image(file string) u32 {
|
||||||
// println('gg create image "$file"')
|
// println('gg create image "$file"')
|
||||||
if file.contains('twitch') {
|
|
||||||
return u32(0)// TODO
|
|
||||||
}
|
|
||||||
if !os.exists(file) {
|
if !os.exists(file) {
|
||||||
println('gg create image no such file "$file"')
|
println('gg create image no such file "$file"')
|
||||||
return u32(0)
|
return u32(0)
|
||||||
}
|
}
|
||||||
texture := gl.gen_texture()
|
// img := stbi.load(file)
|
||||||
img := stbi.load(file)
|
// img.free()
|
||||||
gl.bind_2d_texture(texture)
|
return 0 // texture
|
||||||
img.tex_image_2d()
|
|
||||||
gl.generate_mipmap(C.GL_TEXTURE_2D)
|
|
||||||
img.free()
|
|
||||||
return texture
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_image_from_memory(buf byteptr) u32 {
|
pub fn create_image_from_memory(buf byteptr) u32 {
|
||||||
texture := gl.gen_texture()
|
// texture := gl.gen_texture()
|
||||||
img := stbi.load_from_memory(buf)
|
// img := stbi.load_from_memory(buf)
|
||||||
// TODO copy pasta
|
// img.free()
|
||||||
gl.bind_2d_texture(texture)
|
return 0 // texture
|
||||||
img.tex_image_2d()
|
|
||||||
gl.generate_mipmap(C.GL_TEXTURE_2D)
|
|
||||||
img.free()
|
|
||||||
return texture
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_line(x, y, x2, y2 f32, color gx.Color) {
|
pub fn (gg &GG) begin() {
|
||||||
ctx.use_color_shader(color)
|
sgl.defaults()
|
||||||
vertices := [x, y, x2, y2] !
|
sgl.matrix_mode_projection()
|
||||||
ctx.bind_vertices(vertices)
|
sgl.ortho(0.0, f32(sapp.width()), f32(sapp.height()), 0.0, -1.0, 1.0)
|
||||||
gl.draw_arrays(C.GL_LINES, 0, 2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_arc(x, y, r, start_angle, end_angle f32, segments int, color gx.Color) {
|
pub fn (gg &GG) end() {
|
||||||
ctx.use_color_shader(color)
|
gfx.begin_default_pass(gg.clear_pass, sapp.width(), sapp.height())
|
||||||
vertices := arc_vertices(x, y, r, start_angle, end_angle, segments)
|
sgl.draw()
|
||||||
ctx.bind_vertices(vertices)
|
gfx.end_pass()
|
||||||
gl.draw_arrays(C.GL_LINE_STRIP, 0, segments + 1)
|
gfx.commit()
|
||||||
unsafe { vertices.free() }
|
if gg.config.wait_events {
|
||||||
|
wait_events()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_filled_arc(x, y, r, start_angle, end_angle f32, segments int, color gx.Color) {
|
pub fn (ctx &GG) draw_line(x, y, x2, y2 f32, color gx.Color) {}
|
||||||
ctx.use_color_shader(color)
|
|
||||||
|
|
||||||
|
fn C.WaitMessage()
|
||||||
|
|
||||||
mut vertices := []f32{}
|
pub fn wait_events() {
|
||||||
vertices << [x, y] !
|
unsafe {
|
||||||
vertices << arc_vertices(x, y, r, start_angle, end_angle, segments)
|
$if macos {
|
||||||
ctx.bind_vertices(vertices)
|
# NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||||
gl.draw_arrays(C.GL_TRIANGLE_FAN, 0, segments + 2)
|
# untilDate:[NSDate distantFuture]
|
||||||
unsafe { vertices.free() }
|
# inMode:NSDefaultRunLoopMode
|
||||||
|
# dequeue:YES];
|
||||||
|
# [NSApp sendEvent:event];
|
||||||
}
|
}
|
||||||
|
$if windows {
|
||||||
pub fn (ctx &GG) draw_circle(x, y, r f32, color gx.Color) {
|
C.WaitMessage()
|
||||||
ctx.draw_filled_arc(x, y, r, 0, 360, 24 + int(r / 2), color)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_rounded_rect(x, y, w, h, r f32, color gx.Color) {
|
|
||||||
ctx.use_color_shader(color)
|
|
||||||
mut vertices := []f32{}
|
|
||||||
segments := 6 + int(r / 8)
|
|
||||||
|
|
||||||
// Create a rounded rectangle using a triangle fan mesh.
|
|
||||||
vertices << [x + (w/2.0), y + (h/2.0)] !
|
|
||||||
vertices << arc_vertices(x + w - r, y + h - r, r, 0, 90, segments)
|
|
||||||
vertices << arc_vertices(x + r, y + h - r, r, 90, 180, segments)
|
|
||||||
vertices << arc_vertices(x + r, y + r, r, 180, 270, segments)
|
|
||||||
vertices << arc_vertices(x + w - r, y + r, r, 270, 360, segments)
|
|
||||||
// Finish the loop by going back to the first vertex
|
|
||||||
vertices << [vertices[2], vertices[3]] !
|
|
||||||
|
|
||||||
ctx.bind_vertices(vertices)
|
|
||||||
gl.draw_arrays(C.GL_TRIANGLE_FAN, 0, segments * 4 + 6)
|
|
||||||
unsafe { vertices.free() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &GG) draw_empty_rounded_rect(x, y, w, h, r f32, color gx.Color) {
|
|
||||||
ctx.use_color_shader(color)
|
|
||||||
mut vertices := []f32{}
|
|
||||||
segments := 6 + int(r / 8)
|
|
||||||
|
|
||||||
vertices << arc_vertices(x + w - r, y + h - r, r, 0, 90, segments)
|
|
||||||
vertices << arc_vertices(x + r, y + h - r, r, 90, 180, segments)
|
|
||||||
vertices << arc_vertices(x + r, y + r, r, 180, 270, segments)
|
|
||||||
vertices << arc_vertices(x + w - r, y + r, r, 270, 360, segments)
|
|
||||||
|
|
||||||
ctx.bind_vertices(vertices)
|
|
||||||
gl.draw_arrays(C.GL_LINE_STRIP, 0, segments * 4 + 1)
|
|
||||||
unsafe { vertices.free() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
pub fn (c &GG) draw_gray_line(x, y, x2, y2 f32) {
|
|
||||||
c.draw_line(x, y, x2, y2, gx.gray)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (c &GG) draw_vertical(x, y, height int) {
|
|
||||||
c.draw_line(x, y, x, y + height)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//ctx.gg.draw_line(center + prev_x, center+prev_y, center + x*10.0, center+y)
|
|
||||||
|
|
||||||
// fn (ctx &GG) draw_image(x, y, w, h f32, img stbi.Image) {
|
|
||||||
pub fn (ctx &GG) draw_image(x, y, w, h f32, tex_id u32) {
|
|
||||||
|
|
||||||
// NB: HACK to ensure same state ... TODO: remove next line
|
|
||||||
ctx.draw_empty_rect(0,0,0,0, gx.white)
|
|
||||||
|
|
||||||
last_array_buffer := 0
|
|
||||||
last_texture := 0
|
|
||||||
C.glGetIntegerv(C.GL_ARRAY_BUFFER_BINDING, &last_array_buffer)
|
|
||||||
C.glGetIntegerv(C.GL_TEXTURE_BINDING_2D, &last_texture)
|
|
||||||
|
|
||||||
// println('DRAW IMAGE $x $y $w $h $tex_id')
|
|
||||||
ctx.shader.use()
|
|
||||||
// ctx.shader.set_color('color', c)
|
|
||||||
ctx.shader.set_int('has_texture', 1)
|
|
||||||
// 4--1
|
|
||||||
// | |
|
|
||||||
// 3--2
|
|
||||||
vertices := [
|
|
||||||
x + w, y, 0, 1, 0, 0, 1, 1,
|
|
||||||
x + w, y + h, 0, 0, 1, 0, 1, 0,
|
|
||||||
x, y + h, 0, 0, 0, 1, 0, 0,
|
|
||||||
x, y, 0, 1, 1, 0, 0, 1,
|
|
||||||
] !
|
|
||||||
indices := [
|
|
||||||
0, 1, 3,// first triangle
|
|
||||||
1, 2, 3// second triangle
|
|
||||||
] !
|
|
||||||
// VAO := gl.gen_vertex_array()
|
|
||||||
// VBO := gl.gen_buffer()
|
|
||||||
C.glEnable(C.GL_TEXTURE_2D)
|
|
||||||
gl.bind_vao(ctx.vao)
|
|
||||||
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
|
||||||
ebo := gl.gen_buffer()
|
|
||||||
gl.set_ebo(ebo, indices, C.GL_STATIC_DRAW)
|
|
||||||
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 8, 0)
|
|
||||||
gl.enable_vertex_attrib_array(0)
|
|
||||||
gl.vertex_attrib_pointer(1, 3, C.GL_FLOAT, false, 8, 3)
|
|
||||||
gl.enable_vertex_attrib_array(1)
|
|
||||||
gl.vertex_attrib_pointer(2, 2, C.GL_FLOAT, false, 8, 6)
|
|
||||||
gl.enable_vertex_attrib_array(2)
|
|
||||||
gl.bind_2d_texture(tex_id)
|
|
||||||
gl.bind_vao(ctx.vao)
|
|
||||||
gl.draw_elements(C.GL_TRIANGLES, 6, C.GL_UNSIGNED_INT, 0)
|
|
||||||
C.glDisable(C.GL_TEXTURE_2D)
|
|
||||||
// restore state
|
|
||||||
C.glBindBuffer(C.GL_ARRAY_BUFFER, last_array_buffer)
|
|
||||||
C. glBindTexture(C.GL_TEXTURE_2D, last_texture)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (c &GG) draw_empty_rect(x, y, w, h f32, color gx.Color) {
|
|
||||||
c.draw_line(x, y, x + w, y, color)
|
|
||||||
c.draw_line(x, y, x, y + h, color)
|
|
||||||
c.draw_line(x, y + h, x + w, y + h, color)
|
|
||||||
c.draw_line(x + w, y, x + w, y + h, color)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scissor(x, y, w, h f32) {
|
|
||||||
C.glScissor(x, y, w, h)
|
|
||||||
}
|
}
|
||||||
|
|
218
vlib/gg2/gg.v
218
vlib/gg2/gg.v
|
@ -1,218 +0,0 @@
|
||||||
// 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 gx
|
|
||||||
import os
|
|
||||||
import sokol
|
|
||||||
import sokol.sapp
|
|
||||||
import sokol.sgl
|
|
||||||
import sokol.gfx
|
|
||||||
|
|
||||||
type FNvoidptr1 fn(voidptr)
|
|
||||||
type FNvoidptr2 fn(voidptr,voidptr)
|
|
||||||
type FNFail fn(string,voidptr)
|
|
||||||
|
|
||||||
pub struct Config {
|
|
||||||
pub:
|
|
||||||
width int
|
|
||||||
height int
|
|
||||||
use_ortho bool
|
|
||||||
retina bool
|
|
||||||
resizable bool
|
|
||||||
user_data voidptr
|
|
||||||
font_size int
|
|
||||||
create_window bool
|
|
||||||
// window_user_ptr voidptr
|
|
||||||
window_title string
|
|
||||||
always_on_top bool
|
|
||||||
scale int
|
|
||||||
bg_color gx.Color
|
|
||||||
init_fn FNvoidptr1 = voidptr(0)
|
|
||||||
frame_fn FNvoidptr1 = voidptr(0)
|
|
||||||
event_fn FNvoidptr2 = voidptr(0)
|
|
||||||
cleanup_fn FNvoidptr1 = voidptr(0)
|
|
||||||
fail_fn FNFail = voidptr(0)
|
|
||||||
wait_events bool = false // set this to true for UIs, to save power
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
config Config
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gg_init_sokol_window(user_data voidptr) {
|
|
||||||
mut g := &GG(user_data)
|
|
||||||
desc := C.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 := C.sgl_desc_t{}
|
|
||||||
sgl.setup(&sgl_desc)
|
|
||||||
if g.config.init_fn != voidptr(0) {
|
|
||||||
g.config.init_fn( g.config.user_data )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gg_frame_fn(user_data voidptr) {
|
|
||||||
mut g := &GG(user_data)
|
|
||||||
if g.config.frame_fn != voidptr(0) {
|
|
||||||
g.config.frame_fn( g.config.user_data )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gg_event_fn(e &C.sapp_event, user_data voidptr){
|
|
||||||
mut g := &GG(user_data)
|
|
||||||
if g.config.event_fn != voidptr(0) {
|
|
||||||
g.config.event_fn(e, g.config.user_data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gg_cleanup_fn(user_data voidptr){
|
|
||||||
mut g := &GG(user_data)
|
|
||||||
if g.config.cleanup_fn != voidptr(0) {
|
|
||||||
g.config.cleanup_fn(g.config.user_data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gg_fail_fn(msg charptr, user_data voidptr){
|
|
||||||
mut g := &GG(user_data)
|
|
||||||
vmsg := tos3(msg)
|
|
||||||
if g.config.fail_fn != voidptr(0) {
|
|
||||||
g.config.fail_fn(vmsg, g.config.user_data)
|
|
||||||
}else{
|
|
||||||
eprintln('gg error: $vmsg')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
pub fn new_context(cfg Config) &GG {
|
|
||||||
mut g := &GG{
|
|
||||||
width: cfg.width
|
|
||||||
height: cfg.height
|
|
||||||
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
|
|
||||||
config: cfg
|
|
||||||
}
|
|
||||||
|
|
||||||
//C.printf('new_context() %p\n', cfg.user_data)
|
|
||||||
window := C.sapp_desc{
|
|
||||||
user_data: g
|
|
||||||
init_userdata_cb: gg_init_sokol_window
|
|
||||||
frame_userdata_cb: gg_frame_fn
|
|
||||||
event_userdata_cb: gg_event_fn
|
|
||||||
fail_userdata_cb: gg_fail_fn
|
|
||||||
cleanup_userdata_cb: gg_cleanup_fn
|
|
||||||
window_title: cfg.window_title.str
|
|
||||||
html5_canvas_name: cfg.window_title.str
|
|
||||||
width: cfg.width
|
|
||||||
height: cfg.height
|
|
||||||
//high_dpi: true
|
|
||||||
}
|
|
||||||
if cfg.use_ortho {}
|
|
||||||
else {}
|
|
||||||
g.window = window
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
if gg.config.wait_events {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,553 @@
|
||||||
|
// 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 gg
|
||||||
|
|
||||||
|
import stbi
|
||||||
|
import glm
|
||||||
|
import gl
|
||||||
|
import gx
|
||||||
|
import os
|
||||||
|
import glfw
|
||||||
|
|
||||||
|
pub struct Vec2 {
|
||||||
|
pub:
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (v Vec2) str() string {
|
||||||
|
return 'Vec2{ x: $v.x y: $v.y }'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vec2(x, y int) Vec2 {
|
||||||
|
res := Vec2 {
|
||||||
|
x: x
|
||||||
|
y: y
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_gg() {
|
||||||
|
glfw.init_glfw()
|
||||||
|
gl.init_glad()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Cfg {
|
||||||
|
pub:
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
use_ortho bool
|
||||||
|
retina bool
|
||||||
|
resizable bool
|
||||||
|
decorated bool = true
|
||||||
|
|
||||||
|
font_size int
|
||||||
|
font_path string
|
||||||
|
create_window bool
|
||||||
|
window_user_ptr voidptr
|
||||||
|
window_title string
|
||||||
|
always_on_top bool
|
||||||
|
scale int
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type RenderFn fn()
|
||||||
|
pub struct GG {
|
||||||
|
shader gl.Shader
|
||||||
|
// use_ortho bool
|
||||||
|
vao u32
|
||||||
|
rect_vao u32
|
||||||
|
rect_vbo u32
|
||||||
|
line_vao u32
|
||||||
|
line_vbo u32
|
||||||
|
vbo u32
|
||||||
|
scale int // retina = 2 , normal = 1
|
||||||
|
//pub:
|
||||||
|
pub mut:
|
||||||
|
width int
|
||||||
|
height int
|
||||||
|
window &glfw.Window
|
||||||
|
render_fn RenderFn
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// fn new_context(width, height int, use_ortho bool, font_size int) *GG {
|
||||||
|
pub fn new_context(cfg Cfg) &GG {
|
||||||
|
mut window := &glfw.Window(0)
|
||||||
|
if cfg.create_window {
|
||||||
|
if cfg.resizable {
|
||||||
|
glfw.window_hint(C.GLFW_RESIZABLE, 1)
|
||||||
|
} else {
|
||||||
|
glfw.window_hint(C.GLFW_RESIZABLE, 0)
|
||||||
|
}
|
||||||
|
if cfg.decorated {
|
||||||
|
glfw.window_hint(C.GLFW_DECORATED, 1)
|
||||||
|
} else {
|
||||||
|
glfw.window_hint(C.GLFW_DECORATED, 0)
|
||||||
|
}
|
||||||
|
window = glfw.create_window(glfw.WinCfg{
|
||||||
|
title: cfg.window_title
|
||||||
|
width: cfg.width
|
||||||
|
height: cfg.height
|
||||||
|
ptr: cfg.window_user_ptr
|
||||||
|
always_on_top: cfg.always_on_top
|
||||||
|
})
|
||||||
|
window.make_context_current()
|
||||||
|
init_gg()
|
||||||
|
}
|
||||||
|
shader := gl.new_shader('simple')
|
||||||
|
shader.use()
|
||||||
|
if cfg.use_ortho {
|
||||||
|
projection := glm.ortho(0, f32(cfg.width), f32(cfg.height), 0)
|
||||||
|
shader.set_mat4('projection', projection)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO move to function (allow volt functions to return arrays without allocations)
|
||||||
|
// i := glm.identity3()
|
||||||
|
shader.set_mat4('projection', glm.identity())
|
||||||
|
}
|
||||||
|
vao := gl.gen_vertex_array()
|
||||||
|
//println('new gg context VAO=$VAO')
|
||||||
|
vbo := gl.gen_buffer()
|
||||||
|
mut scale := 1
|
||||||
|
if cfg.retina {
|
||||||
|
scale = 2
|
||||||
|
}
|
||||||
|
gl.enable(C.GL_SCISSOR_TEST)
|
||||||
|
//gl.enable(GL_BLEND)
|
||||||
|
//# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
//println('new gg text context VAO=$VAO')
|
||||||
|
//gl.bind_vao(VAO)
|
||||||
|
//gl.bind_buffer(GL_ARRAY_BUFFER, VBO)
|
||||||
|
//gl.enable_vertex_attrib_array(0)
|
||||||
|
//gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0)
|
||||||
|
todo_remove_me(cfg, scale)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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_color(color.r, color.g, color.b, 255)
|
||||||
|
gl.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
ctx.shader.set_color('color', c)
|
||||||
|
vertices := [
|
||||||
|
x1, y1, 0,
|
||||||
|
x2, y2, 0,
|
||||||
|
x3, y3, 0,
|
||||||
|
] !
|
||||||
|
// bind the Vertex Array Object first, then bind and set vertex buffer(s),
|
||||||
|
// and then configure vertex attributes(s).
|
||||||
|
gl.bind_vao(ctx.vao)
|
||||||
|
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
||||||
|
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 3, 0)
|
||||||
|
gl.enable_vertex_attrib_array(0)
|
||||||
|
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
||||||
|
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO,
|
||||||
|
// but this rarely happens. Modifying other
|
||||||
|
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs
|
||||||
|
// (nor VBOs) when it's not directly necessary.
|
||||||
|
// gl.bind_vertex_array(uint(0))
|
||||||
|
// gl.bind_vertex_array(ctx.VAO)
|
||||||
|
gl.draw_arrays(C.GL_TRIANGLES, 0, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_triangle_tex(x1, y1, x2, y2, x3, y3 f32, c gx.Color) {
|
||||||
|
ctx.shader.use()
|
||||||
|
ctx.shader.set_color('color', c)
|
||||||
|
ctx.shader.set_int('has_texture', 1)
|
||||||
|
vertices := [
|
||||||
|
x1, y1, 0, 0, 0, 0, 1, 1,
|
||||||
|
x2, y2, 0, 0, 0, 0, 1, 0,
|
||||||
|
x3, y3, 0, 0, 0, 0, 0, 0,
|
||||||
|
] !
|
||||||
|
gl.bind_vao(ctx.vao)
|
||||||
|
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
||||||
|
// position attribute
|
||||||
|
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 3, 0)
|
||||||
|
gl.enable_vertex_attrib_array(0)
|
||||||
|
// color attribute
|
||||||
|
gl.vertex_attrib_pointer(1, 3, C.GL_FLOAT, false, 8, 3)
|
||||||
|
gl.enable_vertex_attrib_array(1)
|
||||||
|
// texture attribute
|
||||||
|
gl.vertex_attrib_pointer(2, 2, C.GL_FLOAT, false, 8, 6)
|
||||||
|
gl.enable_vertex_attrib_array(2)
|
||||||
|
// /
|
||||||
|
// gl.draw_arrays(GL_TRIANGLES, 0, 3)
|
||||||
|
gl.draw_elements(C.GL_TRIANGLES, 6, C.GL_UNSIGNED_INT, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_rect(x, y, w, h f32, c gx.Color) {
|
||||||
|
// println('gg.draw_rect($x,$y,$w,$h)')
|
||||||
|
// wrong order
|
||||||
|
// // ctx.draw_triangle(x, y, x + w, y, x + w, y + h, c)
|
||||||
|
// // ctx.draw_triangle(x, y, x, y + h, x + w, y + h, c)
|
||||||
|
// good order. counter clockwise
|
||||||
|
// ctx.draw_triangle(x, y, x, y + h, x + w, y + h, c)
|
||||||
|
// ctx.draw_triangle(x, y, x + w, y + h, x + w, y, c)
|
||||||
|
ctx.draw_rect2(x, y, w, h, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Useful for debugging meshes.
|
||||||
|
pub fn set_mode_wireframe() {
|
||||||
|
C.glPolygonMode(C.GL_FRONT_AND_BACK, C.GL_LINE)
|
||||||
|
}
|
||||||
|
pub fn set_mode_point() {
|
||||||
|
C.glPolygonMode(C.GL_FRONT_AND_BACK, C.GL_POINT)
|
||||||
|
}
|
||||||
|
pub fn set_mode_fill() {
|
||||||
|
C.glPolygonMode(C.GL_FRONT_AND_BACK, C.GL_FILL)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn (mut ctx GG) init_rect_vao() {
|
||||||
|
|
||||||
|
ctx.rect_vao = gl.gen_vertex_array()
|
||||||
|
ctx.rect_vbo = gl.gen_buffer()
|
||||||
|
vertices := [
|
||||||
|
x + w, y, 0,
|
||||||
|
x + w, y + h, 0,
|
||||||
|
x, y + h, 0,
|
||||||
|
x, y, 0,
|
||||||
|
] !
|
||||||
|
indices := [
|
||||||
|
0, 1, 3,// first triangle
|
||||||
|
1, 2, 3// second triangle
|
||||||
|
] !
|
||||||
|
gl.bind_vao(ctx.rect_vao)
|
||||||
|
gl.set_vbo(ctx.rect_vbo, vertices, C.GL_STATIC_DRAW)
|
||||||
|
ebo := gl.gen_buffer()
|
||||||
|
// ///////
|
||||||
|
gl.set_ebo(ebo, indices, C.GL_STATIC_DRAW)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
pub fn (ctx &GG) draw_rect2(x, y, w, h f32, c gx.Color) {
|
||||||
|
C.glDeleteBuffers(1, &ctx.vao)
|
||||||
|
C.glDeleteBuffers(1, &ctx.vbo)
|
||||||
|
ctx.shader.use()
|
||||||
|
ctx.shader.set_color('color', c)
|
||||||
|
ctx.shader.set_int('has_texture', 0)
|
||||||
|
// 4--1
|
||||||
|
// 3--2
|
||||||
|
$if linux {
|
||||||
|
// y += h
|
||||||
|
}
|
||||||
|
vertices := [
|
||||||
|
x + w, y, 0,
|
||||||
|
x + w, y + h, 0,
|
||||||
|
x, y + h, 0,
|
||||||
|
x, y, 0,
|
||||||
|
] !
|
||||||
|
indices := [
|
||||||
|
0, 1, 3,// first triangle
|
||||||
|
1, 2, 3// second triangle
|
||||||
|
] !
|
||||||
|
gl.bind_vao(ctx.vao)
|
||||||
|
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
||||||
|
ebo := gl.gen_buffer()
|
||||||
|
// ///////
|
||||||
|
gl.set_ebo(ebo, indices, C.GL_STATIC_DRAW)// !!! LEAKS
|
||||||
|
// /////
|
||||||
|
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 3, 0)
|
||||||
|
gl.enable_vertex_attrib_array(0)
|
||||||
|
// gl.bind_vao(ctx.rect_vao)
|
||||||
|
gl.bind_vao(ctx.vao)
|
||||||
|
gl.draw_elements(C.GL_TRIANGLES, 6, C.GL_UNSIGNED_INT, 0)
|
||||||
|
C.glDeleteBuffers(1, &ebo)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn todo_remove_me(cfg Cfg, scale int) {
|
||||||
|
// Can only have text in ortho mode
|
||||||
|
if !cfg.use_ortho {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
width := cfg.width * scale
|
||||||
|
height := cfg.height * scale
|
||||||
|
//font_size := cfg.font_size * scale
|
||||||
|
gl.enable(C.GL_BLEND)
|
||||||
|
//# glBlendFunc(C.GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
shader := gl.new_shader('text')
|
||||||
|
shader.use()
|
||||||
|
projection := glm.ortho(0, f32(width), 0, f32(height))// 0 at BOT
|
||||||
|
// projection_new := ortho(0, width, 0, height)// 0 at BOT
|
||||||
|
// projection := gl.ortho(0, width,height,0) // 0 at TOP
|
||||||
|
shader.set_mat4('projection', projection)
|
||||||
|
vao := gl.gen_vertex_array()
|
||||||
|
//println('new gg text context VAO=$VAO')
|
||||||
|
vbo := gl.gen_buffer()
|
||||||
|
gl.bind_vao(vao)
|
||||||
|
gl.bind_buffer(C.GL_ARRAY_BUFFER, vbo)
|
||||||
|
gl.enable_vertex_attrib_array(0)
|
||||||
|
gl.vertex_attrib_pointer(0, 4, C.GL_FLOAT, false, 4, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update() {
|
||||||
|
// # ui__post_empty_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn post_empty_event() {
|
||||||
|
glfw.post_empty_event()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c GG) circle(x, y, r int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) fill_color(color gx.Color) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) fill() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) move_to(x, y int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) line_to(x, y int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) stroke_width(size int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) stroke_color(color gx.Color) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) stroke() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) save() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) restore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) intersect_scissor(x, y, w, h int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) translate(x, y int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) create_font(name, file string) int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) text(x, y int, text string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) text_box(x, y, max int, text string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) font_face(f string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) font_size(size int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (c GG) text_align(a int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) create_image(file string) u32 {
|
||||||
|
return create_image(file)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_image(file string) u32 {
|
||||||
|
//println('gg create image "$file"')
|
||||||
|
if file.contains('twitch') {
|
||||||
|
return u32(0)// TODO
|
||||||
|
}
|
||||||
|
if !os.exists(file) {
|
||||||
|
println('gg create image no such file "$file"')
|
||||||
|
return u32(0)
|
||||||
|
}
|
||||||
|
texture := gl.gen_texture()
|
||||||
|
img := stbi.load(file)
|
||||||
|
gl.bind_2d_texture(texture)
|
||||||
|
img.tex_image_2d()
|
||||||
|
gl.generate_mipmap(C.GL_TEXTURE_2D)
|
||||||
|
img.free()
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_image_from_memory(buf byteptr) u32 {
|
||||||
|
texture := gl.gen_texture()
|
||||||
|
img := stbi.load_from_memory(buf)
|
||||||
|
// TODO copy pasta
|
||||||
|
gl.bind_2d_texture(texture)
|
||||||
|
img.tex_image_2d()
|
||||||
|
gl.generate_mipmap(C.GL_TEXTURE_2D)
|
||||||
|
img.free()
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_line(x, y, x2, y2 f32, color gx.Color) {
|
||||||
|
ctx.use_color_shader(color)
|
||||||
|
vertices := [x, y, x2, y2] !
|
||||||
|
ctx.bind_vertices(vertices)
|
||||||
|
gl.draw_arrays(C.GL_LINES, 0, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_arc(x, y, r, start_angle, end_angle f32, segments int, color gx.Color) {
|
||||||
|
ctx.use_color_shader(color)
|
||||||
|
vertices := arc_vertices(x, y, r, start_angle, end_angle, segments)
|
||||||
|
ctx.bind_vertices(vertices)
|
||||||
|
gl.draw_arrays(C.GL_LINE_STRIP, 0, segments + 1)
|
||||||
|
unsafe { vertices.free() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_filled_arc(x, y, r, start_angle, end_angle f32, segments int, color gx.Color) {
|
||||||
|
ctx.use_color_shader(color)
|
||||||
|
|
||||||
|
|
||||||
|
mut vertices := []f32{}
|
||||||
|
vertices << [x, y] !
|
||||||
|
vertices << arc_vertices(x, y, r, start_angle, end_angle, segments)
|
||||||
|
ctx.bind_vertices(vertices)
|
||||||
|
gl.draw_arrays(C.GL_TRIANGLE_FAN, 0, segments + 2)
|
||||||
|
unsafe { vertices.free() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_circle(x, y, r f32, color gx.Color) {
|
||||||
|
ctx.draw_filled_arc(x, y, r, 0, 360, 24 + int(r / 2), color)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_rounded_rect(x, y, w, h, r f32, color gx.Color) {
|
||||||
|
ctx.use_color_shader(color)
|
||||||
|
mut vertices := []f32{}
|
||||||
|
segments := 6 + int(r / 8)
|
||||||
|
|
||||||
|
// Create a rounded rectangle using a triangle fan mesh.
|
||||||
|
vertices << [x + (w/2.0), y + (h/2.0)] !
|
||||||
|
vertices << arc_vertices(x + w - r, y + h - r, r, 0, 90, segments)
|
||||||
|
vertices << arc_vertices(x + r, y + h - r, r, 90, 180, segments)
|
||||||
|
vertices << arc_vertices(x + r, y + r, r, 180, 270, segments)
|
||||||
|
vertices << arc_vertices(x + w - r, y + r, r, 270, 360, segments)
|
||||||
|
// Finish the loop by going back to the first vertex
|
||||||
|
vertices << [vertices[2], vertices[3]] !
|
||||||
|
|
||||||
|
ctx.bind_vertices(vertices)
|
||||||
|
gl.draw_arrays(C.GL_TRIANGLE_FAN, 0, segments * 4 + 6)
|
||||||
|
unsafe { vertices.free() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (ctx &GG) draw_empty_rounded_rect(x, y, w, h, r f32, color gx.Color) {
|
||||||
|
ctx.use_color_shader(color)
|
||||||
|
mut vertices := []f32{}
|
||||||
|
segments := 6 + int(r / 8)
|
||||||
|
|
||||||
|
vertices << arc_vertices(x + w - r, y + h - r, r, 0, 90, segments)
|
||||||
|
vertices << arc_vertices(x + r, y + h - r, r, 90, 180, segments)
|
||||||
|
vertices << arc_vertices(x + r, y + r, r, 180, 270, segments)
|
||||||
|
vertices << arc_vertices(x + w - r, y + r, r, 270, 360, segments)
|
||||||
|
|
||||||
|
ctx.bind_vertices(vertices)
|
||||||
|
gl.draw_arrays(C.GL_LINE_STRIP, 0, segments * 4 + 1)
|
||||||
|
unsafe { vertices.free() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn (c &GG) draw_gray_line(x, y, x2, y2 f32) {
|
||||||
|
c.draw_line(x, y, x2, y2, gx.gray)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &GG) draw_vertical(x, y, height int) {
|
||||||
|
c.draw_line(x, y, x, y + height)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//ctx.gg.draw_line(center + prev_x, center+prev_y, center + x*10.0, center+y)
|
||||||
|
|
||||||
|
// fn (ctx &GG) draw_image(x, y, w, h f32, img stbi.Image) {
|
||||||
|
pub fn (ctx &GG) draw_image(x, y, w, h f32, tex_id u32) {
|
||||||
|
|
||||||
|
// NB: HACK to ensure same state ... TODO: remove next line
|
||||||
|
ctx.draw_empty_rect(0,0,0,0, gx.white)
|
||||||
|
|
||||||
|
last_array_buffer := 0
|
||||||
|
last_texture := 0
|
||||||
|
C.glGetIntegerv(C.GL_ARRAY_BUFFER_BINDING, &last_array_buffer)
|
||||||
|
C.glGetIntegerv(C.GL_TEXTURE_BINDING_2D, &last_texture)
|
||||||
|
|
||||||
|
// println('DRAW IMAGE $x $y $w $h $tex_id')
|
||||||
|
ctx.shader.use()
|
||||||
|
// ctx.shader.set_color('color', c)
|
||||||
|
ctx.shader.set_int('has_texture', 1)
|
||||||
|
// 4--1
|
||||||
|
// | |
|
||||||
|
// 3--2
|
||||||
|
vertices := [
|
||||||
|
x + w, y, 0, 1, 0, 0, 1, 1,
|
||||||
|
x + w, y + h, 0, 0, 1, 0, 1, 0,
|
||||||
|
x, y + h, 0, 0, 0, 1, 0, 0,
|
||||||
|
x, y, 0, 1, 1, 0, 0, 1,
|
||||||
|
] !
|
||||||
|
indices := [
|
||||||
|
0, 1, 3,// first triangle
|
||||||
|
1, 2, 3// second triangle
|
||||||
|
] !
|
||||||
|
// VAO := gl.gen_vertex_array()
|
||||||
|
// VBO := gl.gen_buffer()
|
||||||
|
C.glEnable(C.GL_TEXTURE_2D)
|
||||||
|
gl.bind_vao(ctx.vao)
|
||||||
|
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
|
||||||
|
ebo := gl.gen_buffer()
|
||||||
|
gl.set_ebo(ebo, indices, C.GL_STATIC_DRAW)
|
||||||
|
gl.vertex_attrib_pointer(0, 3, C.GL_FLOAT, false, 8, 0)
|
||||||
|
gl.enable_vertex_attrib_array(0)
|
||||||
|
gl.vertex_attrib_pointer(1, 3, C.GL_FLOAT, false, 8, 3)
|
||||||
|
gl.enable_vertex_attrib_array(1)
|
||||||
|
gl.vertex_attrib_pointer(2, 2, C.GL_FLOAT, false, 8, 6)
|
||||||
|
gl.enable_vertex_attrib_array(2)
|
||||||
|
gl.bind_2d_texture(tex_id)
|
||||||
|
gl.bind_vao(ctx.vao)
|
||||||
|
gl.draw_elements(C.GL_TRIANGLES, 6, C.GL_UNSIGNED_INT, 0)
|
||||||
|
C.glDisable(C.GL_TEXTURE_2D)
|
||||||
|
// restore state
|
||||||
|
C.glBindBuffer(C.GL_ARRAY_BUFFER, last_array_buffer)
|
||||||
|
C. glBindTexture(C.GL_TEXTURE_2D, last_texture)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c &GG) draw_empty_rect(x, y, w, h f32, color gx.Color) {
|
||||||
|
c.draw_line(x, y, x + w, y, color)
|
||||||
|
c.draw_line(x, y, x, y + h, color)
|
||||||
|
c.draw_line(x, y + h, x + w, y + h, color)
|
||||||
|
c.draw_line(x + w, y, x + w, y + h, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scissor(x, y, w, h f32) {
|
||||||
|
C.glScissor(x, y, w, h)
|
||||||
|
}
|
|
@ -24,6 +24,5 @@ pub const (
|
||||||
|
|
||||||
#include "ft2build.h"
|
#include "ft2build.h"
|
||||||
|
|
||||||
#define FONS_USE_FREETYPE
|
|
||||||
#define SOKOL_FONTSTASH_IMPL
|
#define SOKOL_FONTSTASH_IMPL
|
||||||
#include "util/sokol_fontstash.h"
|
#include "util/sokol_fontstash.h"
|
||||||
|
|
Loading…
Reference in New Issue