mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
bed7440ebb
added getexepath() to os module added some wrapper functions to glfw removed hardcored path in gg module better tetris example exit and resource loading
722 lines
18 KiB
Go
722 lines
18 KiB
Go
// Copyright (c) 2019 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
|
|
|
|
#flag darwin -I/usr/local/Cellar/freetype/2.10.0/include/freetype2
|
|
#flag -lfreetype
|
|
#flag linux -I/usr/include/freetype2
|
|
#flag linux -I.
|
|
#include "ft2build.h"
|
|
#include FT_FREETYPE_H
|
|
#include "glad.h"
|
|
struct Vec2 {
|
|
x int
|
|
y int
|
|
}
|
|
|
|
import const (
|
|
GL_STATIC_DRAW
|
|
GL_FLOAT
|
|
GL_FALSE
|
|
GL_UNSIGNED_INT
|
|
GL_INT
|
|
)
|
|
|
|
const (
|
|
DEFAULT_FONT_SIZE = 12
|
|
)
|
|
|
|
pub fn vec2(x, y int) Vec2 {
|
|
res := Vec2 {
|
|
x: x,
|
|
y: y,
|
|
}
|
|
return res
|
|
}
|
|
|
|
struct Character {
|
|
texture_id u32
|
|
size Vec2
|
|
bearing Vec2
|
|
advance u32
|
|
}
|
|
|
|
pub fn init() {
|
|
println(gl.TEXT_VERT)
|
|
gl.init_glad()
|
|
}
|
|
|
|
struct Face {
|
|
cobj voidptr
|
|
kek int
|
|
}
|
|
|
|
struct Cfg {
|
|
width int
|
|
height int
|
|
use_ortho int
|
|
retina bool
|
|
font_size int
|
|
}
|
|
|
|
struct GG {
|
|
shader gl.Shader
|
|
// use_ortho bool
|
|
width int
|
|
height int
|
|
VAO u32
|
|
rect_vao u32
|
|
rect_vbo u32
|
|
line_vao u32
|
|
line_vbo u32
|
|
VBO u32
|
|
chars []gg.Character
|
|
utf_runes []string
|
|
utf_chars []gg.Character
|
|
text_ctx *GG
|
|
face Face
|
|
scale int // retina = 2 , normal = 1
|
|
}
|
|
|
|
// 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);
|
|
shader := gl.new_shader('simple')
|
|
shader.use()
|
|
if cfg.use_ortho > 0 {
|
|
projection := glm.ortho(0, cfg.width, cfg.height, 0)
|
|
/*
|
|
// for debugging broken tetris in gg.o
|
|
# projection.data[0]=0.010000;
|
|
# projection.data[1]=0.000000;
|
|
# projection.data[2]=0.000000;
|
|
# projection.data[3]=0.000000;
|
|
# projection.data[4]=0.000000;
|
|
# projection.data[5]=-0.005000;
|
|
# projection.data[6]=0.000000;
|
|
# projection.data[7]=0.000000;
|
|
# projection.data[8]=0.000000;
|
|
# projection.data[9]=0.000000;
|
|
# projection.data[10]=1.000000;
|
|
# projection.data[11]=0.000000;
|
|
# projection.data[12]=-1.000000;
|
|
# projection.data[13]=1.000000;
|
|
# projection.data[14]=0.000000;
|
|
# projection.data[15]=1.000000;
|
|
*/
|
|
// projection_new := ortho(0, width, height, 0)
|
|
// println('\nORTHO OLD=')
|
|
# for (int i=0;i<16;i++) printf("%d=%f ",i, projection.data[i]);
|
|
// println('\n\n!ORTHO NEW=')
|
|
// # for (int i=0;i<16;i++) printf("%d=%f ",i, projection_new[i]);
|
|
// println('\n\n')
|
|
println('setting o')
|
|
shader.set_mat4('projection', projection)
|
|
}
|
|
else {
|
|
// TODO move to function (allow volt functions to return arrrays 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
|
|
}
|
|
mut ctx := &GG {
|
|
shader: shader,
|
|
width: cfg.width,
|
|
height: cfg.height,
|
|
VAO: VAO,
|
|
VBO: VBO,
|
|
// /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 (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, GL_STATIC_DRAW)
|
|
gl.vertex_attrib_pointer(0, 3, 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(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, GL_STATIC_DRAW)
|
|
// position attribute
|
|
gl.vertex_attrib_pointer(0, 3, GL_FLOAT, false, 3, 0)
|
|
gl.enable_vertex_attrib_array(0)
|
|
// color attribute
|
|
gl.vertex_attrib_pointer(1, 3, GL_FLOAT, false, 8, 3)
|
|
gl.enable_vertex_attrib_array(1)
|
|
// texture attribute
|
|
gl.vertex_attrib_pointer(2, 2, GL_FLOAT, false, 8, 6)
|
|
gl.enable_vertex_attrib_array(2)
|
|
// /
|
|
// gl.draw_arrays(GL_TRIANGLES, 0, 3)
|
|
gl.draw_elements(GL_TRIANGLES, 6, 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 clock wise
|
|
// 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)
|
|
}
|
|
|
|
/*
|
|
fn (ctx mut 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, GL_STATIC_DRAW)
|
|
ebo := gl.gen_buffer()
|
|
// ///////
|
|
gl.set_ebo(ebo, indices, 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, GL_STATIC_DRAW)
|
|
ebo := gl.gen_buffer()
|
|
// ///////
|
|
gl.set_ebo(ebo, indices, GL_STATIC_DRAW)// !!! LEAKS
|
|
// /////
|
|
gl.vertex_attrib_pointer(0, 3, 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(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
|
|
C.glDeleteBuffers(1, &ebo)
|
|
}
|
|
|
|
// jfn ft_load_char(face FT_Face, code FT_ULong) Character {
|
|
// fn ft_load_char(_face voidptr, _code voidptr) Character {
|
|
fn ft_load_char(_face Face, code i64) Character {
|
|
// #FT_Face face = *(FT_Face*)(_face); FT_ULong code = *(FT_ULong*)(code);
|
|
# FT_Face face = *((FT_Face*)_face.cobj);
|
|
# if (FT_Load_Char(face, code, FT_LOAD_RENDER))
|
|
{
|
|
println('freetype: Failed to load Glyph')
|
|
exit(1)
|
|
}
|
|
// Generate texture
|
|
# GLuint texture;
|
|
# glGenTextures(1, &texture);
|
|
# glBindTexture(GL_TEXTURE_2D, texture);
|
|
# glTexImage2D(
|
|
# GL_TEXTURE_2D,
|
|
# 0,
|
|
# GL_RED,
|
|
# face->glyph->bitmap.width,
|
|
# face->glyph->bitmap.rows,
|
|
# 0,
|
|
# GL_RED,
|
|
# GL_UNSIGNED_BYTE,
|
|
# face->glyph->bitmap.buffer
|
|
# );
|
|
// Set texture options
|
|
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
# glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
// Now store character for later use
|
|
ch := Character{}
|
|
# ch.texture_id=texture ;
|
|
# ch.size = gg__vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
|
|
# ch.bearing = gg__vec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
|
# ch.advance = face->glyph->advance.x;
|
|
return ch
|
|
}
|
|
|
|
pub fn new_context_text(cfg Cfg, scale int) *GG {
|
|
// Can only have text in ortho mode
|
|
if !cfg.use_ortho {
|
|
return &GG{text_ctx: 0}
|
|
}
|
|
mut width := cfg.width * scale
|
|
mut height := cfg.height * scale
|
|
font_size := cfg.font_size * scale
|
|
// exit('fs=$font_size')
|
|
// if false {
|
|
// retina
|
|
// width = width * 2// scale// 2
|
|
// height = height * 2// scale// 2
|
|
// font_size *= scale// 2
|
|
// }
|
|
/*
|
|
gl.viewport(0, 0, width, height)
|
|
*/
|
|
// gl.enable(GL_CULL_FACE) // TODO NEED CULL? MEANS SHIT IS BROKEN?
|
|
gl.enable(GL_BLEND)
|
|
// return &GG{}
|
|
# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
shader := gl.new_shader('text')
|
|
shader.use()
|
|
projection := glm.ortho(0, width, 0, 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)
|
|
// FREETYPE
|
|
# FT_Library ft;
|
|
// All functions return a value different than 0 whenever an error occurred
|
|
# if (FT_Init_FreeType(&ft))
|
|
println('ERROR::FREETYPE: Could not init FreeType Library')
|
|
// Load font as face
|
|
// face := FT_Face{}
|
|
mut font_path := 'RobotoMono-Regular.ttf'
|
|
if !os.file_exists(font_path) {
|
|
exePath := os.getexepath()
|
|
exeDir := os.basedir(exePath)
|
|
println('Trying to load from $exeDir')
|
|
font_path = '${exeDir}/RobotoMono-Regular.ttf'
|
|
}
|
|
if !os.file_exists(font_path) {
|
|
println('failed to load RobotoMono-Regular.ttf')
|
|
exit(1)
|
|
}
|
|
# FT_Face face;
|
|
# if (FT_New_Face(ft, font_path.str, 0, &face))
|
|
// # if (FT_New_Face(ft, "/Library/Fonts/Courier New.ttf", 0, &face))
|
|
// # if (FT_New_Face(ft, "/System/Library/Fonts/Apple Color Emoji.ttc", 0, &face))
|
|
{
|
|
println('freetyp: Failed to load font')
|
|
exit(1)
|
|
}
|
|
// Set size to load glyphs as
|
|
# FT_Set_Pixel_Sizes(face, 0, font_size) ;
|
|
// Disable byte-alignment restriction
|
|
# glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
// Gen texture
|
|
// Load first 128 characters of ASCII set
|
|
mut chars := []gg.Character{}
|
|
f := Face {
|
|
cobj: 0
|
|
kek: 0
|
|
}
|
|
# f.cobj = &face;
|
|
// # for (GLubyte c = 0; c < 128; c++)
|
|
for c := 0; c < 128; c++ {
|
|
// ch := Character{}
|
|
// ch:=ft_load_char(face, c)
|
|
// # ch =gg__ft_load_char(&face, &c);
|
|
// ////////////////////////////////
|
|
mut ch := ft_load_char(f, i64(c))
|
|
// s := utf32_to_str(uint(0x043f))
|
|
// s := 'п'
|
|
// ch = ft_load_char(f, s.utf32_code())
|
|
// # ch = gg__ft_load_char(f, 0x043f); // RUS P
|
|
// # unsigned long c = FT_Get_Char_Index(face, 0x043f );
|
|
// # printf("!!!!!!!!! %lu\n", c);
|
|
// # c = FT_Get_Char_Index(face, 0xd0bf );
|
|
// # printf("!!!!!!!!! %lu\n", c);
|
|
// # ch = gg__ft_load_char(f, 0xd0bf) ; // UTF 8
|
|
chars << ch
|
|
}
|
|
ch := Character{}
|
|
// # ch = gg__ft_load_char(f, 0x0000043f);
|
|
// # ch = gg__ft_load_char(f, 128169);
|
|
// chars.push(ch)
|
|
// Configure VAO
|
|
VAO := gl.gen_vertex_array()
|
|
println('new gg text context VAO=$VAO')
|
|
VBO := gl.gen_buffer()
|
|
gl.bind_vao(VAO)
|
|
gl.bind_buffer(GL_ARRAY_BUFFER, VBO)
|
|
// # glBufferData(GL_ARRAY_BUFFER, sizeof(GLf32) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
|
gl.enable_vertex_attrib_array(0)
|
|
gl.vertex_attrib_pointer(0, 4, GL_FLOAT, false, 4, 0)
|
|
// # glVertexAttribPointer(0, 4, GL_FLOAT,false, 4 * sizeof(GLf32), 0);
|
|
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
|
// # glBindVertexArray(0);
|
|
mut ctx := &GG {
|
|
shader: shader,
|
|
width: width,
|
|
height: height,
|
|
scale: scale
|
|
VAO: VAO,
|
|
VBO: VBO,
|
|
chars: chars,
|
|
face: f
|
|
text_ctx: 0
|
|
}
|
|
ctx.init_utf8_runes()
|
|
return ctx
|
|
}
|
|
|
|
// A dirty hack to implement rendering of cyrillic letters.
|
|
// All UTF-8 must be supported.
|
|
fn (ctx mut GG) init_utf8_runes() {
|
|
s := '≈йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ'
|
|
println(s)
|
|
us := s.ustring()
|
|
for i := 0; i < us.len; i++ {
|
|
_rune := us.at(i)
|
|
ch := ft_load_char(ctx.face, _rune.utf32_code())
|
|
// ctx.utf_rune_map.set(rune, ch)
|
|
ctx.utf_runes << _rune
|
|
ctx.utf_chars << ch
|
|
}
|
|
}
|
|
|
|
// fn (ctx &GG) render_text(text string, x, y, scale f32, color gx.Color) {
|
|
pub fn (ctx &GG) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
|
|
// dont draw non ascii for now
|
|
/*
|
|
for i := 0; i < text.len; i++ {
|
|
c := text[i]
|
|
if int(c) > 128 {
|
|
// ctx.text_ctx._draw_text(_x, _y, '[NON ASCII]', cfg)
|
|
// return
|
|
}
|
|
}
|
|
*/
|
|
// # glScissor(0,0,300,300);
|
|
utext := text.ustring_tmp()
|
|
// utext := text.ustring()
|
|
ctx.text_ctx._draw_text(_x, _y, utext, cfg)
|
|
// utext.free()
|
|
// # glScissor(0,0,ctx->width*2,ctx->height*2);
|
|
// gl.disable(GL_SCISSOR_TEST)// TODO
|
|
// #free(text.str);
|
|
}
|
|
|
|
fn (ctx &GG) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
|
|
ctx.text_ctx._draw_text(_x, _y, text, cfg)
|
|
}
|
|
|
|
// TODO HACK with second text context
|
|
// fn (ctx &GG) _draw_text(_x, _y int, text string, cfg gx.TextCfg) {
|
|
fn (ctx &GG) _draw_text(_x, _y int, utext ustring, cfg gx.TextCfg) {
|
|
/*
|
|
if utext.s.contains('on_seg') {
|
|
println('\nat(0)')
|
|
println(utext.runes)
|
|
firstc := utext.at(0)
|
|
println('drawtext "$utext.s" len=$utext.s.len ulen=$utext.len x=$_x firstc=$firstc')
|
|
if firstc != ' ' {
|
|
exit(1)
|
|
}
|
|
}
|
|
*/
|
|
// println('scale=$ctx.scale size=$cfg.size')
|
|
if cfg.align == gx.ALIGN_RIGHT {
|
|
width := utext.len * 7
|
|
_x -= width + 10
|
|
}
|
|
x := f32(_x) * ctx.scale// f32(2)
|
|
// println('y=$_y height=$ctx.height')
|
|
// _y = _y * int(ctx.scale) //+ 26
|
|
_y = _y * int(ctx.scale) + ((cfg.size * ctx.scale) / 2) + 5 * ctx.scale
|
|
y := f32(ctx.height - _y)
|
|
color := cfg.color
|
|
// Activate corresponding render state
|
|
ctx.shader.use()
|
|
ctx.shader.set_color('textColor', color)
|
|
# glActiveTexture(GL_TEXTURE0);
|
|
gl.bind_vao(ctx.VAO)
|
|
// Iterate through all characters
|
|
// utext := text.ustring()
|
|
for i := 0; i < utext.len; i++ {
|
|
_rune := utext.at(i)
|
|
// println('$i => $_rune')
|
|
mut ch := Character{}
|
|
if _rune.len == 1 {
|
|
idx := _rune[0]
|
|
if idx < 0 || idx >= ctx.chars.len {
|
|
println('BADE RUNE $_rune')
|
|
continue
|
|
}
|
|
ch = ctx.chars[_rune[0]]
|
|
}
|
|
else if _rune.len > 1 {
|
|
// TODO O(1) use map
|
|
for j := 0; j < ctx.utf_runes.len; j++ {
|
|
rune_j := ctx.utf_runes[j]
|
|
// if string_eq(ctx.utf_runes[j], rune) {
|
|
if rune_j==_rune {
|
|
ch = ctx.utf_chars[j]
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if ch.size.x == 0 {
|
|
// continue
|
|
}
|
|
// mut c := int(text[i])
|
|
// c = 128
|
|
// s := 'A'
|
|
// c := int(s[0])
|
|
// ch := ctx.chars[c]
|
|
xpos := x + f32(ch.bearing.x) * 1
|
|
ypos := y - f32(ch.size.y - ch.bearing.y) * 1
|
|
w := f32(ch.size.x) * 1
|
|
h := f32(ch.size.y) * 1
|
|
// Update VBO for each character
|
|
# GLfloat vertices[6][4] = {
|
|
# { xpos, ypos + h, 0.0, 0.0 },
|
|
# { xpos, ypos, 0.0, 1.0 },
|
|
# { xpos + w, ypos, 1.0, 1.0 },
|
|
# { xpos, ypos + h, 0.0, 0.0 },
|
|
# { xpos + w, ypos, 1.0, 1.0 },
|
|
# { xpos + w, ypos + h, 1.0, 0.0 }
|
|
# };
|
|
// t := glfw.get_time()
|
|
// Render glyph texture over quad
|
|
// t1 := glfw.get_time()
|
|
# glBindTexture(GL_TEXTURE_2D, ch.texture_id);
|
|
// Update content of VBO memory
|
|
gl.bind_buffer(GL_ARRAY_BUFFER, ctx.VBO)
|
|
// t2 := glfw.get_time()
|
|
// # glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData
|
|
# glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
|
|
// t3 := glfw.get_time()
|
|
// gl.bind_buffer(GL_ARRAY_BUFFER, uint(0))
|
|
// t4 := glfw.get_time()
|
|
// Render quad
|
|
gl.draw_arrays(GL_TRIANGLES, 0, 6)
|
|
// t5 := glfw.get_time()
|
|
// # if (glfw__get_time() - t > 0.001)
|
|
// {
|
|
// # printf("do_text = %f '%s' \n", glfw__get_time() - t, text.str);
|
|
// # printf("t1=%f, t2=%f, t3=%f, t4=%f, t5=%f\n\n\n", t1-t, t2-t1, t3-t2, t4-t3, t5-t4);
|
|
// }
|
|
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
|
// Bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
|
|
# x += (ch.advance >> 6) * 1;
|
|
}
|
|
gl.bind_vao(u32(0))
|
|
# glBindTexture(GL_TEXTURE_2D, 0);
|
|
// runes.free()
|
|
// #free(runes.data);
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
fn update() {
|
|
// # ui__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 create_image(file string) u32 {
|
|
println('gg create image "$file"')
|
|
if file.contains('twitch') {
|
|
return u32(0)// TODO
|
|
}
|
|
if !os.file_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(GL_TEXTURE_2D)
|
|
img.free()
|
|
// println('gg end')
|
|
return texture
|
|
}
|
|
|
|
pub fn (ctx &GG) draw_line_c(x, y, x2, y2 int, color gx.Color) {
|
|
C.glDeleteBuffers(1, &ctx.VAO)
|
|
C.glDeleteBuffers(1, &ctx.VBO)
|
|
ctx.shader.use()
|
|
ctx.shader.set_color('color', color)
|
|
vertices := [f32(x), f32(y), f32(x2), f32(y2)] !
|
|
gl.bind_vao(ctx.VAO)
|
|
gl.set_vbo(ctx.VBO, vertices, GL_STATIC_DRAW)
|
|
gl.vertex_attrib_pointer(0, 2, GL_FLOAT, false, 2, 0)
|
|
gl.enable_vertex_attrib_array(0)
|
|
gl.bind_vao(ctx.VAO)
|
|
gl.draw_arrays(GL_LINES, 0, 2)
|
|
}
|
|
|
|
pub fn (c &GG) draw_line(x, y, x2, y2 int) {
|
|
c.draw_line_c(x, y, x2, y2, gx.Gray)
|
|
}
|
|
|
|
pub fn (c &GG) draw_vertical(x, y, height int) {
|
|
c.draw_line(x, y, x, y + height)
|
|
}
|
|
|
|
// 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) {
|
|
// 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()
|
|
gl.bind_vao(ctx.VAO)
|
|
gl.set_vbo(ctx.VBO, vertices, GL_STATIC_DRAW)
|
|
ebo := gl.gen_buffer()
|
|
gl.set_ebo(ebo, indices, GL_STATIC_DRAW)
|
|
gl.vertex_attrib_pointer(0, 3, GL_FLOAT, false, 8, 0)
|
|
gl.enable_vertex_attrib_array(0)
|
|
gl.vertex_attrib_pointer(1, 3, GL_FLOAT, false, 8, 3)
|
|
gl.enable_vertex_attrib_array(1)
|
|
gl.vertex_attrib_pointer(2, 2, GL_FLOAT, false, 8, 6)
|
|
gl.enable_vertex_attrib_array(2)
|
|
gl.bind_2d_texture(u32(tex_id))
|
|
gl.bind_vao(ctx.VAO)
|
|
gl.draw_elements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
|
|
}
|
|
|
|
pub fn (c &GG) draw_empty_rect(x, y, w, h int, color gx.Color) {
|
|
c.draw_line_c(x, y, x + w, y, color)
|
|
c.draw_line_c(x, y, x, y + h, color)
|
|
c.draw_line_c(x, y + h, x + w, y + h, color)
|
|
c.draw_line_c(x + w, y, x + w, y + h, color)
|
|
}
|
|
|