remove oldgg, gl, glfw, freetype from vlib now that we have the new sokol based `gg`
parent
96bd4e8794
commit
36183660e6
examples/hot_reload
thirdparty/glfw
vlib
|
@ -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
|
@ -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.
|
@ -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') + ']'
|
||||
}
|
|
@ -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)
|
||||
}
|
398
vlib/gl/gl.v
398
vlib/gl/gl.v
|
@ -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)
|
||||
}
|
||||
}
|
373
vlib/glfw/glfw.v
373
vlib/glfw/glfw.v
|
@ -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)
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
`gg` will be moved to its own repository:
|
||||
|
||||
https://github.com/vlang/gg
|
553
vlib/oldgg/gg.v
553
vlib/oldgg/gg.v
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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('')
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue