remove oldgg, gl, glfw, freetype from vlib now that we have the new sokol based `gg`

pull/5681/head
Alexander Medvednikov 2020-07-05 16:44:23 +02:00
parent 96bd4e8794
commit 36183660e6
14 changed files with 84 additions and 8212 deletions

View File

@ -3,7 +3,6 @@ module main
import gx
import gg
import time
import glfw
import math
const (
@ -17,7 +16,6 @@ struct Context {
}
fn main() {
glfw.init_glfw()
gconfig := gg.Cfg {
width: size
height: size

File diff suppressed because it is too large Load Diff

View File

@ -1,525 +0,0 @@
/*************************************************************************
* GLFW 3.3 - www.glfw.org
* A library for OpenGL, window and input
*------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard
* Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*************************************************************************/
#ifndef _glfw3_native_h_
#define _glfw3_native_h_
#ifdef __cplusplus
extern "C" {
#endif
/*************************************************************************
* Doxygen documentation
*************************************************************************/
/*! @file glfw3native.h
* @brief The header of the native access functions.
*
* This is the header file of the native access functions. See @ref native for
* more information.
*/
/*! @defgroup native Native access
* @brief Functions related to accessing native handles.
*
* **By using the native access functions you assert that you know what you're
* doing and how to fix problems caused by using them. If you don't, you
* shouldn't be using them.**
*
* Before the inclusion of @ref glfw3native.h, you may define zero or more
* window system API macro and zero or more context creation API macros.
*
* The chosen backends must match those the library was compiled for. Failure
* to do this will cause a link-time error.
*
* The available window API macros are:
* * `GLFW_EXPOSE_NATIVE_WIN32`
* * `GLFW_EXPOSE_NATIVE_COCOA`
* * `GLFW_EXPOSE_NATIVE_X11`
* * `GLFW_EXPOSE_NATIVE_WAYLAND`
*
* The available context API macros are:
* * `GLFW_EXPOSE_NATIVE_WGL`
* * `GLFW_EXPOSE_NATIVE_NSGL`
* * `GLFW_EXPOSE_NATIVE_GLX`
* * `GLFW_EXPOSE_NATIVE_EGL`
* * `GLFW_EXPOSE_NATIVE_OSMESA`
*
* These macros select which of the native access functions that are declared
* and which platform-specific headers to include. It is then up your (by
* definition platform-specific) code to handle which of these should be
* defined.
*/
/*************************************************************************
* System headers and types
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
// example to allow applications to correctly declare a GL_ARB_debug_output
// callback) but windows.h assumes no one will define APIENTRY before it does
#if defined(GLFW_APIENTRY_DEFINED)
#undef APIENTRY
#undef GLFW_APIENTRY_DEFINED
#endif
#include <windows.h>
#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
#if defined(__OBJC__)
#import <Cocoa/Cocoa.h>
#else
#include <ApplicationServices/ApplicationServices.h>
typedef void* id;
#endif
#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
#include <wayland-client.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
/* WGL is declared by windows.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
/* NSGL is declared by Cocoa.h */
#endif
#if defined(GLFW_EXPOSE_NATIVE_GLX)
#include <GL/glx.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
#include <EGL/egl.h>
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
#include <GL/osmesa.h>
#endif
/*************************************************************************
* Functions
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
/*! @brief Returns the adapter device name of the specified monitor.
*
* @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
* occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
/*! @brief Returns the display device name of the specified monitor.
*
* @return The UTF-8 encoded display device name (for example
* `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `HWND` of the specified window.
*
* @return The `HWND` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_WGL)
/*! @brief Returns the `HGLRC` of the specified window.
*
* @return The `HGLRC` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_COCOA)
/*! @brief Returns the `CGDirectDisplayID` of the specified monitor.
*
* @return The `CGDirectDisplayID` of the specified monitor, or
* `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor);
/*! @brief Returns the `NSWindow` of the specified window.
*
* @return The `NSWindow` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_NSGL)
/*! @brief Returns the `NSOpenGLContext` of the specified window.
*
* @return The `NSOpenGLContext` of the specified window, or `nil` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_X11)
/*! @brief Returns the `Display` used by GLFW.
*
* @return The `Display` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI Display* glfwGetX11Display(void);
/*! @brief Returns the `RRCrtc` of the specified monitor.
*
* @return The `RRCrtc` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
/*! @brief Returns the `RROutput` of the specified monitor.
*
* @return The `RROutput` of the specified monitor, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.1.
*
* @ingroup native
*/
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `Window` of the specified window.
*
* @return The `Window` of the specified window, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI Window glfwGetX11Window(GLFWwindow* window);
/*! @brief Sets the current primary selection to the specified string.
*
* @param[in] string A UTF-8 encoded string.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The specified string is copied before this function
* returns.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref clipboard
* @sa glfwGetX11SelectionString
* @sa glfwSetClipboardString
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI void glfwSetX11SelectionString(const char* string);
/*! @brief Returns the contents of the current primary selection as a string.
*
* If the selection is empty or if its contents cannot be converted, `NULL`
* is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated.
*
* @return The contents of the selection as a UTF-8 encoded string, or `NULL`
* if an [error](@ref error_handling) occurred.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @pointer_lifetime The returned string is allocated and freed by GLFW. You
* should not free it yourself. It is valid until the next call to @ref
* glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the
* library is terminated.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref clipboard
* @sa glfwSetX11SelectionString
* @sa glfwGetClipboardString
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI const char* glfwGetX11SelectionString(void);
#endif
#if defined(GLFW_EXPOSE_NATIVE_GLX)
/*! @brief Returns the `GLXContext` of the specified window.
*
* @return The `GLXContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);
/*! @brief Returns the `GLXWindow` of the specified window.
*
* @return The `GLXWindow` of the specified window, or `None` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
/*! @brief Returns the `struct wl_display*` used by GLFW.
*
* @return The `struct wl_display*` used by GLFW, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);
/*! @brief Returns the `struct wl_output*` of the specified monitor.
*
* @return The `struct wl_output*` of the specified monitor, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
/*! @brief Returns the main `struct wl_surface*` of the specified window.
*
* @return The main `struct wl_surface*` of the specified window, or `NULL` if
* an [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.2.
*
* @ingroup native
*/
GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_EGL)
/*! @brief Returns the `EGLDisplay` used by GLFW.
*
* @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI EGLDisplay glfwGetEGLDisplay(void);
/*! @brief Returns the `EGLContext` of the specified window.
*
* @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window);
/*! @brief Returns the `EGLSurface` of the specified window.
*
* @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.0.
*
* @ingroup native
*/
GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window);
#endif
#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
/*! @brief Retrieves the color buffer associated with the specified window.
*
* @param[in] window The window whose color buffer to retrieve.
* @param[out] width Where to store the width of the color buffer, or `NULL`.
* @param[out] height Where to store the height of the color buffer, or `NULL`.
* @param[out] format Where to store the OSMesa pixel format of the color
* buffer, or `NULL`.
* @param[out] buffer Where to store the address of the color buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer);
/*! @brief Retrieves the depth buffer associated with the specified window.
*
* @param[in] window The window whose depth buffer to retrieve.
* @param[out] width Where to store the width of the depth buffer, or `NULL`.
* @param[out] height Where to store the height of the depth buffer, or `NULL`.
* @param[out] bytesPerValue Where to store the number of bytes per depth
* buffer element, or `NULL`.
* @param[out] buffer Where to store the address of the depth buffer, or
* `NULL`.
* @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer);
/*! @brief Returns the `OSMesaContext` of the specified window.
*
* @return The `OSMesaContext` of the specified window, or `NULL` if an
* [error](@ref error_handling) occurred.
*
* @thread_safety This function may be called from any thread. Access is not
* synchronized.
*
* @since Added in version 3.3.
*
* @ingroup native
*/
GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _glfw3_native_h_ */

Binary file not shown.

Binary file not shown.

View File

@ -1,454 +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 freetype
import os
import gx
import oldgg as gg
import glm
import gl
/*
TODO
!!!!!!
Use a font atlas
!!!!!!
*/
#flag windows -I @VROOT/thirdparty/freetype/include
#flag windows -L @VROOT/thirdparty/freetype/win64
#flag solaris -I/opt/local/include/freetype2
#flag solaris -L/opt/local/lib
#flag darwin -I/usr/local/include/freetype2
// MacPorts
#flag darwin -I/opt/local/include/freetype2
#flag darwin -L/opt/local/lib
#flag freebsd -I/usr/local/include/freetype2
#flag freebsd -Wl -L/usr/local/lib
#flag -lfreetype
// #flag -I @VROOT/thirdparty/freetype
// #flag @VROOT/thirdparty/freetype/libfreetype.a
#flag darwin -lpng -lbz2 -lz
#flag linux -I/usr/include/freetype2
#flag linux -I.
#include "ft2build.h"
#include FT_FREETYPE_H
fn C.FT_Init_FreeType() voidptr
fn C.FT_New_Face() voidptr
fn C.FT_Set_Pixel_Sizes()
pub const (
default_font_size = 12
)
struct Character {
code i64
texture_id u32
size gg.Vec2
horizontal_bearing_px gg.Vec2
horizontal_advance_px u32
vertical_bearing_px gg.Vec2
vertical_advance_px u32
}
[typedef]
struct C.FT_Library {
}
pub struct FreeType {
shader gl.Shader
width int
height int
vao u32
rect_vao u32
rect_vbo u32
line_vao u32
line_vbo u32
vbo u32
chars []Character
face &C.FT_FaceRec
scale int // retina = 2 , normal = 1
mut:
utf_runes []string
utf_chars []Character
}
struct C.Bitmap {
width int
rows int
buffer int
}
struct C.Advance {
x int
y int
}
[typedef]
struct C.FT_Glyph_Metrics {
width int
height int
horiBearingX int
horiBearingY int
horiAdvance int
vertBearingX int
vertBearingY int
vertAdvance int
}
struct C.Glyph {
bitmap C.Bitmap
bitmap_left int
bitmap_top int
advance Advance
metrics C.FT_Glyph_Metrics
}
[typedef]
struct C.FT_FaceRec {
glyph &C.Glyph
family_name charptr
style_name charptr
}
// /type FT_Face &C.FT_FaceRec
fn C.FT_Load_Char(voidptr, i64, int) int
fn ft_load_char(face &C.FT_FaceRec, code i64) Character {
// println('\nftload_char( code=$code)')
// C.printf('face=%p\n', face)
// C.printf('cobj=%p\n', _face.cobj)
ret := C.FT_Load_Char(face, code, C.FT_LOAD_RENDER | C.FT_LOAD_FORCE_AUTOHINT)
// println('ret=$ret')
if ret != 0 {
println('freetype: failed to load glyph (utf32 code=$code, ' + 'error code=$ret)')
return Character{
code: code
}
}
// Generate texture
mut texture := 0
C.glGenTextures(1, &texture)
C.glBindTexture(C.GL_TEXTURE_2D, texture)
fgwidth := (*face).glyph.bitmap.width
fgrows := (*face).glyph.bitmap.rows
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RED, fgwidth, fgrows, 0, C.GL_RED, C.GL_UNSIGNED_BYTE,
(*face).glyph.bitmap.buffer)
// Set texture options
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_S, C.GL_CLAMP_TO_EDGE)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_WRAP_T, C.GL_CLAMP_TO_EDGE)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
// Create the character
return Character {
code: code
texture_id: u32(texture)
size: gg.vec2(fgwidth, fgrows)
// Note: 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))
horizontal_bearing_px: gg.vec2((*face).glyph.metrics.horiBearingX >> 6, (*face).glyph.metrics.horiBearingY >> 6)
vertical_bearing_px: gg.vec2((*face).glyph.metrics.vertBearingX >> 6, (*face).glyph.metrics.vertBearingY >> 6) // not used for now
horizontal_advance_px: u32((*face).glyph.metrics.horiAdvance) >> 6
vertical_advance_px: u32((*face).glyph.metrics.vertAdvance) >> 6
}
}
pub fn new_context(cfg gg.Cfg) &FreeType {
scale := cfg.scale
// Can only have text in ortho mode
if !cfg.use_ortho {
return &FreeType{
face: 0
}
}
width := cfg.width * scale
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?
gl.enable(C.GL_BLEND)
C.glBlendFunc(C.GL_SRC_ALPHA, C.GL_ONE_MINUS_SRC_ALPHA)
shader := gl.new_shader('text')
shader.use()
projection := glm.ortho(0, f32(width), 0, f32(height)) // 0 at BOT
shader.set_mat4('projection', projection)
// FREETYPE
ft := C.FT_Library{}
// All functions return a value different than 0 whenever
// an error occurred
mut ret := C.FT_Init_FreeType(&ft)
if ret != 0 {
panic('freetype: Could not init FreeType Library')
}
// Load font as face
mut font_path := cfg.font_path
if font_path == '' {
font_path = 'RobotoMono-Regular.ttf'
}
if !os.exists(font_path) {
font_path = os.resource_abs_path(font_path)
}
if !os.exists(font_path) {
eprintln('freetype: font "$font_path" does not exist')
return voidptr(0)
}
face := &C.FT_FaceRec{
glyph: 0
}
ret = int(C.FT_New_Face(ft, font_path.str, 0, &face))
if ret != 0 {
eprintln('freetype: failed to load font (error=$ret) from path: $font_path')
exit(1)
}
// Set size to load glyphs as
C.FT_Set_Pixel_Sizes(face, 0, font_size)
// Disable byte-alignment restriction
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 1)
// Gen texture
// Load first 128 characters of ASCII set
mut chars := []Character{}
for c in 0 .. 128 {
ch := ft_load_char(face, i64(c))
// s := utf32_to_str(uint(0x043f))
// s := 'п'
// ch = ft_load_char(f, s.utf32_code())
// # 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{}
// 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(C.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, C.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);
ctx := &FreeType{
shader: shader
width: width
height: height
scale: scale
vao: vao
vbo: vbo
chars: chars
face: face
}
// ctx.init_utf8_runes()
return ctx
}
pub fn (mut ctx FreeType) draw_text(_x, _y int, text string, cfg gx.TextCfg) {
// utext := text.ustring_tmp()
utext := text.ustring()
ctx.private_draw_text(_x, _y, utext, cfg)
}
fn (mut ctx FreeType) draw_text_fast(_x, _y int, text ustring, cfg gx.TextCfg) {
ctx.private_draw_text(_x, _y, text, cfg)
}
fn (mut ctx FreeType) private_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)
}
}
*/
mut x := f32(_x)
mut y := f32(_y)
wx, wy := ctx.text_size(utext.s)
yoffset := if ctx.scale > 1 { 5 } else { -1 } // 5 hidpi, -1 lowdpi
// println('scale=$ctx.scale size=$cfg.size')
if cfg.align == gx.align_right {
// width := utext.len * 7
width := wx
x -= f32(width + 10)
}
x *= f32(ctx.scale)
y *= f32(ctx.scale)
y += f32(yoffset)
y = f32(ctx.height) - y // invert y direction
color := cfg.color
// Activate corresponding render state
ctx.shader.use()
ctx.shader.set_color('textColor', color)
C.glActiveTexture(C.GL_TEXTURE0)
gl.bind_vao(ctx.vao)
// Iterate through all characters
// utext := text.ustring()
for i in 0 .. utext.len {
rune_ := utext.at(i)
// println('$i => $rune_')
mut ch := Character{}
mut found := false
if rune_.len == 1 {
idx := rune_[0]
if idx < 0 || idx >= ctx.chars.len {
println('BADE RUNE $rune_')
continue
}
found = true
ch = ctx.chars[rune_[0]]
} else if rune_.len > 1 {
// TODO O(1) use map
for j in 0 .. ctx.utf_runes.len {
rune_j := ctx.utf_runes[j]
if rune_j == rune_ {
ch = ctx.utf_chars[j]
found = true
break
}
}
}
// A new Unicode character. Load it and cache it.
if !found && rune_.len > 0 && rune_[0] > 32 {
// c := rune_[0]
// println('cant draw rune "$rune_" code=$c, loading')
// continue
ch = ft_load_char(ctx.face, rune_.utf32_code())
// println('done loading')
ctx.utf_runes << rune_
ctx.utf_chars << ch
// exit(1)
// continue
}
xpos := x + f32(ch.horizontal_bearing_px.x) * 1
ypos := y - f32(ch.size.y + wy - ch.horizontal_bearing_px.y) * 1
// ypos := y - wy
w := f32(ch.size.x) * 1
h := f32(ch.size.y) * 1
// Update VBO for each character
vertices := [
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]
// Render glyph texture over quad
C.glBindTexture(C.GL_TEXTURE_2D, ch.texture_id)
// Update content of VBO memory
gl.bind_buffer(C.GL_ARRAY_BUFFER, ctx.vbo)
// glBufferSubData(..)
C.glBufferData(C.GL_ARRAY_BUFFER, 96, vertices.data, C.GL_DYNAMIC_DRAW)
// Render quad
gl.draw_arrays(C.GL_TRIANGLES, 0, 6)
x += f32(ch.horizontal_advance_px)
// Stop drawing if the limit is reached
if cfg.max_width > 0 {
if x >= cfg.max_width {
// break
}
}
}
gl.bind_vao(u32(0))
C.glBindTexture(C.GL_TEXTURE_2D, 0)
}
pub fn (mut ctx FreeType) 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 (mut ctx FreeType) text_width(s string) int {
x, _ := ctx.text_size(s)
return x
}
pub fn (mut ctx FreeType) text_height(s string) int {
_, y := ctx.text_size(s)
return y
}
pub fn (mut ctx FreeType) text_size(s string) (int, int) {
// t := time.ticks()
utext := s.ustring()
mut x := u32(0)
mut maxy := u32(0)
mut rune_ := ''
mut ch := Character{}
for i in 0 .. utext.len {
rune_ = utext.at(i)
ch = Character{}
mut found := false
if rune_.len == 1 {
idx := rune_[0]
if idx < 0 || idx >= ctx.chars.len {
println('BADE RUNE $rune_')
continue
}
found = true
ch = ctx.chars[rune_[0]]
} else if rune_.len > 1 {
// TODO O(1) use map
for j in 0 .. ctx.utf_runes.len {
rune_j := ctx.utf_runes[j]
if rune_j == rune_ {
ch = ctx.utf_chars[j]
found = true
break
}
}
}
if !found && rune_.len > 0 && rune_[0] > 32 {
ch = ft_load_char(ctx.face, rune_.utf32_code())
ctx.utf_runes << rune_
ctx.utf_chars << ch
}
x += ch.horizontal_advance_px
if maxy < ch.vertical_advance_px {
maxy = ch.vertical_advance_px
}
}
// println('text width "$s" = ${time.ticks() - t} ms')
// scaled_x := x
// scaled_y := maxy
scaled_x := int(f64(x) / ctx.scale)
scaled_y := int(f64(maxy) / ctx.scale)
// println('text_size of "${s}" | x,y: $x,$maxy | scaled_x: ${scaled_x:3d} | scaled_y: ${scaled_y:3d} ')
return scaled_x, scaled_y
}
/*
pub fn (f FT_Face) str() string {
return 'FT_Face{ style_name: ${ptr_str(f.style_name)} family_name: ${ptr_str(f.family_name)} }'
}
*/
pub fn (ac []Character) str() string {
mut res := []string{}
for c in ac {
res << ' Character{ code: $c.code , texture_id: $c.texture_id }'
}
return '[\n' + res.join(',\n') + ']'
}

View File

@ -1,203 +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 gl
import gx
import glm
// import os
// import darwin
pub struct Shader {
program_id int
}
pub fn (s Shader) str() string {
return 'Shader{ program_id: s.program_id }'
}
pub const (
text_vert = '#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;
uniform mat4 projection;
void main()
{
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
TexCoords = vertex.zw;
} '
text_frag = '#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D text;
uniform vec3 textColor;
void main()
{
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
color = vec4(textColor, 1.0) * sampled;
} '
simple_vert = ' #version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(aPos, 1.0);
// gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
//TexCoord = vec2(aTexCoord.x, aTexCoord.y);
TexCoord = aTexCoord;
}
'
simple_frag = '#version 330 core
out vec4 FragColor;
uniform vec3 color;
uniform bool has_texture;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main() {
// FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
// FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
if (has_texture) {
/*
vec3 chromaKeyColor = texture(ourTexture,TexCoord.xy).xyz;
float alpha;
bool is_cyan = ((chromaKeyColor.x == 0)); // && chromaKeyColor.x <= 1) && (chromaKeyColor.y <= 255) &&
bool is_pink= ((chromaKeyColor.y == 0));
//bool is_pink= ((chromaKeyColor.x <= 255) && (chromaKeyColor.y == 0) &&(chromaKeyColor.z <= 255));
if (is_cyan || is_pink) {
alpha = 0.;
}
else
{
alpha = 1.0;
}
FragColor= vec4(texture(ourTexture,TexCoord.xy).xyz,alpha);
*/
FragColor = texture(ourTexture, TexCoord);
} else {
FragColor = vec4(color, 1.0f);
}
}
'
)
pub fn new_shader(name string) Shader {
// TODO This is not used, remove
mut dir := ''
// Already have absolute path
if name.starts_with('/') {
dir = ''
}
//vertex_path := '${dir}${name}.vert'
//fragment_path := '${dir}${name}.frag'
//println('shader path=$vertex_path,\n fpath="$fragment_path"')
// vertex_src := os.read_file(vertex_path.trim_space())
mut vertex_src := ''
mut fragment_src := ''
if name == 'text' {
vertex_src = text_vert
fragment_src = text_frag
}
else if name == 'simple' {
// println('new shader simple!!!')
// println(simple_vert)
vertex_src = simple_vert
fragment_src = simple_frag
}
// ////////////////////////////////////////
vertex_shader := gl.create_shader(C.GL_VERTEX_SHADER)
gl.shader_source(vertex_shader, 1, vertex_src, 0)
gl.compile_shader(vertex_shader)
if gl.shader_compile_status(vertex_shader) == 0 {
cerror := gl.shader_info_log(vertex_shader)
eprintln('vertex ${vertex_shader} shader compilation failed')
eprintln('shader source = ${vertex_src}')
eprintln('failed to compile, with error')
eprintln(cerror)
exit(1)
}
// fragment shader
// fragment_src := os.read_file(fragment_path.trim_space())
fragment_shader := gl.create_shader(C.GL_FRAGMENT_SHADER)
gl.shader_source(fragment_shader, 1, fragment_src, 0)
gl.compile_shader(fragment_shader)
if gl.shader_compile_status(fragment_shader) == 0 {
cerror := gl.shader_info_log(fragment_shader)
eprintln('fragment ${fragment_shader} shader compilation failed')
eprintln('shader source = ${fragment_src}')
eprintln('failed to compile, with error')
eprintln(cerror)
exit(1)
}
// link shaders
shader_program := gl.create_program()
gl.attach_shader(shader_program, vertex_shader)
gl.attach_shader(shader_program, fragment_shader)
gl.link_program(shader_program)
// check for linking errors
success := gl.get_program_link_status(shader_program)
if success == 0 {
cerror := gl.shader_info_log(shader_program)
eprintln('shader program linking failed')
eprintln('vertex source = ${vertex_src}')
eprintln('fragment source = ${fragment_src}')
eprintln('failed to compile, with error')
eprintln(cerror)
exit(1)
}
shader := Shader {
program_id: shader_program,
}
return shader
}
pub fn (s Shader) use() {
gl.use_program(s.program_id)
}
fn C.glUniformMatrix4fv()
fn C.glUniform1i()
fn C.glUniform3f()
pub fn (s Shader) uni_location(key string) int {
return C.glGetUniformLocation(s.program_id, key.str)
}
// fn (s Shader) set_mat4(str string, f *f32) {
pub fn (s Shader) set_mat4(str string, m glm.Mat4) {
// TODO cache uniform location
C.glUniformMatrix4fv(s.uni_location(str), 1, false, m.data)
}
pub fn (s Shader) set_int(str string, n int) {
C.glUniform1i(s.uni_location(str), n)
}
pub fn (s Shader) set_color(str string, c gx.Color) {
C.glUniform3f(s.uni_location(str), f32(c.r) / 255.0, f32(c.g) / 255.0, f32(c.b) / 255.0)
}

View File

@ -1,398 +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 gl
import glm
#flag -I @VROOT/thirdparty/glad
#include "glad.h"
#flag @VROOT/thirdparty/glad/glad.o
// joe-c: fix & remove
pub enum TmpGlImportHack{ non_empty }
fn C.gladLoadGL() int
fn C.glDisable()
fn C.glEnable()
fn C.glScissor()
fn C.glVertexAttribPointer()
fn C.glGenBuffers()
fn C.glEnableVertexAttribArray()
fn C.glDisableVertexAttribArray()
fn C.glGenVertexArrays()
fn C.glDrawElements()
fn C.glUseProgram()
fn C.glValidateProgram()
fn C.glDrawArrays()
fn C.glBufferData()
fn C.glGenerateMipmap()
fn C.glTexParameteri()
fn C.glDeleteTextures()
fn C.glBindTexture()
fn C.glActiveTexture()
fn C.glGenTextures()
fn C.glBindBuffer()
fn C.glBindVertexArray()
fn C.glGetProgramInfoLog()
fn C.glGetShaderInfoLog()
fn C.glDeleteShader()
fn C.glGetProgramiv()
fn C.glLinkProgram()
fn C.glAttachShader()
fn C.glDetachShader()
fn C.glGetShaderiv()
fn C.glCompileShader()
fn C.glShaderSource()
fn C.glCreateProgram() int
fn C.glDeleteProgram()
fn C.glClear()
fn C.glCreateShader() int
fn C.glClearColor()
fn C.glViewport()
fn C.glPixelStorei()
fn C.glBlendFunc()
fn C.glPolygonMode()
fn C.glDeleteBuffers()
fn C.glDeleteVertexArrays()
fn C.glGetUniformLocation() int
fn C.glGetAttribLocation() int
fn C.glBindAttribLocation()
fn C.glUniform1f()
// init_glad initializes glad, which is needed to use other functions.
pub fn init_glad() {
ok := C.gladLoadGL()
if ok == 0 {
println('Failed to initialize glad OpenGL context')
exit(1)
}
}
// viewport declares the area, which should be rendered in the window.
// Should be used on resizing the window.
pub fn viewport(x, y, width, height int) {
C.glViewport(x, y, width, height)
}
// clear_color sets the color, which will be the background, where you can draw.
// Need only set once.
pub fn clear_color(r, g, b, a int) {
C.glClearColor(f32(r)/255.0, f32(g)/255.0, f32(b)/255.0, f32(a)/255.0)
}
// clear clears the bits of the last frame (ColorBufferBit, DepthBufferBit, StencilBufferBit) to store new data.
// Should be done every frame.
pub fn clear() {
C.glClear(C.GL_COLOR_BUFFER_BIT | C.GL_DEPTH_BUFFER_BIT | C.GL_STENCIL_BUFFER_BIT)
}
// create_shader creates a shader in OpenGL and returns the id.
pub fn create_shader(typ int) int {
return C.glCreateShader(typ)
}
// Create a program in OpenGL and returns the id.
// A shader can be attached to a program, which is required to use them.
pub fn create_program() int {
return C.glCreateProgram()
}
// Delete a program by id.
// Cleanup method, should be used after the main game loop
pub fn delete_program(program int) {
C.glDeleteProgram(program)
}
// shader_source attaches source code to the shader via the shaderID.
// Could be also used to load multiple sources into a shader.
// To just add one source code to one shader use: `gl.shader_source(shader, 1, src, 0)`
pub fn shader_source(shader, count int, source string, length int) {
C.glShaderSource(shader, count, &source.str, length)
}
// compile_shader compiles the shader's source code.
// OpenGL compiles the source code at runtime.
pub fn compile_shader(shader int) {
C.glCompileShader(shader)
}
// shader_compile_status returns the compile status of the shader compilation.
// Can be used to check the compilation and see for errors in the shader code via `gl.shader_info_log()`
pub fn shader_compile_status(shader int) int {
success := 0
C.glGetShaderiv(shader, C.GL_COMPILE_STATUS, &success)
return success
}
// attach_shader attaches a shader to a program.
// Required for drawing things on the screen
pub fn attach_shader(program, shader int) {
C.glAttachShader(program, shader)
}
// detach_shader detaches a shader of a program
// Cleanup method
pub fn detach_shader(program, shader int) {
C.glDetachShader(program, shader)
}
// link_program links a program as target.
// This let OpenGL know, which program has to be use.
pub fn link_program(program int) {
C.glLinkProgram(program)
}
// get_program_link_status returns the link status of linking the program
pub fn get_program_link_status(program int) int {
success := 0
C.glGetProgramiv(program, C.GL_LINK_STATUS, &success)
return success
}
// validate_program checks that the shaders in the program can be executed
pub fn validate_program(program int) {
C.glValidateProgram(program)
}
// delete_shader deletes a shader via the shaderID
// Cleanup method
pub fn delete_shader(shader int) {
C.glDeleteShader(shader)
}
// shader_info_log returns a info log of the shader.
// Can be used to print compilation errors.
pub fn shader_info_log(shader int) string {
info_log := [512]byte
C.glGetShaderInfoLog(shader, 512, 0, info_log)
return tos_clone(info_log)
}
// get_program_info_log returns a info log of the program.
// Can be used to print linking errors etc.
pub fn get_program_info_log(program int) string {
info_log := [1024]byte
C.glGetProgramInfoLog(program, 1024, 0, info_log)
return tos_clone(info_log)
}
// bind_vao binds a vertex array buffer to OpenGL.
// Says OpenGL which vao is the target.
pub fn bind_vao(vao u32) {
C.glBindVertexArray(vao)
}
// bind_buffer binds a vertex buffer object to OpenGL.
// Says OpenGL which vbo is the target.
pub fn bind_buffer(typ int, vbo u32) {
C.glBindBuffer(typ, vbo)
}
// gen_texture generates a textureID.
// Needed to use texturing.
pub fn gen_texture() u32 {
res := u32(0)
C.glGenTextures(1, &res)
return res
}
// active_texture activates a texture.
// If you don't do this, texture isn't working.
pub fn active_texture(t int) {
C.glActiveTexture(t)
}
// bind_2d_texture binds the activated texture as a 2D texture.
// Helper method.
pub fn bind_2d_texture(texture u32) {
C.glBindTexture(C.GL_TEXTURE_2D, texture)
}
// bind_texture binds the activated texture to a texture type.
// Defines the type for texture.
pub fn bind_texture(texture, typ u32) {
C.glBindTexture(typ, texture)
}
// delete_texture deletes a texture by ID.
// Cleanup method.
pub fn delete_texture(texture u32) {
C.glDeleteTextures(1, &texture)
}
// buffer_data puts data into a buffer.
// With these methods, data can put into a buffer.
// Common usage for C.GL_ARRAY_BUFFER or C.GL_ELEMENT_ARRAY_BUFFER.
pub fn buffer_data(typ, size int, arr voidptr, draw_typ int) {
C.glBufferData(typ, size, arr, draw_typ)
}
// buffer_data_int puts int into a buffer.
pub fn buffer_data_int(typ int, vertices []int, draw_typ int) {
size := sizeof(int) * u32(vertices.len)
C.glBufferData(typ, size, vertices.data, draw_typ)
}
// buffer_data_f32 puts float into a buffer.
pub fn buffer_data_f32(typ int, vertices []f32, draw_typ int) {
size := sizeof(f32) * u32(vertices.len)
C.glBufferData(typ, size, vertices.data, draw_typ)
}
// set_vbo sets vertices into a vertex buffer object.
// Helper method.
pub fn set_vbo(vbo u32, vertices []f32, draw_typ int) {
gl.bind_buffer(C.GL_ARRAY_BUFFER, vbo)
gl.buffer_data_f32(C.GL_ARRAY_BUFFER, vertices, draw_typ)
}
// set_ebo sets indices into a element array buffer.
// Helper method.
pub fn set_ebo(ebo u32, indices []int, draw_typ int) {
gl.bind_buffer(C.GL_ELEMENT_ARRAY_BUFFER, ebo)
gl.buffer_data_int(C.GL_ELEMENT_ARRAY_BUFFER, indices, draw_typ)
}
// delete_buffer deletes a vertex buffer object.
// Cleanup method.
pub fn delete_buffer(vbo u32) {
C.glDeleteBuffers(1, vbo)
}
// delete_vao deletes a vertex array object.
// Cleanup method.
pub fn delete_vao(vao u32) {
C.glDeleteVertexArrays(1, vao)
}
// get_uniform_location gets the uniform location for key in program.
// Required to put uniform data in shader at runtime.
pub fn get_uniform_location(program int, key string) int {
return C.glGetUniformLocation(program, key.str)
}
// get_attrib_location gets the attribute location for key in program.
// Required to put attrib data in shader at runtime.
pub fn get_attrib_location(program int, key string) int {
return C.glGetAttribLocation(program, key.str)
}
// bind_attrib_location binds a attrib on index in program to a name.
// Used to send data into a shader.
pub fn bind_attrib_location(program int, index int, name string) {
C.glBindAttribLocation(program, index, name.str)
}
// draw_arrays draws the vertex buffer object on screen.
// Commonly start is 0 and len 3 (without textures) or 5 (with textures).
// Mode commonly C.GL_TRIANGLES.
pub fn draw_arrays(mode, start, len int) {
C.glDrawArrays(mode, start, len)
}
// draw_elements draws the element object buffer on screen.
// Commonly typ is C.GL_UNSIGNED_INT and mode C.GL_TRIANGLES.
pub fn draw_elements(mode, count, typ, indices int) {
C.glDrawElements(mode, count, typ, indices)
}
// use_program binds program to OpenGL.
// Defines the program which is the target.
pub fn use_program(program int) {
C.glUseProgram(program)
}
// gen_vertex_array generates a vertex array ID.
// Linked to an empty vertex array.
pub fn gen_vertex_array() u32 {
vao := u32(0)
C.glGenVertexArrays(1, &vao)
return vao
}
// enable_vertex_attrib_array enables a vertex attrib array by index.
pub fn enable_vertex_attrib_array(n int) {
C.glEnableVertexAttribArray(n)
}
// disable_vertex_attrib_array disabled a vertex attrib array by index.
pub fn disable_vertex_attrib_array(n int) {
C.glDisableVertexAttribArray(n)
}
// gen_buffer generates an buffer ID.
// Linked to an empty buffer-
pub fn gen_buffer() u32 {
vbo := u32(0)
C.glGenBuffers(1, &vbo)
return vbo
}
// vertex_attrib_pointer defines the activated array by index.
pub fn vertex_attrib_pointer(index, size int, typ int, normalized bool, _stride int, _ptr int) {
mut stride := u32(_stride)
mut ptr := _ptr
if typ == C.GL_FLOAT {
stride *= sizeof(f32)
ptr *= int(sizeof(f32))
}
C.glVertexAttribPointer(index, size, typ, normalized, stride, ptr)
}
// tex_param attachs texture value as int to a texture by ID.
pub fn tex_param(key, val int) {
C.glTexParameteri(C.GL_TEXTURE_2D, key, val)
}
// enable enables various capabilities for OpenGL.
pub fn enable(val int) {
C.glEnable(val)
}
// disable disables various capabilities for OpenGL.
pub fn disable(val int) {
C.glDisable(val)
}
// scissor defines a rectangle in the window.
pub fn scissor(x, y, width, height int) {
C.glScissor(x, y, height, height)
}
pub fn generate_mipmap(typ int) {
C.glGenerateMipmap(typ)
}
// set_mat4fv sets a mat4 at uniform location.
// Used for almost every view stuff in OpenGL.
pub fn set_mat4fv(loc, count int, transpose bool, val glm.Mat4) {
C.glUniformMatrix4fv(loc, count, transpose, val.data)
}
// set_f32 sets a float at uniform location.
// Usable for global lighing.
pub fn set_f32(loc int, val f32) {
C.glUniform1f(loc, val)
}
// set_vec sets a vec3 at uniform location.
// Usable to set locations or colors.
pub fn set_vec(loc int, x, y, z f32) {
C.glUniform3f(loc, x, y, z)
}
// set_bool sets a bool at uniform location.
// Send states to the shader.
pub fn set_bool(loc int, val bool) {
if val {
set_f32(loc, 1)
} else {
set_f32(loc, 0)
}
}

View File

@ -1,373 +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 glfw
import gl
// note: we might need special case for this
// see TmpGlImportHack below (joe-c)
#flag -I @VROOT/thirdparty/glfw
#flag -L @VROOT/thirdparty/glfw
// Debugging a custom build
//-#flag darwin -L/var/tmp/glfw/src/
// MacPorts
#flag darwin -L/opt/local/lib
#flag darwin -lglfw
#flag freebsd -I/usr/local/include
#flag freebsd -Wl,-L/usr/local/lib,-lglfw
#flag solaris -I/opt/local/include
#flag solaris -L/opt/local/lib
#flag solaris -lglfw
#flag linux -lglfw
#flag windows -lgdi32 -lshell32 -lglfw3
#flag mingw -mwindows
#include <GLFW/glfw3.h>
// #flag darwin -framework Carbon
// #flag darwin -framework Cocoa
// #flag darwin -framework CoreVideo
// #flag darwin -framework IOKit
pub const (
resizable = 1
decorated = 2
)
pub const (
key_escape = 256
key_space = 32
key_left_super = 343
key_up = 265
key_left = 263
key_right = 262
key_down = 264
)
fn C.glfwGetWindowUserPointer() voidptr
fn C.glfwGetPrimaryMonitor() voidptr
fn C.glfwSetWindowUserPointer()
fn C.glfwSetCursor()
fn C.glfwGetCursorPos()
fn C.glfwSetClipboardString()
fn C.glfwGetWindowContentScale()
fn C.glfwGetClipboardString()
fn C.glfwGetKey()
fn C.glfwGetTime() f64
fn C.glfwSetCharModsCallback()
fn C.glfwSetKeyCallback()
fn C.glfwPostEmptyEvent()
fn C.glfwSetScrollCallback()
fn C.glfwSetWindowSizeCallback()
fn C.glfwSetMouseButtonCallback()
fn C.glfwSetCursorPosCallback()
fn C.glfwSwapBuffers()
fn C.glfwWindowShouldClose() bool
fn C.glfwSetWindowShouldClose()
fn C.glfwWaitEvents()
fn C.glfwPollEvents()
fn C.glfwSwapInterval()
fn C.glfwMakeContextCurrent()
fn C.glfwSetWindowTitle()
fn C.glfwTerminate()
fn C.glfwCreateWindow(w int, h int, title charptr, m voidptr, sh voidptr) voidptr
fn C.glfwWindowHint()
fn C.glfwDestroyWindow()
fn C.glfwInit()
fn C.glGetIntegerv()
// joe-c: fix & remove
struct TmpGlImportHack {
hack gl.TmpGlImportHack
}
pub struct WinCfg {
width int
height int
title string
ptr voidptr
borderless bool
is_modal int
is_browser bool
url string
always_on_top bool
scale_to_monitor bool = true
}
// data *C.GLFWwindow
// TODO change data to cobj
pub struct Window {
data voidptr
title string
mx int
my int
scale_ f32
}
pub struct Size {
pub:
width int
height int
}
pub struct Pos {
pub:
x int
y int
}
// type clickpub fn pub fn (window * GLFWwindow, button, action, mods int)
type ClickPubFn fn (window voidptr, button, action, mods int)
/*
* TODO broken
fn init() {
init_glfw()
}
*/
pub fn init_glfw() {
C.glfwInit()
C.glfwWindowHint(C.GLFW_CONTEXT_VERSION_MAJOR, 3)
C.glfwWindowHint(C.GLFW_CONTEXT_VERSION_MINOR, 3)
C.glfwWindowHint(C.GLFW_OPENGL_FORWARD_COMPAT, C.GL_TRUE)
C.glfwWindowHint(C.GLFW_OPENGL_PROFILE, C.GLFW_OPENGL_CORE_PROFILE)
}
pub fn (w &Window) destroy() {
C.glfwDestroyWindow(w.data)
}
pub fn terminate() {
C.glfwTerminate()
}
// pub fn mouse_move(w * GLFWwindow, x, y double) {
pub fn mouse_move(w voidptr, x, y f64) {
// #printf("%f : %f => %d \n", x,y);
}
pub fn window_hint(key, val int) {
C.glfwWindowHint(key, val)
}
pub fn create_window(c WinCfg) &Window {
if c.borderless {
window_hint(C.GLFW_RESIZABLE, 0)
window_hint(C.GLFW_DECORATED, 0)
}
if c.always_on_top {
window_hint(C.GLFW_FLOATING, 1)
}
if c.scale_to_monitor {
$if windows {
window_hint(C.GLFW_SCALE_TO_MONITOR, 1)
}
}
cwindow := C.glfwCreateWindow(c.width, c.height, c.title.str, 0, 0)
if isnil(cwindow) {
println('failed to create a glfw window, make sure you have a GPU driver installed')
C.glfwTerminate()
}
// println('create window wnd=$cwindow ptr==$c.ptr')
C.glfwSetWindowUserPointer(cwindow, c.ptr)
mut scale := f32(1.0)
$if windows {
C.glfwGetWindowContentScale(cwindow, &scale, &scale)
}
$else {
scale = 1.0
}
window := &Window {
data: cwindow,
title: c.title,
scale_: scale
}
return window
}
pub fn (w &Window) set_title(title string) {
C.glfwSetWindowTitle(w.data, title.str)
}
pub fn (w &Window) make_context_current() {
C.glfwMakeContextCurrent(w.data)
}
pub fn (w &Window) scale() f32 {
return w.scale_
}
pub fn swap_interval(interval int) {
C.glfwSwapInterval(interval)
}
pub fn wait_events() {
C.glfwWaitEvents()
}
pub fn poll_events() {
C.glfwPollEvents()
}
pub fn set_should_close(w voidptr, close bool) {
C.glfwSetWindowShouldClose(w, close)
}
pub fn (w &Window) set_should_close(close bool) {
C.glfwSetWindowShouldClose(w.data, close)
}
pub fn (w &Window) should_close() bool {
return C.glfwWindowShouldClose(w.data)
}
pub fn (w &Window) swap_buffers() {
C.glfwSwapBuffers(w.data)
}
pub fn (mut w Window) onmousemove(cb voidptr) {
C.glfwSetCursorPosCallback(w.data, cb)
}
pub fn (mut w Window) set_mouse_button_callback(cb voidptr) {
C.glfwSetMouseButtonCallback(w.data, cb)
}
pub fn (mut w Window) on_resize(cb voidptr) {
C.glfwSetWindowSizeCallback(w.data, cb)
}
pub fn (mut w Window) on_click(cb voidptr) {
C.glfwSetMouseButtonCallback(w.data, cb)
}
pub fn (w &Window) set_scroll_callback(cb voidptr) {
C.glfwSetScrollCallback(w.data, cb)
}
pub fn (w &Window) on_scroll(cb voidptr) {
C.glfwSetScrollCallback(w.data, cb)
}
pub fn post_empty_event() {
C.glfwPostEmptyEvent()
}
pub fn (mut w Window) onkeydown(cb voidptr) {
C.glfwSetKeyCallback(w.data, cb)
}
pub fn (mut w Window) onchar(cb voidptr) {
C.glfwSetCharModsCallback(w.data, cb)
}
pub fn get_time() f64 {
return C.glfwGetTime()
}
pub fn key_pressed(wnd voidptr, key int) bool {
return int(C.glfwGetKey(wnd, key)) == C.GLFW_PRESS
}
pub fn (w &Window) get_clipboard_text() string {
return string(byteptr(C.glfwGetClipboardString(w.data)))
}
pub fn (w &Window) set_clipboard_text(s string) {
C.glfwSetClipboardString(w.data, s.str)
}
pub fn get_cursor_pos(cwindow voidptr) (f64, f64) {
x := f64(0)
y := f64(0)
C.glfwGetCursorPos(cwindow, &x, &y)
mut scale := f32(1.0)
$if windows {
C.glfwGetWindowContentScale(cwindow, &scale, &scale)
}
$else {
scale = 1.0
}
return x/scale, y/scale
}
pub fn (w &Window) get_cursor_pos() Pos {
x := f64(0)
y := f64(0)
C.glfwGetCursorPos(w.data, &x, &y)
return Pos {
x: int(x/w.scale_)
y: int(y/w.scale_)
}
}
enum Cursor {
arrow
ibeam
hand
}
pub fn set_cursor(c Cursor) {
C.glfwSetCursor(0, C.GLFW_IBEAM_CURSOR)
}
pub fn (w &Window) set_cursor(c Cursor) {
C.glfwSetCursor(w.data, C.GLFW_IBEAM_CURSOR)
}
pub fn (w &Window) user_ptr() voidptr {
return C.glfwGetWindowUserPointer(w.data)
}
pub fn (w &Window) set_user_ptr(ptr voidptr) {
C.glfwSetWindowUserPointer(w.data, ptr)
}
struct C.GLFWvidmode {
width int
height int
}
pub fn C.glfwGetVideoMode() &C.GLFWvidmode
pub fn get_monitor_size() Size {
//# GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
mode := C.glfwGetVideoMode(C.glfwGetPrimaryMonitor())
return Size{mode.width, mode.height}
}
fn C.glfwGetWindowSize(window &Window, width &int, height &int) // screen coordinates
fn C.glfwGetFramebufferSize(window &Window, width &int, height &int) // pixels
// get_window_size in screen coordinates
pub fn (w &Window) get_window_size() Size {
res := Size {0, 0}
C.glfwGetWindowSize(w.data, &res.width, &res.height)
return res
}
// get_framebuffer_size in pixels
pub fn (w &Window) get_framebuffer_size() Size {
res := Size {0, 0}
C.glfwGetFramebufferSize(w.data, &res.width, &res.height)
return res
}
pub fn (size Size) str() string {
return '{$size.width, $size.height}'
}
pub fn get_window_user_pointer(gwnd voidptr) voidptr {
return C.glfwGetWindowUserPointer(gwnd)
}

View File

@ -1,3 +0,0 @@
`gg` will be moved to its own repository:
https://github.com/vlang/gg

View File

@ -1,553 +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 oldgg
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)
}

View File

@ -1,37 +0,0 @@
module oldgg
import gl
import gx
import math
fn arc_vertices(x, y, r, start_angle, end_angle f32, segments int) []f32 {
mut vertices := []f32{}
start_rads := start_angle * 0.0174533 // deg -> rad approx
end_rads := end_angle * 0.0174533
increment := (end_rads - start_rads) / f32(segments)
vertices << [x + f32(math.cos(start_rads)) * r, y + f32(math.sin(start_rads)) * r] !
mut i := 1
for i < segments {
theta := f32(i) * increment + start_rads
vertices << [x + f32(math.cos(theta)) * r, y + f32(math.sin(theta)) * r] !
i++
}
vertices << [x + f32(math.cos(end_rads)) * r, y + f32(math.sin(end_rads)) * r] !
return vertices
}
fn (ctx &GG) use_color_shader(color gx.Color) {
ctx.shader.set_int('has_texture', 0)
C.glDeleteBuffers(1, &ctx.vao)
C.glDeleteBuffers(1, &ctx.vbo)
ctx.shader.use()
ctx.shader.set_color('color', color)
}
fn (ctx &GG) bind_vertices(vertices []f32) {
gl.bind_vao(ctx.vao)
gl.set_vbo(ctx.vbo, vertices, C.GL_STATIC_DRAW)
gl.vertex_attrib_pointer(0, 2, C.GL_FLOAT, false, 2, 0)
gl.enable_vertex_attrib_array(0)
gl.bind_vao(ctx.vao)
}

View File

@ -100,12 +100,16 @@ fn (mut g Gen) comp_if(it ast.CompIf) {
}
fn (mut g Gen) comp_for(node ast.CompFor) {
g.writeln('// comptime $' + 'for {')
g.writeln('// 2comptime $' + 'for {')
sym := g.table.get_type_symbol(g.unwrap_generic(node.typ))
vweb_result_type := table.new_type(g.table.find_type_idx('vweb.Result'))
mut i := 0
// g.writeln('string method = tos_lit("");')
for method in sym.methods {
if method.attrs.len == 0 {
// if method.attrs.len == 0 {
// continue
// }
if method.return_type != vweb_result_type { // table.void_type {
continue
}
g.comp_for_method = method.name
@ -117,7 +121,11 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
if i == 0 {
g.write('\tstring ')
}
g.writeln('attrs = tos_lit("${method.attrs[0]}");')
if method.attrs.len == 0 {
g.writeln('attrs = tos_lit("");')
} else {
g.writeln('attrs = tos_lit("${method.attrs[0]}");')
}
g.stmts(node.stmts)
i++
g.writeln('')

View File

@ -54,6 +54,14 @@ pub mut:
page_gen_start i64
}
pub struct Cookie {
name string
value string
exprires time.Time
secure bool
http_only bool
}
pub struct Result {}
fn (mut ctx Context) send_response_to_client(mimetype string, res string) bool {
@ -108,10 +116,17 @@ pub fn (mut ctx Context) not_found() Result {
return vweb.Result{}
}
pub fn (mut ctx Context) set_cookie(key, val string) {
pub fn (mut ctx Context) set_cookie(cookie Cookie) {
secure := if cookie.secure { "Secure;" } else { "" }
http_only := if cookie.http_only { "HttpOnly" } else { "" }
ctx.add_header('Set-Cookie', '$cookie.name=$cookie.value; $secure $http_only')
}
pub fn (mut ctx Context) set_cookie_old(key, val string) {
// TODO support directives, escape cookie value (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie)
//println('Set-Cookie $key=$val')
ctx.add_header('Set-Cookie', '${key}=${val}; Secure; HttpOnly')
//ctx.add_header('Set-Cookie', '${key}=${val}; Secure; HttpOnly')
ctx.add_header('Set-Cookie', '${key}=${val}; HttpOnly')
}
pub fn (mut ctx Context) set_content_type(typ string) {
@ -313,39 +328,72 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
}
app.init()
// Call the right action
println('route matching...')
t := time.ticks()
mut action := ''
mut route_words := []string{}
mut ok := true
url_words := vals[1][1..].split('/')
mut vars := []string{cap: route_words.len}
$for method in T {
ok = true
route_words = attrs[1..].split('/')
//println('words:') println(route_words)
//println('vals:') println(url_words)
vars = []string{cap: route_words.len}
if route_words.len <= url_words.len {
// match `/:user/:repo/tree` to `/vlang/v/tree`
for i, word in route_words {
if word.starts_with(':') {
// remember and skip the var
vars << url_words[i]
continue
}
if word != url_words[i] {
ok = false
break
}
}
if ok {
action = method
println('OK !! $action="$action"')
println('\n\n method = $method urlwords=')
println(url_words)
println('attrs=$attrs')
if attrs == '' {
// No routing for this method. If it matches, call it and finish matching
// since such methods have a priority.
// For example URL `/register` matches route `/:user`, but `fn register()`
// should be called first.
println('no attrs for ${url_words[0]}')
if url_words[0] == method {
println('easy match $method')
vars = []
app.$method(vars)
conn.close() or {}
return
}
}
else {
//println('ATTR=$attrs')
route_words = attrs[1..].split('/')
//println('words:') println(route_words)
//println('vals:') println(url_words)
vars = []string{cap: route_words.len}
if route_words.len <= url_words.len {
// match `/:user/:repo/tree` to `/vlang/v/tree`
for i, word in route_words {
if word.starts_with(':') {
// remember and skip the var
vars << url_words[i]
continue
}
if word != url_words[i] {
ok = false
break
}
}
if ok {
//goto end // TODO break in $for
if !route_words[0].starts_with(':') {
// Routes without variables have higher priority, so call it right now
// e.g. `/register` matches `['/:user']`, but `['/register']` should be called first.
//println('OK not var $action="$action"')
app.$method(vars)
conn.close() or {}
return
}
action = method
println('setting action to $method')
}
}
}
}
if action == '' {
conn.send_string(http_404) or {}
}
//end:
// No route matched, just do a simple `/home` => `action=home`
if action == '' {
//println('action is empty because no routes were matched...')
@ -357,10 +405,11 @@ fn handle_conn<T>(conn net.Socket, mut app T) {
action = 'index'
}
}
//$if debug {
$if debug {
println('action=$action')
//}
}
println('route matching took ${time.ticks() - t}ms')
app.$action()
/*
app.$action() or {