summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRay <[email protected]>2020-02-03 18:31:30 +0100
committerGitHub <[email protected]>2020-02-03 18:31:30 +0100
commit40b73a8a91afb26becfcb39560dae73447ce15af (patch)
treec00df37c9488649f694304149b45043165128b71
parent6f3c99a295533e41de3049db5e683d15fd5c6e1a (diff)
downloadraylib-40b73a8a91afb26becfcb39560dae73447ce15af.tar.gz
raylib-40b73a8a91afb26becfcb39560dae73447ce15af.zip
Develop branch integration (#1091)
* [core] REDESIGNED: Implement global context * [rlgl] REDESIGNED: Implement global context * Reviewed globals for Android * Review Android globals usage * Update Android globals * Bump raylib version to 3.0 !!! * [raudio] REDESIGNED: Implement global context * [raudio] Reorder functions * [core] Tweaks on descriptions * Issues with SUPPORT_MOUSE_GESTURES * [camera] Use global context * REDESIGN: Move shapes drawing texture/rec to RLGL context * Review some issues on standalone mode * Update to use global context * [GAME] Upload RE-PAIR game from GGJ2020 -WIP- * Update game: RE-PAIR * [utils] TRACELOG macros proposal * Update config.h
-rw-r--r--games/repair/LICENSE.txt20
-rw-r--r--games/repair/Makefile406
-rw-r--r--games/repair/repair.c416
-rw-r--r--games/repair/resources/background.pngbin0 -> 461621 bytes
-rw-r--r--games/repair/resources/coin.wavbin0 -> 9508 bytes
-rw-r--r--games/repair/resources/elevator_romance.oggbin0 -> 2171286 bytes
-rw-r--r--games/repair/resources/eyes_models.pngbin0 -> 52636 bytes
-rw-r--r--games/repair/resources/font.pngbin0 -> 62597 bytes
-rw-r--r--games/repair/resources/hair_models.pngbin0 -> 227387 bytes
-rw-r--r--games/repair/resources/head_models.pngbin0 -> 89812 bytes
-rw-r--r--games/repair/resources/makeup.pngbin0 -> 21801 bytes
-rw-r--r--games/repair/resources/match.pngbin0 -> 20986 bytes
-rw-r--r--games/repair/resources/mouth_models.pngbin0 -> 12088 bytes
-rw-r--r--games/repair/resources/nose_models.pngbin0 -> 12291 bytes
-rw-r--r--games/repair/resources/npatch.pngbin0 -> 12301 bytes
-rw-r--r--games/repair/resources/qmark.pngbin0 -> 6500 bytes
-rw-r--r--games/repair/resources/raylib_logo.pngbin0 -> 1868 bytes
-rw-r--r--games/repair/resources/title.pngbin0 -> 15267 bytes
-rw-r--r--games/repair/screens/screen_ending.c246
-rw-r--r--games/repair/screens/screen_gameplay.c169
-rw-r--r--games/repair/screens/screen_logo.c211
-rw-r--r--games/repair/screens/screen_title.c134
-rw-r--r--games/repair/screens/screens.h134
-rw-r--r--src/camera.h238
-rw-r--r--src/config.h2
-rw-r--r--src/core.c1541
-rw-r--r--src/gestures.h285
-rw-r--r--src/raudio.c743
-rw-r--r--src/raylib.dll.rc8
-rw-r--r--src/raylib.h5
-rw-r--r--src/raylib.rc8
-rw-r--r--src/rlgl.h957
-rw-r--r--src/shapes.c198
-rw-r--r--src/utils.h12
34 files changed, 3763 insertions, 1970 deletions
diff --git a/games/repair/LICENSE.txt b/games/repair/LICENSE.txt
new file mode 100644
index 00000000..d8fb2738
--- /dev/null
+++ b/games/repair/LICENSE.txt
@@ -0,0 +1,20 @@
+
+This game sources are licensed under an unmodified zlib/libpng license,
+which is an OSI-certified, BSD-like license:
+
+Copyright (c) 2020 Ramon Santamaria (@raysan5)
+
+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. \ No newline at end of file
diff --git a/games/repair/Makefile b/games/repair/Makefile
new file mode 100644
index 00000000..2b7065e3
--- /dev/null
+++ b/games/repair/Makefile
@@ -0,0 +1,406 @@
+#**************************************************************************************************
+#
+# raylib makefile for Desktop platforms, Raspberry Pi, Android and HTML5
+#
+# Copyright (c) 2013-2020 Ramon Santamaria (@raysan5)
+#
+# 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.
+#
+#**************************************************************************************************
+
+.PHONY: all clean
+
+# Define required raylib variables
+PROJECT_NAME ?= repair
+RAYLIB_VERSION ?= 3.0.0
+RAYLIB_API_VERSION ?= 3
+RAYLIB_PATH ?= C:\GitHub\raylib
+
+# Define default options
+
+# One of PLATFORM_DESKTOP, PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
+PLATFORM ?= PLATFORM_DESKTOP
+
+# Locations of your newly installed library and associated headers. See ../src/Makefile
+# On Linux, if you have installed raylib but cannot compile the examples, check that
+# the *_INSTALL_PATH values here are the same as those in src/Makefile or point to known locations.
+# To enable system-wide compile-time and runtime linking to libraylib.so, run ../src/$ sudo make install RAYLIB_LIBTYPE_SHARED.
+# To enable compile-time linking to a special version of libraylib.so, change these variables here.
+# To enable runtime linking to a special version of libraylib.so, see EXAMPLE_RUNTIME_PATH below.
+# If there is a libraylib in both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH, at runtime,
+# the library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over the one at RAYLIB_INSTALL_PATH.
+# RAYLIB_INSTALL_PATH should be the desired full path to libraylib. No relative paths.
+DESTDIR ?= /usr/local
+RAYLIB_INSTALL_PATH ?= $(DESTDIR)/lib
+# RAYLIB_H_INSTALL_PATH locates the installed raylib header and associated source files.
+RAYLIB_H_INSTALL_PATH ?= $(DESTDIR)/include
+
+# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll)
+RAYLIB_LIBTYPE ?= STATIC
+
+# Build mode for project: DEBUG or RELEASE
+BUILD_MODE ?= RELEASE
+
+# Use external GLFW library instead of rglfw module
+# TODO: Review usage on Linux. Target version of choice. Switch on -lglfw or -lglfw3
+USE_EXTERNAL_GLFW ?= FALSE
+
+# Use Wayland display server protocol on Linux desktop
+# by default it uses X11 windowing system
+USE_WAYLAND_DISPLAY ?= FALSE
+
+# Determine PLATFORM_OS in case PLATFORM_DESKTOP selected
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ # No uname.exe on MinGW!, but OS=Windows_NT on Windows!
+ # ifeq ($(UNAME),Msys) -> Windows
+ ifeq ($(OS),Windows_NT)
+ PLATFORM_OS=WINDOWS
+ else
+ UNAMEOS=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ endif
+ ifeq ($(UNAMEOS),FreeBSD)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),OpenBSD)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),NetBSD)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),DragonFly)
+ PLATFORM_OS=BSD
+ endif
+ ifeq ($(UNAMEOS),Darwin)
+ PLATFORM_OS=OSX
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ UNAMEOS=$(shell uname)
+ ifeq ($(UNAMEOS),Linux)
+ PLATFORM_OS=LINUX
+ endif
+endif
+
+# RAYLIB_PATH adjustment for different platforms.
+# If using GNU make, we can get the full path to the top of the tree. Windows? BSD?
+# Required for ldconfig or other tools that do not perform path expansion.
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ RAYLIB_PREFIX ?= ..
+ RAYLIB_PATH = $(realpath $(RAYLIB_PREFIX))
+ endif
+endif
+# Default path for raylib on Raspberry Pi, if installed in different path, update it!
+# This is not currently used by src/Makefile. Not sure of its origin or usage. Refer to wiki.
+# TODO: update install: target in src/Makefile for RPI, consider relation to LINUX.
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ RAYLIB_PATH ?= /home/pi/raylib
+endif
+
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # Emscripten required variables
+ EMSDK_PATH ?= C:/emsdk
+ EMSCRIPTEN_PATH ?= $(EMSDK_PATH)/fastcomp/emscripten
+ CLANG_PATH = $(EMSDK_PATH)/fastcomp/bin
+ PYTHON_PATH = $(EMSDK_PATH)/python/2.7.13.1_64bit/python-2.7.13.amd64
+ NODE_PATH = $(EMSDK_PATH)/node/12.9.1_64bit/bin
+ export PATH = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH);C:\raylib\MinGW\bin:$$(PATH)
+endif
+
+# Define raylib release directory for compiled library.
+# RAYLIB_RELEASE_PATH points to provided binaries or your freshly built version
+RAYLIB_RELEASE_PATH ?= $(RAYLIB_PATH)/src
+
+# EXAMPLE_RUNTIME_PATH embeds a custom runtime location of libraylib.so or other desired libraries
+# into each example binary compiled with RAYLIB_LIBTYPE=SHARED. It defaults to RAYLIB_RELEASE_PATH
+# so that these examples link at runtime with your version of libraylib.so in ../release/libs/linux
+# without formal installation from ../src/Makefile. It aids portability and is useful if you have
+# multiple versions of raylib, have raylib installed to a non-standard location, or want to
+# bundle libraylib.so with your game. Change it to your liking.
+# NOTE: If, at runtime, there is a libraylib.so at both EXAMPLE_RUNTIME_PATH and RAYLIB_INSTALL_PATH,
+# The library at EXAMPLE_RUNTIME_PATH, if present, will take precedence over RAYLIB_INSTALL_PATH,
+# Implemented for LINUX below with CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
+# To see the result, run readelf -d core/core_basic_window; looking at the RPATH or RUNPATH attribute.
+# To see which libraries a built example is linking to, ldd core/core_basic_window;
+# Look for libraylib.so.1 => $(RAYLIB_INSTALL_PATH)/libraylib.so.1 or similar listing.
+EXAMPLE_RUNTIME_PATH ?= $(RAYLIB_RELEASE_PATH)
+
+# Define default C compiler: gcc
+# NOTE: define g++ compiler if using C++
+CC = gcc
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),OSX)
+ # OSX default compiler
+ CC = clang
+ endif
+ ifeq ($(PLATFORM_OS),BSD)
+ # FreeBSD, OpenBSD, NetBSD, DragonFly default compiler
+ CC = clang
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ ifeq ($(USE_RPI_CROSS_COMPILER),TRUE)
+ # Define RPI cross-compiler
+ #CC = armv6j-hardfloat-linux-gnueabi-gcc
+ CC = $(RPI_TOOLCHAIN)/bin/arm-linux-gnueabihf-gcc
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # HTML5 emscripten compiler
+ # WARNING: To compile to HTML5, code must be redesigned
+ # to use emscripten.h and emscripten_set_main_loop()
+ CC = emcc
+endif
+
+# Define default make program: Mingw32-make
+MAKE = mingw32-make
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),LINUX)
+ MAKE = make
+ endif
+endif
+
+# Define compiler flags:
+# -O1 defines optimization level
+# -g include debug information on compilation
+# -s strip unnecessary data from build
+# -Wall turns on most, but not all, compiler warnings
+# -std=c99 defines C language mode (standard C from 1999 revision)
+# -std=gnu99 defines C language mode (GNU C from 1999 revision)
+# -Wno-missing-braces ignore invalid warning (GCC bug 53119)
+# -D_DEFAULT_SOURCE use with -std=c99 on Linux and PLATFORM_WEB, required for timespec
+CFLAGS += -Wall -std=c99 -D_DEFAULT_SOURCE -Wno-missing-braces
+
+ifeq ($(BUILD_MODE),DEBUG)
+ CFLAGS += -g
+ ifeq ($(PLATFORM),PLATFORM_WEB)
+ CFLAGS += -s ASSERTIONS=1 --profiling
+ endif
+else
+ ifeq ($(PLATFORM),PLATFORM_WEB)
+ CFLAGS += -Os
+ else
+ CFLAGS += -s -O1
+ endif
+endif
+
+# Additional flags for compiler (if desired)
+#CFLAGS += -Wextra -Wmissing-prototypes -Wstrict-prototypes
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),WINDOWS)
+ # resource file contains windows executable icon and properties
+ # -Wl,--subsystem,windows hides the console window
+ CFLAGS += $(RAYLIB_PATH)/src/raylib.rc.data
+ ifeq ($(BUILD_MODE), RELEASE)
+ CFLAGS += -Wl,--subsystem,windows
+ endif
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ ifeq ($(RAYLIB_LIBTYPE),STATIC)
+ CFLAGS += -D_DEFAULT_SOURCE
+ endif
+ ifeq ($(RAYLIB_LIBTYPE),SHARED)
+ # Explicitly enable runtime link to libraylib.so
+ CFLAGS += -Wl,-rpath,$(EXAMPLE_RUNTIME_PATH)
+ endif
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ CFLAGS += -std=gnu99
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # -Os # size optimization
+ # -O2 # optimization level 2, if used, also set --memory-init-file 0
+ # -s USE_GLFW=3 # Use glfw3 library (context/input management)
+ # -s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing -> WARNING: Audio buffers could FAIL!
+ # -s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB)
+ # -s USE_PTHREADS=1 # multithreading support
+ # -s WASM=0 # disable Web Assembly, emitted by default
+ # -s EMTERPRETIFY=1 # enable emscripten code interpreter (very slow)
+ # -s EMTERPRETIFY_ASYNC=1 # support synchronous loops by emterpreter
+ # -s FORCE_FILESYSTEM=1 # force filesystem to load/save files data
+ # -s ASSERTIONS=1 # enable runtime checks for common memory allocation errors (-O1 and above turn it off)
+ # --profiling # include information for code profiling
+ # --memory-init-file 0 # to avoid an external memory initialization code file (.mem)
+ # --preload-file resources # specify a resources folder for data compilation
+ CFLAGS += -s USE_GLFW=3 -s TOTAL_MEMORY=67108864 --preload-file resources
+
+ # Define a custom shell .html and output extension
+ CFLAGS += --shell-file $(RAYLIB_PATH)/src/shell.html
+ EXT = .html
+endif
+
+# Define include paths for required headers
+# NOTE: Several external required libraries (stb and others)
+INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external
+
+# Define additional directories containing required header files
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # RPI required libraries
+ INCLUDE_PATHS += -I/opt/vc/include
+ INCLUDE_PATHS += -I/opt/vc/include/interface/vmcs_host/linux
+ INCLUDE_PATHS += -I/opt/vc/include/interface/vcos/pthreads
+endif
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),BSD)
+ # Consider -L$(RAYLIB_H_INSTALL_PATH)
+ INCLUDE_PATHS += -I/usr/local/include
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ # Reset everything.
+ # Precedence: immediately local, installed version, raysan5 provided libs -I$(RAYLIB_H_INSTALL_PATH) -I$(RAYLIB_PATH)/release/include
+ INCLUDE_PATHS = -I$(RAYLIB_H_INSTALL_PATH) -isystem. -isystem$(RAYLIB_PATH)/src -isystem$(RAYLIB_PATH)/release/include -isystem$(RAYLIB_PATH)/src/external
+ endif
+endif
+
+# Define library paths containing required libs.
+LDFLAGS = -L. -L$(RAYLIB_RELEASE_PATH) -L$(RAYLIB_PATH)/src
+
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),BSD)
+ # Consider -L$(RAYLIB_INSTALL_PATH)
+ LDFLAGS += -L. -Lsrc -L/usr/local/lib
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ # Reset everything.
+ # Precedence: immediately local, installed version, raysan5 provided libs
+ LDFLAGS = -L. -L$(RAYLIB_INSTALL_PATH) -L$(RAYLIB_RELEASE_PATH)
+ endif
+endif
+
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ LDFLAGS += -L/opt/vc/lib
+endif
+
+# Define any libraries required on linking
+# if you want to link libraries (libname.so or libname.a), use the -lname
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),WINDOWS)
+ # Libraries for Windows desktop compilation
+ # NOTE: WinMM library required to set high-res timer resolution
+ LDLIBS = -lraylib -lopengl32 -lgdi32 -lwinmm
+ # Required for physac examples
+ LDLIBS += -static -lpthread
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ # Libraries for Debian GNU/Linux desktop compiling
+ # NOTE: Required packages: libegl1-mesa-dev
+ LDLIBS = -lraylib -lGL -lm -lpthread -ldl -lrt
+
+ # On X11 requires also below libraries
+ LDLIBS += -lX11
+ # NOTE: It seems additional libraries are not required any more, latest GLFW just dlopen them
+ #LDLIBS += -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+
+ # On Wayland windowing system, additional libraries requires
+ ifeq ($(USE_WAYLAND_DISPLAY),TRUE)
+ LDLIBS += -lwayland-client -lwayland-cursor -lwayland-egl -lxkbcommon
+ endif
+ # Explicit link to libc
+ ifeq ($(RAYLIB_LIBTYPE),SHARED)
+ LDLIBS += -lc
+ endif
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ # Libraries for OSX 10.9 desktop compiling
+ # NOTE: Required packages: libopenal-dev libegl1-mesa-dev
+ LDLIBS = -lraylib -framework OpenGL -framework Cocoa -framework IOKit -framework CoreAudio -framework CoreVideo
+ endif
+ ifeq ($(PLATFORM_OS),BSD)
+ # Libraries for FreeBSD, OpenBSD, NetBSD, DragonFly desktop compiling
+ # NOTE: Required packages: mesa-libs
+ LDLIBS = -lraylib -lGL -lpthread -lm
+
+ # On XWindow requires also below libraries
+ LDLIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
+ endif
+ ifeq ($(USE_EXTERNAL_GLFW),TRUE)
+ # NOTE: It could require additional packages installed: libglfw3-dev
+ LDLIBS += -lglfw
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ # Libraries for Raspberry Pi compiling
+ # NOTE: Required packages: libasound2-dev (ALSA)
+ LDLIBS = -lraylib -lbrcmGLESv2 -lbrcmEGL -lpthread -lrt -lm -lbcm_host -ldl
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ # Libraries for web (HTML5) compiling
+ LDLIBS = $(RAYLIB_RELEASE_PATH)/libraylib.bc
+endif
+
+# Define all source files required
+PROJECT_SOURCE_FILES ?= \
+ repair.c \
+ screens/screen_logo.c \
+ screens/screen_title.c \
+ screens/screen_gameplay.c \
+ screens/screen_ending.c
+
+# Define all object files from source files
+OBJS = $(patsubst %.c, %.o, $(PROJECT_SOURCE_FILES))
+
+# For Android platform we call a custom Makefile.Android
+ifeq ($(PLATFORM),PLATFORM_ANDROID)
+ MAKEFILE_PARAMS = -f Makefile.Android
+ export PROJECT_NAME
+ export PROJECT_SOURCE_FILES
+else
+ MAKEFILE_PARAMS = $(PROJECT_NAME)
+endif
+
+# Default target entry
+# NOTE: We call this Makefile target or Makefile.Android target
+all:
+ $(MAKE) $(MAKEFILE_PARAMS)
+
+# Project target defined by PROJECT_NAME
+$(PROJECT_NAME): $(OBJS)
+ $(CC) -o $(PROJECT_NAME)$(EXT) $(OBJS) $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
+
+# Compile source files
+# NOTE: This pattern will compile every module defined on $(OBJS)
+%.o: %.c
+ $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDE_PATHS) -D$(PLATFORM)
+
+# Clean everything
+clean:
+ifeq ($(PLATFORM),PLATFORM_DESKTOP)
+ ifeq ($(PLATFORM_OS),WINDOWS)
+ del *.o *.exe /s
+ endif
+ ifeq ($(PLATFORM_OS),LINUX)
+ find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable|x-pie-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv
+ endif
+ ifeq ($(PLATFORM_OS),OSX)
+ find . -type f -perm +ugo+x -delete
+ rm -f *.o
+ endif
+endif
+ifeq ($(PLATFORM),PLATFORM_RPI)
+ find . -type f -executable -delete
+ rm -fv *.o
+endif
+ifeq ($(PLATFORM),PLATFORM_WEB)
+ del *.o *.html *.js
+endif
+ @echo Cleaning done
+
diff --git a/games/repair/repair.c b/games/repair/repair.c
new file mode 100644
index 00000000..df541e34
--- /dev/null
+++ b/games/repair/repair.c
@@ -0,0 +1,416 @@
+/*******************************************************************************************
+*
+* raylib - Advance Game template
+*
+* <Game title>
+* <Game description>
+*
+* This game has been created using raylib (www.raylib.com)
+* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+* Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "screens/screens.h" // NOTE: Defines global variable: currentScreen
+
+#if defined(PLATFORM_WEB)
+ #include <emscripten/emscripten.h>
+#endif
+
+GameScreen currentScreen = 0;
+Font font = { 0 };
+Music music = { 0 };
+Sound fxCoin = { 0 };
+Texture2D background = { 0 };
+Texture2D texNPatch = { 0 };
+NPatchInfo npInfo = { 0 };
+
+Texture2D texHead, texHair, texNose, texMouth, texEyes, texComp;
+Texture2D texMakeup = { 0 };
+
+Character playerBase = { 0 };
+Character datingBase = { 0 };
+
+Character player = { 0 };
+Character dating = { 0 };
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+const int screenWidth = 1280;
+const int screenHeight = 720;
+
+// Required variables to manage screen transitions (fade-in, fade-out)
+static float transAlpha = 0.0f;
+static bool onTransition = false;
+static bool transFadeOut = false;
+static int transFromScreen = -1;
+static int transToScreen = -1;
+
+// NOTE: Some global variables that require to be visible for all screens,
+// are defined in screens.h (i.e. currentScreen)
+
+//----------------------------------------------------------------------------------
+// Local Functions Declaration
+//----------------------------------------------------------------------------------
+static void ChangeToScreen(int screen); // No transition effect
+
+static void TransitionToScreen(int screen);
+static void UpdateTransition(void);
+static void DrawTransition(void);
+
+static void UpdateDrawFrame(void); // Update and Draw one frame
+
+//----------------------------------------------------------------------------------
+// Main entry point
+//----------------------------------------------------------------------------------
+int main(void)
+{
+ // Initialization (Note windowTitle is unused on Android)
+ //---------------------------------------------------------
+ InitWindow(screenWidth, screenHeight, "raylib template - advance game");
+
+ // Global data loading (assets that must be available in all screens, i.e. fonts)
+ InitAudioDevice();
+
+ font = LoadFont("resources/font.png");
+ SetTextureFilter(font.texture, FILTER_BILINEAR);
+
+ music = LoadMusicStream("resources/elevator_romance.ogg");
+ fxCoin = LoadSound("resources/coin.wav");
+
+ background = LoadTexture("resources/background.png");
+
+ texNPatch = LoadTexture("resources/npatch.png");
+ npInfo.sourceRec = (Rectangle){ 0, 0, 80, texNPatch.height },
+ npInfo.left = 24;
+ npInfo.top = 24;
+ npInfo.right = 24;
+ npInfo.bottom = 24;
+
+ // Load required textures
+ texHead = LoadTexture("resources/head_models.png");
+ texHair = LoadTexture("resources/hair_models.png");
+ texNose = LoadTexture("resources/nose_models.png");
+ texMouth = LoadTexture("resources/mouth_models.png");
+ texEyes = LoadTexture("resources/eyes_models.png");
+ //texComp = LoadTexture("resources/comp_models.png");
+ texMakeup = LoadTexture("resources/makeup.png");
+
+ SetMusicVolume(music, 0.5f);
+ //PlayMusicStream(music);
+
+ // Setup and Init first screen
+ currentScreen = LOGO;
+ InitLogoScreen();
+
+#if defined(PLATFORM_WEB)
+ emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
+#else
+ SetTargetFPS(60); // Set our game to run at 60 frames-per-second
+ //--------------------------------------------------------------------------------------
+
+ // Main game loop
+ while (!WindowShouldClose()) // Detect window close button or ESC key
+ {
+ UpdateDrawFrame();
+ }
+#endif
+
+ // De-Initialization
+ //--------------------------------------------------------------------------------------
+
+ // Unload current screen data before closing
+ switch (currentScreen)
+ {
+ case LOGO: UnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case GAMEPLAY: UnloadGameplayScreen(); break;
+ case ENDING: UnloadEndingScreen(); break;
+ default: break;
+ }
+
+ // Unload all global loaded data (i.e. fonts) here!
+ UnloadFont(font);
+ UnloadMusicStream(music);
+ UnloadSound(fxCoin);
+ UnloadTexture(background);
+ UnloadTexture(texNPatch);
+
+ UnloadTexture(texHead);
+ UnloadTexture(texHair);
+ UnloadTexture(texNose);
+ UnloadTexture(texMouth);
+ UnloadTexture(texEyes);
+ //UnloadTexture(texComp);
+ UnloadTexture(texMakeup);
+
+ CloseAudioDevice(); // Close audio context
+
+ CloseWindow(); // Close window and OpenGL context
+ //--------------------------------------------------------------------------------------
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------------
+// Public Functions Definition
+//----------------------------------------------------------------------------------
+
+Character GenerateCharacter(void)
+{
+ Character character = { 0 };
+
+ // Generate player character!
+ character.head = GetRandomValue(0, texHead.width/BASE_HEAD_WIDTH - 1);
+ character.colHead = headColors[GetRandomValue(0, 5)];
+ character.hair = GetRandomValue(0, texHair.width/BASE_HAIR_WIDTH - 1);
+ character.colHair = hairColors[GetRandomValue(0, 9)];
+ character.eyes = GetRandomValue(0, texEyes.width/BASE_EYES_WIDTH - 1);
+ character.nose = GetRandomValue(0, texNose.width/BASE_NOSE_WIDTH - 1);
+ character.mouth = GetRandomValue(0, texMouth.width/BASE_MOUTH_WIDTH - 1);
+
+ // NOTE: No character customization at this point
+
+ return character;
+}
+
+void CustomizeCharacter(Character *character)
+{
+ if (GetRandomValue(0, 1)) character->hair = GetRandomValue(0, texHair.width/BASE_HAIR_WIDTH - 1);
+ if (GetRandomValue(0, 1)) character->colHair = hairColors[GetRandomValue(0, 9)];
+ if (GetRandomValue(0, 1)) character->eyes = GetRandomValue(0, texEyes.width/BASE_EYES_WIDTH - 1);
+ if (GetRandomValue(0, 1)) character->nose = GetRandomValue(0, texNose.width/BASE_NOSE_WIDTH - 1);
+ if (GetRandomValue(0, 1)) character->mouth = GetRandomValue(0, texMouth.width/BASE_MOUTH_WIDTH - 1);
+}
+
+void DrawCharacter(Character character, Vector2 position)
+{
+ DrawTextureRec(texHair, (Rectangle){ BASE_HAIR_WIDTH*character.hair, 240, BASE_HAIR_WIDTH, texHair.height - 240 }, (Vector2){ position.x + (250 - BASE_HAIR_WIDTH)/2, position.y + 240 }, GetColor(character.colHair));
+ DrawTextureRec(texHead, (Rectangle){ BASE_HEAD_WIDTH*character.head, 0, BASE_HEAD_WIDTH, texHead.height }, (Vector2){ position.x + (250 - BASE_HEAD_WIDTH)/2, position.y + 60 }, GetColor(character.colHead));
+ DrawTextureRec(texHair, (Rectangle){ BASE_HAIR_WIDTH*character.hair, 0, BASE_HAIR_WIDTH, 240 }, (Vector2){ position.x + (250 - BASE_HAIR_WIDTH)/2, position.y }, GetColor(character.colHair));
+ DrawTextureRec(texEyes, (Rectangle){ BASE_EYES_WIDTH*character.eyes, 0, BASE_EYES_WIDTH, texEyes.height }, (Vector2){ position.x + (250 - BASE_EYES_WIDTH)/2, position.y + 190 }, WHITE);
+ DrawTextureRec(texNose, (Rectangle){ BASE_NOSE_WIDTH*character.nose, 0, BASE_NOSE_WIDTH, texNose.height }, (Vector2){ position.x + (250 - BASE_NOSE_WIDTH)/2, position.y + 275 }, GetColor(character.colHead));
+ DrawTextureRec(texMouth, (Rectangle){ BASE_MOUTH_WIDTH*character.mouth, 0, BASE_MOUTH_WIDTH, texMouth.height }, (Vector2){ position.x + (250 - BASE_MOUTH_WIDTH)/2, position.y + 370 }, GetColor(character.colHead));
+}
+
+// Gui Button
+bool GuiButton(Rectangle bounds, const char *text, int forcedState)
+{
+ static const int textColor[4] = { 0xeff6ffff, 0x78e782ff, 0xb04d5fff, 0xd6d6d6ff };
+
+ int state = (forcedState >= 0)? forcedState : 0; // NORMAL
+ bool pressed = false;
+ Vector2 textSize = MeasureTextEx(font, text, font.baseSize, 1);
+
+ // Update control
+ //--------------------------------------------------------------------
+ if ((state < 3) && (forcedState < 0))
+ {
+ Vector2 mousePoint = GetMousePosition();
+
+ // Check button state
+ if (CheckCollisionPointRec(mousePoint, bounds))
+ {
+ if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = 2; // PRESSED
+ else state = 1; // FOCUSED
+
+ if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
+ {
+ pressed = true;
+ PlaySound(fxCoin);
+ }
+ }
+ }
+
+ npInfo.sourceRec.x = 80*state;
+
+ //--------------------------------------------------------------------
+
+ // Draw control
+ //--------------------------------------------------------------------
+ //DrawRectangleRec(bounds, GREEN);
+ //DrawRectangleLinesEx(bounds, 4, DARKGREEN);
+ DrawTextureNPatch(texNPatch, npInfo, bounds, (Vector2){ 0.0f, 0.0f }, 0.0f, WHITE);
+ DrawTextEx(font, text, (Vector2){ bounds.x + bounds.width/2 - textSize.x/2, bounds.y + bounds.height/2 - textSize.y/2 + 4 }, font.baseSize, 1, GetColor(textColor[state]));
+ //------------------------------------------------------------------
+
+ return pressed;
+}
+
+//----------------------------------------------------------------------------------
+// Module specific Functions Definition
+//----------------------------------------------------------------------------------
+
+// Change to next screen, no transition
+static void ChangeToScreen(int screen)
+{
+ // Unload current screen
+ switch (currentScreen)
+ {
+ case LOGO: UnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case GAMEPLAY: UnloadGameplayScreen(); break;
+ case ENDING: UnloadEndingScreen(); break;
+ default: break;
+ }
+
+ // Init next screen
+ switch (screen)
+ {
+ case LOGO: InitLogoScreen(); break;
+ case TITLE: InitTitleScreen(); break;
+ case GAMEPLAY: InitGameplayScreen(); break;
+ case ENDING: InitEndingScreen(); break;
+ default: break;
+ }
+
+ currentScreen = screen;
+}
+
+// Define transition to next screen
+static void TransitionToScreen(int screen)
+{
+ onTransition = true;
+ transFadeOut = false;
+ transFromScreen = currentScreen;
+ transToScreen = screen;
+ transAlpha = 0.0f;
+}
+
+// Update transition effect
+static void UpdateTransition(void)
+{
+ if (!transFadeOut)
+ {
+ transAlpha += 0.05f;
+
+ // NOTE: Due to float internal representation, condition jumps on 1.0f instead of 1.05f
+ // For that reason we compare against 1.01f, to avoid last frame loading stop
+ if (transAlpha > 1.01f)
+ {
+ transAlpha = 1.0f;
+
+ // Unload current screen
+ switch (transFromScreen)
+ {
+ case LOGO: UnloadLogoScreen(); break;
+ case TITLE: UnloadTitleScreen(); break;
+ case GAMEPLAY: UnloadGameplayScreen(); break;
+ case ENDING: UnloadEndingScreen(); break;
+ default: break;
+ }
+
+ // Load next screen
+ switch (transToScreen)
+ {
+ case LOGO: InitLogoScreen(); break;
+ case TITLE: InitTitleScreen(); break;
+ case GAMEPLAY: InitGameplayScreen(); break;
+ case ENDING: InitEndingScreen(); break;
+ default: break;
+ }
+
+ currentScreen = transToScreen;
+
+ // Activate fade out effect to next loaded screen
+ transFadeOut = true;
+ }
+ }
+ else // Transition fade out logic
+ {
+ transAlpha -= 0.02f;
+
+ if (transAlpha < -0.01f)
+ {
+ transAlpha = 0.0f;
+ transFadeOut = false;
+ onTransition = false;
+ transFromScreen = -1;
+ transToScreen = -1;
+ }
+ }
+}
+
+// Draw transition effect (full-screen rectangle)
+static void DrawTransition(void)
+{
+ DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(BLACK, transAlpha));
+}
+
+// Update and draw game frame
+static void UpdateDrawFrame(void)
+{
+ // Update
+ //----------------------------------------------------------------------------------
+ UpdateMusicStream(music); // NOTE: Music keeps playing between screens
+
+ if (!onTransition)
+ {
+ switch(currentScreen)
+ {
+ case LOGO:
+ {
+ UpdateLogoScreen();
+
+ if (FinishLogoScreen())
+ {
+ TransitionToScreen(TITLE);
+ PlayMusicStream(music);
+ }
+
+ } break;
+ case TITLE:
+ {
+ UpdateTitleScreen();
+
+ if (FinishTitleScreen() == 1) TransitionToScreen(GAMEPLAY);
+ //else if (FinishTitleScreen() == 2) TransitionToScreen(GAMEPLAY);
+
+ } break;
+ case GAMEPLAY:
+ {
+ UpdateGameplayScreen();
+
+ if (FinishGameplayScreen() == 1) TransitionToScreen(ENDING);
+ //else if (FinishGameplayScreen() == 2) TransitionToScreen(TITLE);
+
+ } break;
+ case ENDING:
+ {
+ UpdateEndingScreen();
+
+ if (FinishEndingScreen() == 1) TransitionToScreen(TITLE);
+
+ } break;
+ default: break;
+ }
+ }
+ else UpdateTransition(); // Update transition (fade-in, fade-out)
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ ClearBackground(RAYWHITE);
+
+ switch(currentScreen)
+ {
+ case LOGO: DrawLogoScreen(); break;
+ case TITLE: DrawTitleScreen(); break;
+ case GAMEPLAY: DrawGameplayScreen(); break;
+ case ENDING: DrawEndingScreen(); break;
+ default: break;
+ }
+
+ // Draw full screen rectangle in front of everything
+ if (onTransition) DrawTransition();
+
+ //DrawFPS(10, 10);
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+}
diff --git a/games/repair/resources/background.png b/games/repair/resources/background.png
new file mode 100644
index 00000000..ecd8969f
--- /dev/null
+++ b/games/repair/resources/background.png
Binary files differ
diff --git a/games/repair/resources/coin.wav b/games/repair/resources/coin.wav
new file mode 100644
index 00000000..6684ffc6
--- /dev/null
+++ b/games/repair/resources/coin.wav
Binary files differ
diff --git a/games/repair/resources/elevator_romance.ogg b/games/repair/resources/elevator_romance.ogg
new file mode 100644
index 00000000..0bcb1248
--- /dev/null
+++ b/games/repair/resources/elevator_romance.ogg
Binary files differ
diff --git a/games/repair/resources/eyes_models.png b/games/repair/resources/eyes_models.png
new file mode 100644
index 00000000..cd0eb603
--- /dev/null
+++ b/games/repair/resources/eyes_models.png
Binary files differ
diff --git a/games/repair/resources/font.png b/games/repair/resources/font.png
new file mode 100644
index 00000000..dab37501
--- /dev/null
+++ b/games/repair/resources/font.png
Binary files differ
diff --git a/games/repair/resources/hair_models.png b/games/repair/resources/hair_models.png
new file mode 100644
index 00000000..a7c86ad0
--- /dev/null
+++ b/games/repair/resources/hair_models.png
Binary files differ
diff --git a/games/repair/resources/head_models.png b/games/repair/resources/head_models.png
new file mode 100644
index 00000000..6990db1b
--- /dev/null
+++ b/games/repair/resources/head_models.png
Binary files differ
diff --git a/games/repair/resources/makeup.png b/games/repair/resources/makeup.png
new file mode 100644
index 00000000..0b8f6069
--- /dev/null
+++ b/games/repair/resources/makeup.png
Binary files differ
diff --git a/games/repair/resources/match.png b/games/repair/resources/match.png
new file mode 100644
index 00000000..c1637fda
--- /dev/null
+++ b/games/repair/resources/match.png
Binary files differ
diff --git a/games/repair/resources/mouth_models.png b/games/repair/resources/mouth_models.png
new file mode 100644
index 00000000..88a165a0
--- /dev/null
+++ b/games/repair/resources/mouth_models.png
Binary files differ
diff --git a/games/repair/resources/nose_models.png b/games/repair/resources/nose_models.png
new file mode 100644
index 00000000..7f4782d3
--- /dev/null
+++ b/games/repair/resources/nose_models.png
Binary files differ
diff --git a/games/repair/resources/npatch.png b/games/repair/resources/npatch.png
new file mode 100644
index 00000000..824083ab
--- /dev/null
+++ b/games/repair/resources/npatch.png
Binary files differ
diff --git a/games/repair/resources/qmark.png b/games/repair/resources/qmark.png
new file mode 100644
index 00000000..c782062d
--- /dev/null
+++ b/games/repair/resources/qmark.png
Binary files differ
diff --git a/games/repair/resources/raylib_logo.png b/games/repair/resources/raylib_logo.png
new file mode 100644
index 00000000..99ba5437
--- /dev/null
+++ b/games/repair/resources/raylib_logo.png
Binary files differ
diff --git a/games/repair/resources/title.png b/games/repair/resources/title.png
new file mode 100644
index 00000000..0d9b725a
--- /dev/null
+++ b/games/repair/resources/title.png
Binary files differ
diff --git a/games/repair/screens/screen_ending.c b/games/repair/screens/screen_ending.c
new file mode 100644
index 00000000..728e3d28
--- /dev/null
+++ b/games/repair/screens/screen_ending.c
@@ -0,0 +1,246 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Ending Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+*
+* 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.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+typedef struct {
+ int hair;
+ int colHair;
+ int eyes;
+ int nose;
+ int mouth;
+ //int glasses;
+ //int piercing;
+} CharLikes;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Ending screen global variables
+static int framesCounter = 0;
+static int finishScreen = 0;
+
+static Texture2D texQmark = { 0 };
+static Texture2D texMatch = { 0 };
+
+static int state = 0;
+static int matchValue = 0;
+
+static CharLikes playerLikes = { 0 };
+static CharLikes playerBaseLikes = { 0 };
+
+//----------------------------------------------------------------------------------
+// Ending Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Ending Screen Initialization logic
+void InitEndingScreen(void)
+{
+ framesCounter = 0;
+ finishScreen = 0;
+ state = 0;
+
+ CustomizeCharacter(&dating);
+
+ texQmark = LoadTexture("resources/qmark.png");
+ texMatch = LoadTexture("resources/match.png");
+}
+
+// Ending Screen Update logic
+void UpdateEndingScreen(void)
+{
+ if (state == 0)
+ {
+ framesCounter++;
+
+ if (framesCounter > 200)
+ {
+ state = 1;
+
+ // Check like percentatge for player base (playerBaseLikes)
+ if (playerBase.hair == dating.hair) playerBaseLikes.hair = GetRandomValue(70, 100);
+ else if (playerBase.hair == datingBase.hair) playerBaseLikes.hair = GetRandomValue(0, 30);
+ else playerBaseLikes.hair = GetRandomValue(0, 100);
+
+ if (playerBase.colHair == dating.colHair) playerBaseLikes.colHair = GetRandomValue(70, 100);
+ else if (playerBase.colHair == datingBase.colHair) playerBaseLikes.colHair = GetRandomValue(0, 30);
+ else playerBaseLikes.colHair = GetRandomValue(0, 100);
+
+ if (playerBase.eyes == dating.eyes) playerBaseLikes.eyes = GetRandomValue(70, 100);
+ else if (playerBase.eyes == datingBase.eyes) playerBaseLikes.eyes = GetRandomValue(0, 30);
+ else playerBaseLikes.eyes = GetRandomValue(0, 100);
+
+ if (playerBase.nose == dating.nose) playerBaseLikes.nose = GetRandomValue(70, 100);
+ else if (playerBase.nose == datingBase.nose) playerBaseLikes.nose = GetRandomValue(0, 30);
+ else playerBaseLikes.nose = GetRandomValue(0, 100);
+
+ if (playerBase.mouth == dating.mouth) playerBaseLikes.mouth = GetRandomValue(70, 100);
+ else if (playerBase.mouth == datingBase.mouth) playerBaseLikes.mouth = GetRandomValue(0, 30);
+ else playerBaseLikes.mouth = GetRandomValue(0, 100);
+
+
+ // Check like percentatge for player (playerLikes)
+ if (player.hair == dating.hair) playerLikes.hair = GetRandomValue(70, 100);
+ else if (player.hair == datingBase.hair) playerLikes.hair = GetRandomValue(0, 30);
+ else playerLikes.hair = GetRandomValue(0, 100);
+
+ if (player.colHair == dating.colHair) playerLikes.colHair = GetRandomValue(70, 100);
+ else if (player.colHair == datingBase.colHair) playerLikes.colHair = GetRandomValue(0, 30);
+ else playerLikes.colHair = GetRandomValue(0, 100);
+
+ if (player.eyes == dating.eyes) playerLikes.eyes = GetRandomValue(70, 100);
+ else if (player.eyes == datingBase.eyes) playerLikes.eyes = GetRandomValue(0, 30);
+ else playerLikes.eyes = GetRandomValue(0, 100);
+
+ if (player.nose == dating.nose) playerLikes.nose = GetRandomValue(70, 100);
+ else if (player.nose == datingBase.nose) playerLikes.nose = GetRandomValue(0, 30);
+ else playerLikes.nose = GetRandomValue(0, 100);
+
+ if (player.mouth == dating.mouth) playerLikes.mouth = GetRandomValue(70, 100);
+ else if (player.mouth == datingBase.mouth) playerLikes.mouth = GetRandomValue(0, 30);
+ else playerLikes.mouth = GetRandomValue(0, 100);
+
+ // NOTE: Max possible points to get 5*100 = 500
+ // If getting > 250 player likes! :D
+ matchValue = playerLikes.hair + playerLikes.colHair + playerLikes.eyes + playerLikes.nose + playerLikes.mouth;
+ }
+ }
+ else if (state == 1)
+ {
+ // Levels animation?
+ }
+
+ // Press enter or tap to return to TITLE screen
+ if (IsKeyPressed(KEY_ENTER) || IsGestureDetected(GESTURE_TAP))
+ {
+ finishScreen = 1;
+ PlaySound(fxCoin);
+ }
+}
+
+// Ending Screen Draw logic
+void DrawEndingScreen(void)
+{
+ // Draw background
+ DrawTexture(background, 0, 0, GetColor(0xf6aa60ff));
+
+ DrawCharacter(player, (Vector2){ 180, 40 });
+
+ DrawCharacter(dating, (Vector2){ 820, 40 });
+
+ if (state == 0)
+ {
+ if ((framesCounter/15)%2 == 1) DrawTexture(texQmark, GetScreenWidth()/2 - texQmark.width/2, 180, WHITE);
+ }
+ else if (state == 1)
+ {
+ DrawTextEx(font, TextFormat("MATCH: %i%%", (int)(((float)matchValue/500.0f)*100.0f)), (Vector2){ 420, 40 }, font.baseSize*2, 1, SKYBLUE);
+
+ DrawTextureRec(texMatch, (Rectangle){ 0, (matchValue > 250)? 0 : texMatch.height/2, texMatch.width, texMatch.height/2 }, (Vector2){ GetScreenWidth()/2 - texMatch.width/2, 240 }, WHITE);
+
+ int barsPositionX = 80;
+
+ //DrawRectangle(0, 530, GetScreenWidth(), GetScreenHeight() - 530, Fade(GRAY, 0.6f));
+ //DrawRectangleLines(0, 530, GetScreenWidth(), GetScreenHeight() - 530, Fade(DARKGRAY, 0.8f));
+
+ // Draw like values: player base
+ DrawTextEx(font, "HAIR:", (Vector2){ barsPositionX, 550 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80, 550 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80, 550 + 6, playerBaseLikes.hair*4, font.baseSize/4, RED);
+
+ DrawTextEx(font, "TINT:", (Vector2){ barsPositionX, 580 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80, 580 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80, 580 + 6, playerBaseLikes.colHair*4, font.baseSize/4, RED);
+
+ DrawTextEx(font, "EYES:", (Vector2){ barsPositionX, 610 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80, 610 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80, 610 + 6, playerBaseLikes.eyes*4, font.baseSize/4, RED);
+
+ DrawTextEx(font, "NOSE:", (Vector2){ barsPositionX, 640 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80, 640 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80, 640 + 6, playerBaseLikes.nose*4, font.baseSize/4, RED);
+
+ DrawTextEx(font, "LIPS:", (Vector2){ barsPositionX, 670 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80, 670 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80, 670 + 6, playerBaseLikes.mouth*4, font.baseSize/4, RED);
+
+ // Draw like values: player
+ if (player.hair != playerBase.hair)
+ {
+ DrawTextEx(font, "after re-touch:", (Vector2){ barsPositionX + 80 + 400 + 20, 550 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 550 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 550 + 6, playerLikes.hair*4, font.baseSize/4, RED);
+ }
+
+ if (player.colHair != playerBase.colHair)
+ {
+ DrawTextEx(font, "after re-touch:", (Vector2){ barsPositionX + 80 + 400 + 20, 580 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 580 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 580 + 6, playerLikes.colHair*4, font.baseSize/4, RED);
+ }
+
+ if (player.eyes != playerBase.eyes)
+ {
+ DrawTextEx(font, "after re-touch:", (Vector2){ barsPositionX + 80 + 400 + 20, 610 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 610 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 610 + 6, playerLikes.eyes*4, font.baseSize/4, RED);
+ }
+
+ if (player.nose != playerBase.nose)
+ {
+ DrawTextEx(font, "after re-touch:", (Vector2){ barsPositionX + 80 + 400 + 20, 640 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 640 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 640 + 6, playerLikes.nose*4, font.baseSize/4, RED);
+ }
+
+ if (player.mouth != playerBase.mouth)
+ {
+ DrawTextEx(font, "after re-touch:", (Vector2){ barsPositionX + 80 + 400 + 20, 670 }, font.baseSize/2, 1, WHITE);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 670 + 6, 400, font.baseSize/4, GRAY);
+ DrawRectangle(barsPositionX + 80 + 400 + 100 + 90, 670 + 6, playerLikes.mouth*4, font.baseSize/4, RED);
+ }
+
+ // Draw left button: date!
+ if (GuiButton((Rectangle){ GetScreenWidth() - 280, 60, 260, 80 }, "AGAIN!", -1))
+ {
+ finishScreen = 1;
+ }
+ }
+}
+
+// Ending Screen Unload logic
+void UnloadEndingScreen(void)
+{
+ UnloadTexture(texQmark);
+ UnloadTexture(texMatch);
+}
+
+// Ending Screen should finish?
+int FinishEndingScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/repair/screens/screen_gameplay.c b/games/repair/screens/screen_gameplay.c
new file mode 100644
index 00000000..9d1c4473
--- /dev/null
+++ b/games/repair/screens/screen_gameplay.c
@@ -0,0 +1,169 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Gameplay Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+*
+* 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.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+static bool doHairCut = false;
+static bool doHairTint = false;
+static bool doEyeLiner = false;
+static bool doLipStick = false;
+static bool doNose = false;
+static bool doGlasses = false;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+const unsigned int headColors[6] = { 0xffe29bff, 0xfed5a8ff, 0xad8962ff, 0xfff1b8ff, 0xffd6c4ff, 0xd49c8dff };
+const unsigned int hairColors[10] = { 0xf5bf60ff, 0xaa754aff, 0x974e14ff, 0xf36347ff, 0x87f347ff, 0xfc48d0ff, 0x3b435dff, 0x5f5e60ff, 0xe7e7e7ff, 0xfb386bff };
+
+// Gameplay screen global variables
+static int framesCounter = 0;
+static int finishScreen = 0;
+
+static RenderTexture target = { 0 };
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Gameplay Screen Initialization logic
+void InitGameplayScreen(void)
+{
+ // Initialize GAMEPLAY screen variables
+ framesCounter = 0;
+ finishScreen = 0;
+
+ target = LoadRenderTexture(720, 720);
+ SetTextureFilter(target.texture, FILTER_BILINEAR);
+
+ // Generate player character!
+ //player = GenerateCharacter();
+ playerBase = player;
+
+ // Generate dating character!
+ dating = GenerateCharacter();
+ datingBase = dating;
+
+ // TODO: Generate dating character likes
+ // For the different types of properties we assign random like values: 0% (total-dislike) -> 100% (total-like)
+
+ // The total match point will be the (like accumulated amount)/(num properties)
+ // Some of the elements add points or remove points
+
+ // At the end we can show the like percentadge of every element
+
+ doHairCut = false;
+ doHairTint = false;
+ doEyeLiner = false;
+ doLipStick = false;
+ doNose = false;
+ doGlasses = false;
+}
+
+// Gameplay Screen Update logic
+void UpdateGameplayScreen(void)
+{
+ if (IsKeyPressed(KEY_SPACE))
+ {
+ player = GenerateCharacter();
+ playerBase = player;
+ }
+
+ if (IsKeyPressed(KEY_ENTER)) finishScreen = 1;
+}
+
+// Gameplay Screen Draw logic
+void DrawGameplayScreen(void)
+{
+ // Draw background
+ DrawTexture(background, 0, 0, GetColor(0xf6aa60ff));
+
+ // Draw left menu buttons
+ GuiButton((Rectangle){ 20, 40, 300, 60 }, "RE-TOUCH:", 2);
+
+ if (GuiButton((Rectangle){ 20, 40 + 90, 300, 80 }, "HAIR TINT", doHairTint? 3 : -1))
+ {
+ doHairTint = true;
+ player.colHair = hairColors[GetRandomValue(0, 9)];
+ }
+ if (GuiButton((Rectangle){ 20, 40 + 180, 300, 80 }, "HAIR", doHairCut? 3 : -1))
+ {
+ doHairCut = true;
+ player.hair = GetRandomValue(0, texHair.width/BASE_HAIR_WIDTH);
+
+ }
+ if (GuiButton((Rectangle){ 20, 40 + 270, 300, 80 }, "EYES", doEyeLiner? 3 : -1))
+ {
+ doEyeLiner = true;
+ player.eyes = GetRandomValue(0, texEyes.width/BASE_EYES_WIDTH - 1);
+ }
+ if (GuiButton((Rectangle){ 20, 40 + 360, 300, 80 }, "NOSE", doNose? 3 : -1))
+ {
+ doNose = true;
+ player.nose = GetRandomValue(0, texNose.width/BASE_NOSE_WIDTH - 1);
+ }
+ if (GuiButton((Rectangle){ 20, 40 + 450, 300, 80 }, "LIPS", doLipStick? 3 : -1))
+ {
+ doLipStick = true;
+ player.mouth = GetRandomValue(0, texMouth.width/BASE_MOUTH_WIDTH - 1);
+ }
+ if (GuiButton((Rectangle){ 20, 40 + 540, 300, 80 }, "GLASSES", 3))
+ {
+ doGlasses = true;
+ }
+
+ // Draw player
+ DrawCharacter(player, (Vector2){ GetScreenWidth()/2 - 125, 80 });
+
+ // Draw dating view
+ GuiButton((Rectangle){ 970, 40, 260, 60 }, "DATING:", 2);
+ GuiButton((Rectangle){ 970, 40 + 70, 260, 260 }, " ", 0);
+
+ BeginTextureMode(target);
+ DrawCharacter(dating, (Vector2){ (720 - 250)/2, (720 - 500)/2 });
+ EndTextureMode();
+
+ DrawTexturePro(target.texture, (Rectangle){ 0.0f, 0.0f, (float)target.texture.width, (float)-target.texture.height }, (Rectangle){ 970, 40 + 70, 260, 260 }, (Vector2){ 0, 0 }, 0.0f, WHITE);
+
+ // Draw left button: date!
+ if (GuiButton((Rectangle){ 970, 580, 260, 90 }, "GO DATE!", -1))
+ {
+ finishScreen = 1;
+ }
+}
+
+// Gameplay Screen Unload logic
+void UnloadGameplayScreen(void)
+{
+ // Unload required textures
+}
+
+// Gameplay Screen should finish?
+int FinishGameplayScreen(void)
+{
+ return finishScreen;
+}
diff --git a/games/repair/screens/screen_logo.c b/games/repair/screens/screen_logo.c
new file mode 100644
index 00000000..1d8fa978
--- /dev/null
+++ b/games/repair/screens/screen_logo.c
@@ -0,0 +1,211 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Logo Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014-2019 Ramon Santamaria (@raysan5)
+*
+* 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.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+#define LOGO_RECS_SIDE 16
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Logo screen global variables
+static int framesCounter = 0;
+static int finishScreen = 0;
+
+static int logoPositionX = 0;
+static int logoPositionY = 0;
+
+static int lettersCount = 0;
+
+static int topSideRecWidth = 0;
+static int leftSideRecHeight = 0;
+
+static int bottomSideRecWidth = 0;
+static int rightSideRecHeight = 0;
+
+static char raylib[8] = { 0 }; // raylib text array, max 8 letters
+static int state = 0; // Tracking animation states (State Machine)
+static float alpha = 1.0f; // Useful for fading
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Logo Screen Initialization logic
+void InitLogoScreen(void)
+{
+ // Initialize LOGO screen variables here!
+ finishScreen = 0;
+ framesCounter = 0;
+ lettersCount = 0;
+
+ logoPositionX = GetScreenWidth()/2 - 128;
+ logoPositionY = GetScreenHeight()/2 - 128;
+
+ topSideRecWidth = LOGO_RECS_SIDE;
+ leftSideRecHeight = LOGO_RECS_SIDE;
+ bottomSideRecWidth = LOGO_RECS_SIDE;
+ rightSideRecHeight = LOGO_RECS_SIDE;
+
+ for (int i = 0; i < 8; i++) raylib[i] = '\0';
+
+ state = 0;
+ alpha = 1.0f;
+}
+
+// Logo Screen Update logic
+void UpdateLogoScreen(void)
+{
+ // Update LOGO screen variables here!
+ if (state == 0) // State 0: Small box blinking
+ {
+ framesCounter++;
+
+ if (framesCounter == 80)
+ {
+ state = 1;
+ framesCounter = 0; // Reset counter... will be used later...
+ }
+ }
+ else if (state == 1) // State 1: Top and left bars growing
+ {
+ topSideRecWidth += 8;
+ leftSideRecHeight += 8;
+
+ if (topSideRecWidth == 256) state = 2;
+ }
+ else if (state == 2) // State 2: Bottom and right bars growing
+ {
+ bottomSideRecWidth += 8;
+ rightSideRecHeight += 8;
+
+ if (bottomSideRecWidth == 256) state = 3;
+ }
+ else if (state == 3) // State 3: Letters appearing (one by one)
+ {
+ framesCounter++;
+
+ if (framesCounter/10) // Every 12 frames, one more letter!
+ {
+ lettersCount++;
+ framesCounter = 0;
+ }
+
+ switch (lettersCount)
+ {
+ case 1: raylib[0] = 'r'; break;
+ case 2: raylib[1] = 'a'; break;
+ case 3: raylib[2] = 'y'; break;
+ case 4: raylib[3] = 'l'; break;
+ case 5: raylib[4] = 'i'; break;
+ case 6: raylib[5] = 'b'; break;
+ default: break;
+ }
+
+ // When all letters have appeared...
+ if (lettersCount >= 10)
+ {
+ state = 4;
+ framesCounter = 0;
+ }
+ }
+ else if (state == 4)
+ {
+ framesCounter++;
+
+ if (framesCounter > 100)
+ {
+ alpha -= 0.02f;
+
+ if (alpha <= 0.0f)
+ {
+ alpha = 0.0f;
+ finishScreen = 1;
+ }
+ }
+ }
+}
+
+// Logo Screen Draw logic
+void DrawLogoScreen(void)
+{
+ if (state == 0)
+ {
+ if ((framesCounter/10)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
+ }
+ else if (state == 1)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+ }
+ else if (state == 2)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+
+ DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
+ }
+ else if (state == 3)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
+ }
+ else if (state == 4)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48, 50, Fade(BLACK, alpha));
+
+ if (framesCounter > 20) DrawText("powered by", logoPositionX, logoPositionY - 27, 20, Fade(DARKGRAY, alpha));
+ }
+}
+
+// Logo Screen Unload logic
+void UnloadLogoScreen(void)
+{
+ // Unload LOGO screen variables here!
+}
+
+// Logo Screen should finish?
+int FinishLogoScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/repair/screens/screen_title.c b/games/repair/screens/screen_title.c
new file mode 100644
index 00000000..460d3063
--- /dev/null
+++ b/games/repair/screens/screen_title.c
@@ -0,0 +1,134 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Title Screen Functions Definitions (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+*
+* 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.
+*
+**********************************************************************************************/
+
+#include "raylib.h"
+#include "screens.h"
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition (local to this module)
+//----------------------------------------------------------------------------------
+
+// Title screen global variables
+static int framesCounter = 0;
+static int finishScreen = 0;
+
+static Texture2D texTitle = { 0 };
+static Texture2D texLogo = { 0 };
+
+static int titlePositionY = 0;
+static int titleCounter = 0;
+
+//----------------------------------------------------------------------------------
+// Title Screen Functions Definition
+//----------------------------------------------------------------------------------
+
+// Title Screen Initialization logic
+void InitTitleScreen(void)
+{
+ framesCounter = 0;
+ finishScreen = 0;
+
+ texTitle = LoadTexture("resources/title.png");
+ texLogo = LoadTexture("resources/raylib_logo.png");
+
+ player = GenerateCharacter();
+
+ titlePositionY = -200;
+}
+
+// Title Screen Update logic
+void UpdateTitleScreen(void)
+{
+ framesCounter++;
+
+ if (framesCounter > 5)
+ {
+ int partToChange = GetRandomValue(0, 4);
+
+ if (partToChange == 0)
+ {
+ player.head = GetRandomValue(0, texHead.width/BASE_HEAD_WIDTH - 1);
+ player.colHead = headColors[GetRandomValue(0, 5)];
+ }
+ else if (partToChange == 1) player.eyes = GetRandomValue(0, texEyes.width/BASE_EYES_WIDTH - 1);
+ else if (partToChange == 2) player.nose = GetRandomValue(0, texNose.width/BASE_NOSE_WIDTH - 1);
+ else if (partToChange == 3) player.mouth = GetRandomValue(0, texMouth.width/BASE_MOUTH_WIDTH - 1);
+ else if (partToChange == 4)
+ {
+ player.hair = GetRandomValue(0, texHair.width/BASE_HAIR_WIDTH - 1);
+ player.colHair = hairColors[GetRandomValue(0, 9)];
+ }
+
+ framesCounter = 0;
+ }
+
+ titlePositionY += 3;
+ if (titlePositionY > 40) titlePositionY = 40;
+
+ titleCounter++;
+
+ if (IsKeyPressed(KEY_ENTER)) finishScreen = 1;
+}
+
+// Title Screen Draw logic
+void DrawTitleScreen(void)
+{
+ DrawTexture(background, 0, 0, GetColor(0xf6aa60ff));
+
+ // Draw face, parts keep changing ranomly
+ DrawCharacter(player, (Vector2){ GetScreenWidth()/2 - 125, 80 });
+
+ // Draw face rectangles
+ //DrawRectangleRec((Rectangle){ GetScreenWidth()/2 - BASE_EYES_WIDTH/2, 270, BASE_EYES_WIDTH, texEyes.height }, Fade(GREEN, 0.3f));
+ //DrawRectangleRec((Rectangle){ GetScreenWidth()/2 - BASE_NOSE_WIDTH/2, 355, BASE_NOSE_WIDTH, texNose.height }, Fade(SKYBLUE, 0.3f));
+ //DrawRectangleRec((Rectangle){ GetScreenWidth()/2 - BASE_MOUTH_WIDTH/2, 450, BASE_MOUTH_WIDTH, texMouth.height }, Fade(RED, 0.3f));
+
+ DrawTexture(texTitle, GetScreenWidth()/2 - texTitle.width/2, titlePositionY, WHITE);
+
+ if (titleCounter > 180)
+ {
+ if (GuiButton((Rectangle){ GetScreenWidth()/2 - 440/2, 580, 440, 80 }, "START DATE!", -1))
+ {
+ finishScreen = 1; // GAMEPLAY
+ PlaySound(fxCoin);
+ }
+ }
+
+ DrawText("powered by", 20, GetScreenHeight() - texLogo.height - 35, 10, BLACK);
+ DrawTexture(texLogo, 20, GetScreenHeight() - texLogo.height - 20, WHITE);
+}
+
+// Title Screen Unload logic
+void UnloadTitleScreen(void)
+{
+ UnloadTexture(texTitle);
+ UnloadTexture(texLogo);
+}
+
+// Title Screen should finish?
+int FinishTitleScreen(void)
+{
+ return finishScreen;
+} \ No newline at end of file
diff --git a/games/repair/screens/screens.h b/games/repair/screens/screens.h
new file mode 100644
index 00000000..362a15c9
--- /dev/null
+++ b/games/repair/screens/screens.h
@@ -0,0 +1,134 @@
+/**********************************************************************************************
+*
+* raylib - Advance Game template
+*
+* Screens Functions Declarations (Init, Update, Draw, Unload)
+*
+* Copyright (c) 2014-2020 Ramon Santamaria (@raysan5)
+*
+* 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 SCREENS_H
+#define SCREENS_H
+
+#define BASE_HEAD_WIDTH 400
+#define BASE_HAIR_WIDTH 500
+#define BASE_NOSE_WIDTH 80
+#define BASE_MOUTH_WIDTH 170
+#define BASE_EYES_WIDTH 240
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+typedef enum GameScreen { LOGO = 0, TITLE, OPTIONS, GAMEPLAY, ENDING } GameScreen;
+
+typedef struct {
+ int head;
+ int colHead;
+ int eyes; // Config
+ int nose; // Config
+ int mouth; // Config
+ int hair; // Config
+ int colHair; // Config
+ int glasses; // Config
+ //int piercing;
+ //int freckles;
+} Character;
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+extern const unsigned int headColors[6];
+extern const unsigned int hairColors[10];
+
+extern GameScreen currentScreen;
+extern Font font;
+extern Music music;
+extern Sound fxCoin;
+extern Texture2D background;
+extern Texture2D texNPatch;
+extern NPatchInfo npInfo;
+extern Texture2D texHead, texHair, texNose, texMouth, texEyes, texComp;
+extern Texture2D texMakeup;
+
+extern Character player;
+extern Character playerBase;
+extern Character dating;
+extern Character datingBase;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+// Gui Button
+bool GuiButton(Rectangle rec, const char *text, int forcedState);
+
+Character GenerateCharacter(void);
+void CustomizeCharacter(Character *character);
+void DrawCharacter(Character character, Vector2 position);
+
+//----------------------------------------------------------------------------------
+// Logo Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitLogoScreen(void);
+void UpdateLogoScreen(void);
+void DrawLogoScreen(void);
+void UnloadLogoScreen(void);
+int FinishLogoScreen(void);
+
+//----------------------------------------------------------------------------------
+// Title Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitTitleScreen(void);
+void UpdateTitleScreen(void);
+void DrawTitleScreen(void);
+void UnloadTitleScreen(void);
+int FinishTitleScreen(void);
+
+//----------------------------------------------------------------------------------
+// Options Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitOptionsScreen(void);
+void UpdateOptionsScreen(void);
+void DrawOptionsScreen(void);
+void UnloadOptionsScreen(void);
+int FinishOptionsScreen(void);
+
+//----------------------------------------------------------------------------------
+// Gameplay Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitGameplayScreen(void);
+void UpdateGameplayScreen(void);
+void DrawGameplayScreen(void);
+void UnloadGameplayScreen(void);
+int FinishGameplayScreen(void);
+
+//----------------------------------------------------------------------------------
+// Ending Screen Functions Declaration
+//----------------------------------------------------------------------------------
+void InitEndingScreen(void);
+void UpdateEndingScreen(void);
+void DrawEndingScreen(void);
+void UnloadEndingScreen(void);
+int FinishEndingScreen(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SCREENS_H \ No newline at end of file
diff --git a/src/camera.h b/src/camera.h
index 42ffe12e..d6c15298 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -197,19 +197,31 @@ typedef enum {
MOVE_DOWN
} CameraMove;
+typedef struct {
+ int mode; // Current camera mode
+ float targetDistance; // Camera distance from position to target
+ float playerEyesPosition; // Default player eyes position from ground (in meters)
+ Vector2 angle; // Camera angle in plane XZ
+
+ int moveControl[6];
+ int smoothZoomControl; // raylib: KEY_LEFT_CONTROL
+ int altControl; // raylib: KEY_LEFT_ALT
+ int panControl; // raylib: MOUSE_MIDDLE_BUTTON
+} CameraData;
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-static Vector2 cameraAngle = { 0.0f, 0.0f }; // Camera angle in plane XZ
-static float cameraTargetDistance = 0.0f; // Camera distance from position to target
-static float playerEyesPosition = 1.85f; // Default player eyes position from ground (in meters)
-
-static int cameraMoveControl[6] = { 'W', 'S', 'D', 'A', 'E', 'Q' };
-static int cameraPanControlKey = 2; // raylib: MOUSE_MIDDLE_BUTTON
-static int cameraAltControlKey = 342; // raylib: KEY_LEFT_ALT
-static int cameraSmoothZoomControlKey = 341; // raylib: KEY_LEFT_CONTROL
-
-static int cameraMode = CAMERA_CUSTOM; // Current camera mode
+static CameraData CAMERA = {
+ .mode = 0,
+ .targetDistance = 0,
+ .playerEyesPosition = 1.85f,
+ .angle = { 0 },
+ .moveControl = { 'W', 'S', 'D', 'A', 'E', 'Q' },
+ .smoothZoomControl = 341,
+ .altControl = 342,
+ .panControl = 2
+};
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
@@ -241,19 +253,19 @@ void SetCameraMode(Camera camera, int mode)
float dy = v2.y - v1.y;
float dz = v2.z - v1.z;
- cameraTargetDistance = sqrtf(dx*dx + dy*dy + dz*dz);
+ CAMERA.targetDistance = sqrtf(dx*dx + dy*dy + dz*dz);
// Camera angle calculation
- cameraAngle.x = atan2f(dx, dz); // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
- cameraAngle.y = atan2f(dy, sqrtf(dx*dx + dz*dz)); // Camera angle in plane XY (0 aligned with X, move positive CW)
+ CAMERA.angle.x = atan2f(dx, dz); // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
+ CAMERA.angle.y = atan2f(dy, sqrtf(dx*dx + dz*dz)); // Camera angle in plane XY (0 aligned with X, move positive CW)
- playerEyesPosition = camera.position.y;
+ CAMERA.playerEyesPosition = camera.position.y;
// Lock cursor for first person and third person cameras
if ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)) DisableCursor();
else EnableCursor();
- cameraMode = mode;
+ CAMERA.mode = mode;
}
// Update camera depending on selected mode
@@ -267,7 +279,7 @@ void UpdateCamera(Camera *camera)
static int swingCounter = 0; // Used for 1st person swinging movement
static Vector2 previousMousePosition = { 0.0f, 0.0f };
- // TODO: Compute cameraTargetDistance and cameraAngle here
+ // TODO: Compute CAMERA.targetDistance and CAMERA.angle here
// Mouse movement detection
Vector2 mousePositionDelta = { 0.0f, 0.0f };
@@ -275,20 +287,20 @@ void UpdateCamera(Camera *camera)
int mouseWheelMove = GetMouseWheelMove();
// Keys input detection
- bool panKey = IsMouseButtonDown(cameraPanControlKey);
- bool altKey = IsKeyDown(cameraAltControlKey);
- bool szoomKey = IsKeyDown(cameraSmoothZoomControlKey);
+ bool panKey = IsMouseButtonDown(CAMERA.panControl);
+ bool altKey = IsKeyDown(CAMERA.altControl);
+ bool szoomKey = IsKeyDown(CAMERA.smoothZoomControl);
- bool direction[6] = { IsKeyDown(cameraMoveControl[MOVE_FRONT]),
- IsKeyDown(cameraMoveControl[MOVE_BACK]),
- IsKeyDown(cameraMoveControl[MOVE_RIGHT]),
- IsKeyDown(cameraMoveControl[MOVE_LEFT]),
- IsKeyDown(cameraMoveControl[MOVE_UP]),
- IsKeyDown(cameraMoveControl[MOVE_DOWN]) };
+ bool direction[6] = { IsKeyDown(CAMERA.moveControl[MOVE_FRONT]),
+ IsKeyDown(CAMERA.moveControl[MOVE_BACK]),
+ IsKeyDown(CAMERA.moveControl[MOVE_RIGHT]),
+ IsKeyDown(CAMERA.moveControl[MOVE_LEFT]),
+ IsKeyDown(CAMERA.moveControl[MOVE_UP]),
+ IsKeyDown(CAMERA.moveControl[MOVE_DOWN]) };
// TODO: Consider touch inputs for camera
- if (cameraMode != CAMERA_CUSTOM)
+ if (CAMERA.mode != CAMERA_CUSTOM)
{
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
@@ -297,58 +309,58 @@ void UpdateCamera(Camera *camera)
}
// Support for multiple automatic camera modes
- switch (cameraMode)
+ switch (CAMERA.mode)
{
case CAMERA_FREE:
{
// Camera zoom
- if ((cameraTargetDistance < CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
+ if ((CAMERA.targetDistance < CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
- cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
+ CAMERA.targetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
- if (cameraTargetDistance > CAMERA_FREE_DISTANCE_MAX_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MAX_CLAMP;
+ if (CAMERA.targetDistance > CAMERA_FREE_DISTANCE_MAX_CLAMP) CAMERA.targetDistance = CAMERA_FREE_DISTANCE_MAX_CLAMP;
}
// Camera looking down
- // TODO: Review, weird comparisson of cameraTargetDistance == 120.0f?
- else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
+ // TODO: Review, weird comparisson of CAMERA.targetDistance == 120.0f?
+ else if ((camera->position.y > camera->target.y) && (CAMERA.targetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
- camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
{
- camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
// if (camera->target.y < 0) camera->target.y = -0.001;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (mouseWheelMove > 0))
{
- cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
- if (cameraTargetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP;
+ CAMERA.targetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
+ if (CAMERA.targetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) CAMERA.targetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP;
}
// Camera looking up
- // TODO: Review, weird comparisson of cameraTargetDistance == 120.0f?
- else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
+ // TODO: Review, weird comparisson of CAMERA.targetDistance == 120.0f?
+ else if ((camera->position.y < camera->target.y) && (CAMERA.targetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
- camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
{
- camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
- camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/CAMERA.targetDistance;
// if (camera->target.y > 0) camera->target.y = 0.001;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (mouseWheelMove > 0))
{
- cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
- if (cameraTargetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP;
+ CAMERA.targetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
+ if (CAMERA.targetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) CAMERA.targetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP;
}
// Input keys checks
@@ -359,78 +371,78 @@ void UpdateCamera(Camera *camera)
if (szoomKey)
{
// Camera smooth zoom
- cameraTargetDistance += (mousePositionDelta.y*CAMERA_FREE_SMOOTH_ZOOM_SENSITIVITY);
+ CAMERA.targetDistance += (mousePositionDelta.y*CAMERA_FREE_SMOOTH_ZOOM_SENSITIVITY);
}
else
{
// Camera rotation
- cameraAngle.x += mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY;
- cameraAngle.y += mousePositionDelta.y*-CAMERA_FREE_MOUSE_SENSITIVITY;
+ CAMERA.angle.x += mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY;
+ CAMERA.angle.y += mousePositionDelta.y*-CAMERA_FREE_MOUSE_SENSITIVITY;
// Angle clamp
- if (cameraAngle.y > CAMERA_FREE_MIN_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FREE_MIN_CLAMP*DEG2RAD;
- else if (cameraAngle.y < CAMERA_FREE_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FREE_MAX_CLAMP*DEG2RAD;
+ if (CAMERA.angle.y > CAMERA_FREE_MIN_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_FREE_MIN_CLAMP*DEG2RAD;
+ else if (CAMERA.angle.y < CAMERA_FREE_MAX_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_FREE_MAX_CLAMP*DEG2RAD;
}
}
else
{
// Camera panning
- camera->target.x += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(cameraAngle.x)*sinf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER);
- camera->target.y += ((mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER);
- camera->target.z += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.x)*sinf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER);
+ camera->target.x += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(CAMERA.angle.x)*sinf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
+ camera->target.y += ((mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
+ camera->target.z += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(CAMERA.angle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(CAMERA.angle.x)*sinf(CAMERA.angle.y))*(CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER);
}
}
// Update camera position with changes
- camera->position.x = -sinf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.x;
- camera->position.y = -sinf(cameraAngle.y)*cameraTargetDistance + camera->target.y;
- camera->position.z = -cosf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.z;
+ camera->position.x = -sinf(CAMERA.angle.x)*CAMERA.targetDistance*cosf(CAMERA.angle.y) + camera->target.x;
+ camera->position.y = -sinf(CAMERA.angle.y)*CAMERA.targetDistance + camera->target.y;
+ camera->position.z = -cosf(CAMERA.angle.x)*CAMERA.targetDistance*cosf(CAMERA.angle.y) + camera->target.z;
} break;
case CAMERA_ORBITAL:
{
- cameraAngle.x += CAMERA_ORBITAL_SPEED; // Camera orbit angle
- cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY); // Camera zoom
+ CAMERA.angle.x += CAMERA_ORBITAL_SPEED; // Camera orbit angle
+ CAMERA.targetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY); // Camera zoom
// Camera distance clamp
- if (cameraTargetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP;
+ if (CAMERA.targetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) CAMERA.targetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP;
// Update camera position with changes
- camera->position.x = sinf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.x;
- camera->position.y = ((cameraAngle.y <= 0.0f)? 1 : -1)*sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y;
- camera->position.z = cosf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.z;
+ camera->position.x = sinf(CAMERA.angle.x)*CAMERA.targetDistance*cosf(CAMERA.angle.y) + camera->target.x;
+ camera->position.y = ((CAMERA.angle.y <= 0.0f)? 1 : -1)*sinf(CAMERA.angle.y)*CAMERA.targetDistance*sinf(CAMERA.angle.y) + camera->target.y;
+ camera->position.z = cosf(CAMERA.angle.x)*CAMERA.targetDistance*cosf(CAMERA.angle.y) + camera->target.z;
} break;
case CAMERA_FIRST_PERSON:
{
- camera->position.x += (sinf(cameraAngle.x)*direction[MOVE_BACK] -
- sinf(cameraAngle.x)*direction[MOVE_FRONT] -
- cosf(cameraAngle.x)*direction[MOVE_LEFT] +
- cosf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
+ camera->position.x += (sinf(CAMERA.angle.x)*direction[MOVE_BACK] -
+ sinf(CAMERA.angle.x)*direction[MOVE_FRONT] -
+ cosf(CAMERA.angle.x)*direction[MOVE_LEFT] +
+ cosf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
- camera->position.y += (sinf(cameraAngle.y)*direction[MOVE_FRONT] -
- sinf(cameraAngle.y)*direction[MOVE_BACK] +
+ camera->position.y += (sinf(CAMERA.angle.y)*direction[MOVE_FRONT] -
+ sinf(CAMERA.angle.y)*direction[MOVE_BACK] +
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])/PLAYER_MOVEMENT_SENSITIVITY;
- camera->position.z += (cosf(cameraAngle.x)*direction[MOVE_BACK] -
- cosf(cameraAngle.x)*direction[MOVE_FRONT] +
- sinf(cameraAngle.x)*direction[MOVE_LEFT] -
- sinf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
+ camera->position.z += (cosf(CAMERA.angle.x)*direction[MOVE_BACK] -
+ cosf(CAMERA.angle.x)*direction[MOVE_FRONT] +
+ sinf(CAMERA.angle.x)*direction[MOVE_LEFT] -
+ sinf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
bool isMoving = false; // Required for swinging
for (int i = 0; i < 6; i++) if (direction[i]) { isMoving = true; break; }
// Camera orientation calculation
- cameraAngle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
- cameraAngle.y += (mousePositionDelta.y*-CAMERA_MOUSE_MOVE_SENSITIVITY);
+ CAMERA.angle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
+ CAMERA.angle.y += (mousePositionDelta.y*-CAMERA_MOUSE_MOVE_SENSITIVITY);
// Angle clamp
- if (cameraAngle.y > CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD;
- else if (cameraAngle.y < CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD;
+ if (CAMERA.angle.y > CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD;
+ else if (CAMERA.angle.y < CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD;
// Recalculate camera target considering translation and rotation
- Matrix translation = MatrixTranslate(0, 0, (cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER));
- Matrix rotation = MatrixRotateXYZ((Vector3){ PI*2 - cameraAngle.y, PI*2 - cameraAngle.x, 0 });
+ Matrix translation = MatrixTranslate(0, 0, (CAMERA.targetDistance/CAMERA_FREE_PANNING_DIVIDER));
+ Matrix rotation = MatrixRotateXYZ((Vector3){ PI*2 - CAMERA.angle.y, PI*2 - CAMERA.angle.x, 0 });
Matrix transform = MatrixMultiply(translation, rotation);
camera->target.x = camera->position.x - transform.m12;
@@ -441,7 +453,7 @@ void UpdateCamera(Camera *camera)
// Camera position update
// NOTE: On CAMERA_FIRST_PERSON player Y-movement is limited to player 'eyes position'
- camera->position.y = playerEyesPosition - sinf(swingCounter/CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/CAMERA_FIRST_PERSON_STEP_DIVIDER;
+ camera->position.y = CAMERA.playerEyesPosition - sinf(swingCounter/CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/CAMERA_FIRST_PERSON_STEP_DIVIDER;
camera->up.x = sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER;
camera->up.z = -sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER;
@@ -450,39 +462,39 @@ void UpdateCamera(Camera *camera)
} break;
case CAMERA_THIRD_PERSON:
{
- camera->position.x += (sinf(cameraAngle.x)*direction[MOVE_BACK] -
- sinf(cameraAngle.x)*direction[MOVE_FRONT] -
- cosf(cameraAngle.x)*direction[MOVE_LEFT] +
- cosf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
+ camera->position.x += (sinf(CAMERA.angle.x)*direction[MOVE_BACK] -
+ sinf(CAMERA.angle.x)*direction[MOVE_FRONT] -
+ cosf(CAMERA.angle.x)*direction[MOVE_LEFT] +
+ cosf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
- camera->position.y += (sinf(cameraAngle.y)*direction[MOVE_FRONT] -
- sinf(cameraAngle.y)*direction[MOVE_BACK] +
+ camera->position.y += (sinf(CAMERA.angle.y)*direction[MOVE_FRONT] -
+ sinf(CAMERA.angle.y)*direction[MOVE_BACK] +
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])/PLAYER_MOVEMENT_SENSITIVITY;
- camera->position.z += (cosf(cameraAngle.x)*direction[MOVE_BACK] -
- cosf(cameraAngle.x)*direction[MOVE_FRONT] +
- sinf(cameraAngle.x)*direction[MOVE_LEFT] -
- sinf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
+ camera->position.z += (cosf(CAMERA.angle.x)*direction[MOVE_BACK] -
+ cosf(CAMERA.angle.x)*direction[MOVE_FRONT] +
+ sinf(CAMERA.angle.x)*direction[MOVE_LEFT] -
+ sinf(CAMERA.angle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
// Camera orientation calculation
- cameraAngle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
- cameraAngle.y += (mousePositionDelta.y*-CAMERA_MOUSE_MOVE_SENSITIVITY);
+ CAMERA.angle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
+ CAMERA.angle.y += (mousePositionDelta.y*-CAMERA_MOUSE_MOVE_SENSITIVITY);
// Angle clamp
- if (cameraAngle.y > CAMERA_THIRD_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_THIRD_PERSON_MIN_CLAMP*DEG2RAD;
- else if (cameraAngle.y < CAMERA_THIRD_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_THIRD_PERSON_MAX_CLAMP*DEG2RAD;
+ if (CAMERA.angle.y > CAMERA_THIRD_PERSON_MIN_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_THIRD_PERSON_MIN_CLAMP*DEG2RAD;
+ else if (CAMERA.angle.y < CAMERA_THIRD_PERSON_MAX_CLAMP*DEG2RAD) CAMERA.angle.y = CAMERA_THIRD_PERSON_MAX_CLAMP*DEG2RAD;
// Camera zoom
- cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
+ CAMERA.targetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
// Camera distance clamp
- if (cameraTargetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP;
+ if (CAMERA.targetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) CAMERA.targetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP;
// TODO: It seems camera->position is not correctly updated or some rounding issue makes the camera move straight to camera->target...
- camera->position.x = sinf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.x;
- if (cameraAngle.y <= 0.0f) camera->position.y = sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y;
- else camera->position.y = -sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y;
- camera->position.z = cosf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.z;
+ camera->position.x = sinf(CAMERA.angle.x)*CAMERA.targetDistance*cosf(CAMERA.angle.y) + camera->target.x;
+ if (CAMERA.angle.y <= 0.0f) camera->position.y = sinf(CAMERA.angle.y)*CAMERA.targetDistance*sinf(CAMERA.angle.y) + camera->target.y;
+ else camera->position.y = -sinf(CAMERA.angle.y)*CAMERA.targetDistance*sinf(CAMERA.angle.y) + camera->target.y;
+ camera->position.z = cosf(CAMERA.angle.x)*CAMERA.targetDistance*cosf(CAMERA.angle.y) + camera->target.z;
} break;
default: break;
@@ -490,23 +502,23 @@ void UpdateCamera(Camera *camera)
}
// Set camera pan key to combine with mouse movement (free camera)
-void SetCameraPanControl(int panKey) { cameraPanControlKey = panKey; }
+void SetCameraPanControl(int panKey) { CAMERA.panControl = panKey; }
// Set camera alt key to combine with mouse movement (free camera)
-void SetCameraAltControl(int altKey) { cameraAltControlKey = altKey; }
+void SetCameraAltControl(int altKey) { CAMERA.altControl = altKey; }
// Set camera smooth zoom key to combine with mouse (free camera)
-void SetCameraSmoothZoomControl(int szoomKey) { cameraSmoothZoomControlKey = szoomKey; }
+void SetCameraSmoothZoomControl(int szoomKey) { CAMERA.smoothZoomControl = szoomKey; }
// Set camera move controls (1st person and 3rd person cameras)
void SetCameraMoveControls(int frontKey, int backKey, int rightKey, int leftKey, int upKey, int downKey)
{
- cameraMoveControl[MOVE_FRONT] = frontKey;
- cameraMoveControl[MOVE_BACK] = backKey;
- cameraMoveControl[MOVE_RIGHT] = rightKey;
- cameraMoveControl[MOVE_LEFT] = leftKey;
- cameraMoveControl[MOVE_UP] = upKey;
- cameraMoveControl[MOVE_DOWN] = downKey;
+ CAMERA.moveControl[MOVE_FRONT] = frontKey;
+ CAMERA.moveControl[MOVE_BACK] = backKey;
+ CAMERA.moveControl[MOVE_RIGHT] = rightKey;
+ CAMERA.moveControl[MOVE_LEFT] = leftKey;
+ CAMERA.moveControl[MOVE_UP] = upKey;
+ CAMERA.moveControl[MOVE_DOWN] = downKey;
}
#endif // CAMERA_IMPLEMENTATION
diff --git a/src/config.h b/src/config.h
index 17c82eef..656bcdbf 100644
--- a/src/config.h
+++ b/src/config.h
@@ -25,7 +25,7 @@
*
**********************************************************************************************/
-#define RAYLIB_VERSION "2.6-dev"
+#define RAYLIB_VERSION "3.0"
// Edit to control what features Makefile'd raylib is compiled with
#if defined(RAYLIB_CMAKE)
diff --git a/src/core.c b/src/core.c
index 6ae65853..d6b13c01 100644
--- a/src/core.c
+++ b/src/core.c
@@ -116,7 +116,7 @@
#if !defined(EXTERNAL_CONFIG_FLAGS)
#include "config.h" // Defines module configuration flags
#else
- #define RAYLIB_VERSION "2.6-dev"
+ #define RAYLIB_VERSION "3.0"
#endif
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_C_SOURCE < 199309L
@@ -317,134 +317,132 @@ typedef struct{
} KeyEventFifo;
#endif
-//----------------------------------------------------------------------------------
-// Global Variables Definition
-//----------------------------------------------------------------------------------
-// Window/Graphics variables
-//-----------------------------------------------------------------------------------
+typedef struct { int x; int y; } Point;
+typedef struct { int width; int height; } Size;
+
+#if defined(PLATFORM_UWP)
+extern EGLNativeWindowType handle; // Native window handler for UWP (external, defined in UWP App)
+#endif
+
+typedef struct CoreData {
+ struct {
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
-static GLFWwindow *window; // Native window (graphic device)
+ GLFWwindow *handle; // Native window handle (graphic device)
#endif
#if defined(PLATFORM_RPI)
-static EGL_DISPMANX_WINDOW_T window; // Native window (graphic device)
-#endif
-#if defined(PLATFORM_UWP)
-extern EGLNativeWindowType uwpWindow; // Native window handler for UWP (external, defined in UWP App)
+ // NOTE: RPI4 does not support Dispmanx anymore, system should be redesigned
+ EGL_DISPMANX_WINDOW_T handle; // Native window handle (graphic device)
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
-static EGLDisplay display; // Native display device (physical screen connection)
-static EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
-static EGLContext context; // Graphic context, mode in which drawing can be done
-static EGLConfig config; // Graphic config
-static uint64_t baseTime = 0; // Base time measure for hi-res timer
-static bool windowShouldClose = false; // Flag to set window for closing
-#endif
-
-static const char *windowTitle = NULL; // Window text title...
-static bool windowReady = false; // Check if window has been initialized successfully
-static bool windowMinimized = false; // Check if window has been minimized
-static bool windowResized = false; // Check if window has been resized
-static bool fullscreenMode = false; // Check if fullscreen mode (useful only for PLATFORM_DESKTOP)
-static bool alwaysRun = false; // Keep window update/draw running on minimized
-
-static int windowPositionX, windowPositionY; // Window position on screen (required on fullscreen toggle)
-static int displayWidth, displayHeight; // Display width and height (monitor, device-screen, LCD, ...)
-static int screenWidth, screenHeight; // Screen width and height (used render area)
-static int renderWidth, renderHeight; // Framebuffer width and height (render area, including black bars if required)
-static int currentWidth, currentHeight; // Current render width and height, it could change on BeginTextureMode()
-static int renderOffsetX = 0; // Offset X from render area (must be divided by 2)
-static int renderOffsetY = 0; // Offset Y from render area (must be divided by 2)
-static Matrix screenScaling = { 0 }; // Matrix to scale screen (framebuffer rendering)
-//-----------------------------------------------------------------------------------
+ EGLDisplay device; // Native display device (physical screen connection)
+ EGLSurface surface; // Surface to draw on, framebuffers (connected to context)
+ EGLContext context; // Graphic context, mode in which drawing can be done
+ EGLConfig config; // Graphic config
+#endif
+ unsigned int flags; // Configuration flags (bit based)
+ const char *title; // Window text title const pointer
+ bool ready; // Flag to check if window has been initialized successfully
+ bool minimized; // Flag to check if window has been minimized
+ bool resized; // Flag to check if window has been resized
+ bool fullscreen; // Flag to check if fullscreen mode required
+ bool alwaysRun; // Flag to keep window update/draw running on minimized
+ bool shouldClose; // Flag to set window for closing
+
+ Point position; // Window position on screen (required on fullscreen toggle)
+ Size display; // Display width and height (monitor, device-screen, LCD, ...)
+ Size screen; // Screen width and height (used render area)
+ Size currentFbo; // Current render width and height, it could change on BeginTextureMode()
+ Size render; // Framebuffer width and height (render area, including black bars if required)
+ Point renderOffset; // Offset from render area (must be divided by 2)
+ Matrix screenScale; // Matrix to scale screen (framebuffer rendering)
+
+ char **dropFilesPath; // Store dropped files paths as strings
+ int dropFilesCount; // Count dropped files strings
+ } Window;
#if defined(PLATFORM_ANDROID)
-static struct android_app *androidApp; // Android activity
-static struct android_poll_source *source; // Android events polling source
-static int ident, events; // Android ALooper_pollAll() variables
-static const char *internalDataPath = NULL; // Android internal data path to write data (/data/data/<package>/files)
-
-static bool appEnabled = true; // Used to detec if app is active
-static bool contextRebindRequired = false; // Used to know context rebind required
+ struct {
+ bool appEnabled; // Flag to detect if app is active ** = true
+ struct android_app *app; // Android activity
+ struct android_poll_source *source; // Android events polling source
+ const char *internalDataPath; // Android internal data path to write data (/data/data/<package>/files)
+ bool contextRebindRequired; // Used to know context rebind required
+ } Android;
+#endif
+ struct {
+#if defined(PLATFORM_RPI)
+ InputEventWorker eventWorker[10]; // List of worker threads for every monitored "/dev/input/event<N>"
#endif
+ struct {
+ int exitKey; // Default exit key
+ char currentKeyState[512]; // Registers current frame key state
+ char previousKeyState[512]; // Registers previous frame key state
-// Input system variables
-//-----------------------------------------------------------------------------------
-// Keyboard states
-static char previousKeyState[512] = { 0 }; // Registers previous frame key state
-static char currentKeyState[512] = { 0 }; // Registers current frame key state
-static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
-
-static unsigned int keyPressedQueue[MAX_CHARS_QUEUE] = { 0 }; // Input characters queue
-static int keyPressedQueueCount = 0; // Input characters queue count
-
+ int keyPressedQueue[MAX_CHARS_QUEUE]; // Input characters queue
+ int keyPressedQueueCount; // Input characters queue count
#if defined(PLATFORM_RPI)
-// NOTE: For keyboard we will use the standard input (but reconfigured...)
-static struct termios defaultKeyboardSettings; // Used to store default keyboard settings
-static int defaultKeyboardMode = 0; // Used to store default keyboard mode
+ int defaultMode; // Default keyboard mode
+ struct termios defaultSettings; // Default keyboard settings
+ KeyEventFifo lastKeyPressed; // Buffer for holding keydown events as they arrive (Needed due to multitreading of event workers)
+#endif
+ } Keyboard;
+ struct {
+ Vector2 position; // Mouse position on screen
+ Vector2 offset; // Mouse offset
+ Vector2 scale; // Mouse scaling
+
+ bool cursorHidden; // Track if cursor is hidden
+ bool cursorOnScreen; // Tracks if cursor is inside client area
+#if defined(PLATFORM_WEB)
+ bool cursorLockRequired; // Ask for cursor pointer lock on next click
#endif
-
-// Mouse states
-static Vector2 mousePosition = { 0.0f, 0.0f }; // Mouse position on screen
-static Vector2 mouseScale = { 1.0f, 1.0f }; // Mouse scaling
-static Vector2 mouseOffset = { 0.0f, 0.0f }; // Mouse offset
-static bool cursorHidden = false; // Track if cursor is hidden
-static bool cursorOnScreen = false; // Tracks if cursor is inside client area
-static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen
-
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
-static char previousMouseState[3] = { 0 }; // Registers previous mouse button state
-static char currentMouseState[3] = { 0 }; // Registers current mouse button state
-static int previousMouseWheelY = 0; // Registers previous mouse wheel variation
-static int currentMouseWheelY = 0; // Registers current mouse wheel variation
+ char currentButtonState[3]; // Registers current mouse button state
+ char previousButtonState[3]; // Registers previous mouse button state
+ int currentWheelMove; // Registers current mouse wheel variation
+ int previousWheelMove; // Registers previous mouse wheel variation
#endif
-
#if defined(PLATFORM_RPI)
-static char currentMouseStateEvdev[3] = { 0 }; // Holds the new mouse state for the next polling event to grab (Can't be written directly due to multithreading, app could miss the update)
-static InputEventWorker eventWorkers[10]; // List of worker threads for every monitored "/dev/input/event<N>"
-static KeyEventFifo lastKeyPressedEvdev = { 0 }; // Buffer for holding keydown events as they arrive (Needed due to multitreading of event workers)
-static char currentKeyStateEvdev[512] = { 0 }; // Registers current frame key state from event based driver (Needs to be seperate because the legacy console based method clears keys on every frame)
-#endif
-
-#if defined(PLATFORM_WEB)
-static bool toggleCursorLock = false; // Ask for cursor pointer lock on next click
-#endif
-
-// Gamepads states
-static int lastGamepadButtonPressed = -1; // Register last gamepad button pressed
-static int gamepadAxisCount = 0; // Register number of available gamepad axis
-
+ char currentButtonStateEvdev[3]; // Holds the new mouse state for the next polling event to grab (Can't be written directly due to multithreading, app could miss the update)
+#endif
+ } Mouse;
+ struct {
+ Vector2 position[MAX_TOUCH_POINTS]; // Touch position on screen
+ } Touch;
+ struct {
+ int lastButtonPressed; // Register last gamepad button pressed
+ int axisCount; // Register number of available gamepad axis
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
-static bool gamepadReady[MAX_GAMEPADS] = { false }; // Flag to know if gamepad is ready
-static float gamepadAxisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
-static char previousGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
-static char currentGamepadState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
+ bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready
+ float axisState[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Gamepad axis state
+ char currentState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state
+ char previousState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Previous gamepad buttons state
#endif
-
#if defined(PLATFORM_RPI)
-static int gamepadStream[MAX_GAMEPADS] = { -1 };// Gamepad device file descriptor
-static pthread_t gamepadThreadId; // Gamepad reading thread id
-static char gamepadName[64]; // Gamepad name holder
+ pthread_t threadId; // Gamepad reading thread id
+ int streamId[MAX_GAMEPADS]; // Gamepad device file descriptor
+ char name[64]; // Gamepad name holder
+#endif
+ } Gamepad;
+ } Input;
+ struct {
+ double current; // Current time measure
+ double previous; // Previous time measure
+ double update; // Time measure for frame update
+ double draw; // Time measure for frame draw
+ double frame; // Time measure for one frame
+ double target; // Desired time for one frame, if 0 not applied
+#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
+ unsigned long long base; // Base time measure for hi-res timer
#endif
+ } Time;
+} CoreData;
-//-----------------------------------------------------------------------------------
-
-// Timming system variables
-//-----------------------------------------------------------------------------------
-static double currentTime = 0.0; // Current time measure
-static double previousTime = 0.0; // Previous time measure
-static double updateTime = 0.0; // Time measure for frame update
-static double drawTime = 0.0; // Time measure for frame draw
-static double frameTime = 0.0; // Time measure for one frame
-static double targetTime = 0.0; // Desired time for one frame, if 0 not applied
-//-----------------------------------------------------------------------------------
-
-// Config internal variables
-//-----------------------------------------------------------------------------------
-static unsigned int configFlags = 0; // Configuration flags (bit based)
-
-static char **dropFilesPath; // Store dropped files paths as strings
-static int dropFilesCount = 0; // Count dropped files strings
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+static CoreData CORE = { 0 }; // Global CORE context
static char **dirFilesPath; // Store directory files paths as strings
static int dirFilesCount = 0; // Count directory files strings
@@ -545,7 +543,7 @@ extern int main(int argc, char *argv[]);
void android_main(struct android_app *app)
{
char arg0[] = "raylib"; // NOTE: argv[] are mutable
- androidApp = app;
+ CORE.Android.app = app;
// TODO: Should we maybe report != 0 return codes somewhere?
(void)main(1, (char *[]) { arg0, NULL });
@@ -554,7 +552,7 @@ void android_main(struct android_app *app)
// TODO: Add this to header (if apps really need it)
struct android_app *GetAndroidApp(void)
{
- return androidApp;
+ return CORE.Android.app;
}
#endif
#if defined(PLATFORM_RPI) && !defined(SUPPORT_SSH_KEYBOARD_RPI)
@@ -564,8 +562,8 @@ static void InitTerminal(void)
TraceLog(LOG_INFO, "Reconfigure Terminal ...");
// Save terminal keyboard settings and reconfigure terminal with new settings
struct termios keyboardNewSettings;
- tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings
- keyboardNewSettings = defaultKeyboardSettings;
+ tcgetattr(STDIN_FILENO, &CORE.Input.Keyboard.defaultSettings); // Get current keyboard settings
+ keyboardNewSettings = CORE.Input.Keyboard.defaultSettings;
// New terminal settings for keyboard: turn off buffering (non-canonical mode), echo
// NOTE: ISIG controls if ^C and ^Z generate break signals or not
@@ -577,7 +575,7 @@ static void InitTerminal(void)
tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings);
// Save old keyboard mode to restore it at the end
- if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0)
+ if (ioctl(STDIN_FILENO, KDGKBMODE, &CORE.Input.Keyboard.defaultMode) < 0)
{
// NOTE: It could mean we are using a remote keyboard through ssh or from the desktop
TraceLog(LOG_WARNING, "Could not change keyboard mode (Not a local Terminal)");
@@ -597,10 +595,10 @@ static void RestoreTerminal(void)
TraceLog(LOG_INFO, "Restore Terminal ...");
// Reset to default keyboard settings
- tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings);
+ tcsetattr(STDIN_FILENO, TCSANOW, &CORE.Input.Keyboard.defaultSettings);
// Reconfigure keyboard to default mode
- ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode);
+ ioctl(STDIN_FILENO, KDSKBMODE, CORE.Input.Keyboard.defaultMode);
}
#endif
// Initialize window and OpenGL context
@@ -609,21 +607,26 @@ void InitWindow(int width, int height, const char *title)
{
TraceLog(LOG_INFO, "Initializing raylib %s", RAYLIB_VERSION);
- windowTitle = title;
+ CORE.Window.title = title;
+
+ // Initialize required global values different than 0
+ CORE.Input.Keyboard.exitKey = KEY_ESCAPE;
+ CORE.Input.Mouse.scale = (Vector2){ 1.0f, 1.0f };
+ CORE.Input.Gamepad.lastButtonPressed = -1;
+
#if defined(PLATFORM_ANDROID)
- screenWidth = width;
- screenHeight = height;
- currentWidth = width;
- currentHeight = height;
+ CORE.Window.screen.width = width;
+ CORE.Window.screen.height = height;
+ CORE.Window.currentFbo.width = width;
+ CORE.Window.currentFbo.height = height;
// Input data is android app pointer
- internalDataPath = androidApp->activity->internalDataPath;
+ CORE.Android.internalDataPath = CORE.Android.app->activity->internalDataPath;
// Set desired windows flags before initializing anything
- ANativeActivity_setWindowFlags(androidApp->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
- //ANativeActivity_setWindowFlags(androidApp->activity, AWINDOW_FLAG_FORCE_NOT_FULLSCREEN, AWINDOW_FLAG_FULLSCREEN);
+ ANativeActivity_setWindowFlags(CORE.Android.app->activity, AWINDOW_FLAG_FULLSCREEN, 0); //AWINDOW_FLAG_SCALED, AWINDOW_FLAG_DITHER
- int orientation = AConfiguration_getOrientation(androidApp->config);
+ int orientation = AConfiguration_getOrientation(CORE.Android.app->config);
if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(LOG_INFO, "PORTRAIT window orientation");
else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(LOG_INFO, "LANDSCAPE window orientation");
@@ -631,53 +634,58 @@ void InitWindow(int width, int height, const char *title)
// TODO: Automatic orientation doesn't seem to work
if (width <= height)
{
- AConfiguration_setOrientation(androidApp->config, ACONFIGURATION_ORIENTATION_PORT);
+ AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_PORT);
TraceLog(LOG_WARNING, "Window set to portraid mode");
}
else
{
- AConfiguration_setOrientation(androidApp->config, ACONFIGURATION_ORIENTATION_LAND);
+ AConfiguration_setOrientation(CORE.Android.app->config, ACONFIGURATION_ORIENTATION_LAND);
TraceLog(LOG_WARNING, "Window set to landscape mode");
}
- //AConfiguration_getDensity(androidApp->config);
- //AConfiguration_getKeyboard(androidApp->config);
- //AConfiguration_getScreenSize(androidApp->config);
- //AConfiguration_getScreenLong(androidApp->config);
+ //AConfiguration_getDensity(CORE.Android.app->config);
+ //AConfiguration_getKeyboard(CORE.Android.app->config);
+ //AConfiguration_getScreenSize(CORE.Android.app->config);
+ //AConfiguration_getScreenLong(CORE.Android.app->config);
- androidApp->onAppCmd = AndroidCommandCallback;
- androidApp->onInputEvent = AndroidInputCallback;
+ CORE.Android.app->onAppCmd = AndroidCommandCallback;
+ CORE.Android.app->onInputEvent = AndroidInputCallback;
- InitAssetManager(androidApp->activity->assetManager);
+ InitAssetManager(CORE.Android.app->activity->assetManager);
TraceLog(LOG_INFO, "Android app initialized successfully");
+ // Android ALooper_pollAll() variables
+ int pollResult = 0;
+ int pollEvents = 0;
+
// Wait for window to be initialized (display and context)
- while (!windowReady)
+ while (!CORE.Window.ready)
{
// Process events loop
- while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)
+ while ((pollResult = ALooper_pollAll(0, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0)
{
// Process this event
- if (source != NULL) source->process(androidApp, source);
+ if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source);
// NOTE: Never close window, native activity is controlled by the system!
- //if (androidApp->destroyRequested != 0) windowShouldClose = true;
+ //if (CORE.Android.app->destroyRequested != 0) CORE.Window.shouldClose = true;
}
}
#else
// Init graphics device (display device and OpenGL context)
// NOTE: returns true if window and graphic device has been initialized successfully
- windowReady = InitGraphicsDevice(width, height);
- if (!windowReady) return;
+ CORE.Window.ready = InitGraphicsDevice(width, height);
+ if (!CORE.Window.ready) return;
// Init hi-res timer
InitTimer();
#if defined(SUPPORT_DEFAULT_FONT)
// Load default font
- // NOTE: External function (defined in module: text)
+ // NOTE: External functions (defined in module: text)
LoadFontDefault();
+ SetShapesTexture(GetFontDefault().texture, GetFontDefault().recs[95]);
#endif
#if defined(PLATFORM_DESKTOP) && defined(SUPPORT_HIGH_DPI)
// Set default font texture filter for HighDPI (blurry)
@@ -715,8 +723,8 @@ void InitWindow(int width, int height, const char *title)
emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback);
#endif
- mousePosition.x = (float)screenWidth/2.0f;
- mousePosition.y = (float)screenHeight/2.0f;
+ CORE.Input.Mouse.position.x = (float)CORE.Window.screen.width/2.0f;
+ CORE.Input.Mouse.position.y = (float)CORE.Window.screen.height/2.0f;
#endif // PLATFORM_ANDROID
}
@@ -738,7 +746,7 @@ void CloseWindow(void)
rlglClose(); // De-init rlgl
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
- glfwDestroyWindow(window);
+ glfwDestroyWindow(CORE.Window.handle);
glfwTerminate();
#endif
@@ -748,43 +756,43 @@ void CloseWindow(void)
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
// Close surface, context and display
- if (display != EGL_NO_DISPLAY)
+ if (CORE.Window.device != EGL_NO_DISPLAY)
{
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglMakeCurrent(CORE.Window.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (surface != EGL_NO_SURFACE)
+ if (CORE.Window.surface != EGL_NO_SURFACE)
{
- eglDestroySurface(display, surface);
- surface = EGL_NO_SURFACE;
+ eglDestroySurface(CORE.Window.device, CORE.Window.surface);
+ CORE.Window.surface = EGL_NO_SURFACE;
}
- if (context != EGL_NO_CONTEXT)
+ if (CORE.Window.context != EGL_NO_CONTEXT)
{
- eglDestroyContext(display, context);
- context = EGL_NO_CONTEXT;
+ eglDestroyContext(CORE.Window.device, CORE.Window.context);
+ CORE.Window.context = EGL_NO_CONTEXT;
}
- eglTerminate(display);
- display = EGL_NO_DISPLAY;
+ eglTerminate(CORE.Window.device);
+ CORE.Window.device = EGL_NO_DISPLAY;
}
#endif
#if defined(PLATFORM_RPI)
// Wait for mouse and gamepad threads to finish before closing
// NOTE: Those threads should already have finished at this point
- // because they are controlled by windowShouldClose variable
+ // because they are controlled by CORE.Window.shouldClose variable
- windowShouldClose = true; // Added to force threads to exit when the close window is called
+ CORE.Window.shouldClose = true; // Added to force threads to exit when the close window is called
- for (int i = 0; i < sizeof(eventWorkers)/sizeof(InputEventWorker); ++i)
+ for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{
- if (eventWorkers[i].threadId)
+ if (CORE.Input.eventWorker[i].threadId)
{
- pthread_join(eventWorkers[i].threadId, NULL);
+ pthread_join(CORE.Input.eventWorker[i].threadId, NULL);
}
}
- if (gamepadThreadId) pthread_join(gamepadThreadId, NULL);
+ if (CORE.Input.Gamepad.threadId) pthread_join(CORE.Input.Gamepad.threadId, NULL);
#endif
TraceLog(LOG_INFO, "Window closed successfully");
@@ -793,7 +801,7 @@ void CloseWindow(void)
// Check if window has been initialized successfully
bool IsWindowReady(void)
{
- return windowReady;
+ return CORE.Window.ready;
}
// Check if KEY_ESCAPE pressed or Close icon pressed
@@ -810,18 +818,20 @@ bool WindowShouldClose(void)
#endif
#if defined(PLATFORM_DESKTOP)
- if (windowReady)
+ if (CORE.Window.ready)
{
// While window minimized, stop loop execution
- while (!alwaysRun && windowMinimized) glfwWaitEvents();
+ while (!CORE.Window.alwaysRun && CORE.Window.minimized) glfwWaitEvents();
- return (glfwWindowShouldClose(window));
+ CORE.Window.shouldClose = glfwWindowShouldClose(CORE.Window.handle);
+
+ return CORE.Window.shouldClose;
}
else return true;
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
- if (windowReady) return windowShouldClose;
+ if (CORE.Window.ready) return CORE.Window.shouldClose;
else return true;
#endif
}
@@ -830,7 +840,7 @@ bool WindowShouldClose(void)
bool IsWindowMinimized(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
- return windowMinimized;
+ return CORE.Window.minimized;
#else
return false;
#endif
@@ -840,7 +850,7 @@ bool IsWindowMinimized(void)
bool IsWindowResized(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_UWP)
- return windowResized;
+ return CORE.Window.resized;
#else
return false;
#endif
@@ -850,7 +860,7 @@ bool IsWindowResized(void)
bool IsWindowHidden(void)
{
#if defined(PLATFORM_DESKTOP)
- return (glfwGetWindowAttrib(window, GLFW_VISIBLE) == GL_FALSE);
+ return (glfwGetWindowAttrib(CORE.Window.handle, GLFW_VISIBLE) == GL_FALSE);
#endif
return false;
}
@@ -859,30 +869,30 @@ bool IsWindowHidden(void)
void ToggleFullscreen(void)
{
#if defined(PLATFORM_DESKTOP)
- fullscreenMode = !fullscreenMode; // Toggle fullscreen flag
+ CORE.Window.fullscreen = !CORE.Window.fullscreen; // Toggle fullscreen flag
// NOTE: glfwSetWindowMonitor() doesn't work properly (bugs)
- if (fullscreenMode)
+ if (CORE.Window.fullscreen)
{
// Store previous window position (in case we exit fullscreen)
- glfwGetWindowPos(window, &windowPositionX, &windowPositionY);
+ glfwGetWindowPos(CORE.Window.handle, &CORE.Window.position.x, &CORE.Window.position.y);
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
if (!monitor)
{
TraceLog(LOG_WARNING, "Failed to get monitor");
- glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
+ glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
return;
}
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
- glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, mode->refreshRate);
+ glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, mode->refreshRate);
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
// NOTE: V-Sync can be enabled by graphic driver configuration
- if (configFlags & FLAG_VSYNC_HINT) glfwSwapInterval(1);
+ if (CORE.Window.flags & FLAG_VSYNC_HINT) glfwSwapInterval(1);
}
- else glfwSetWindowMonitor(window, NULL, windowPositionX, windowPositionY, screenWidth, screenHeight, GLFW_DONT_CARE);
+ else glfwSetWindowMonitor(CORE.Window.handle, NULL, CORE.Window.position.x, CORE.Window.position.y, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI)
@@ -905,7 +915,7 @@ void SetWindowIcon(Image image)
// NOTE 1: We only support one image icon
// NOTE 2: The specified image data is copied before this function returns
- glfwSetWindowIcon(window, 1, icon);
+ glfwSetWindowIcon(CORE.Window.handle, 1, icon);
}
else TraceLog(LOG_WARNING, "Window icon image must be in R8G8B8A8 pixel format");
#endif
@@ -914,9 +924,9 @@ void SetWindowIcon(Image image)
// Set title for window (only PLATFORM_DESKTOP)
void SetWindowTitle(const char *title)
{
- windowTitle = title;
+ CORE.Window.title = title;
#if defined(PLATFORM_DESKTOP)
- glfwSetWindowTitle(window, title);
+ glfwSetWindowTitle(CORE.Window.handle, title);
#endif
}
@@ -924,7 +934,7 @@ void SetWindowTitle(const char *title)
void SetWindowPosition(int x, int y)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetWindowPos(window, x, y);
+ glfwSetWindowPos(CORE.Window.handle, x, y);
#endif
}
@@ -940,7 +950,7 @@ void SetWindowMonitor(int monitor)
TraceLog(LOG_INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor]));
const GLFWvidmode *mode = glfwGetVideoMode(monitors[monitor]);
- glfwSetWindowMonitor(window, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate);
+ glfwSetWindowMonitor(CORE.Window.handle, monitors[monitor], 0, 0, mode->width, mode->height, mode->refreshRate);
}
else TraceLog(LOG_WARNING, "Selected monitor not found");
#endif
@@ -951,7 +961,7 @@ void SetWindowMinSize(int width, int height)
{
#if defined(PLATFORM_DESKTOP)
const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
- glfwSetWindowSizeLimits(window, width, height, mode->width, mode->height);
+ glfwSetWindowSizeLimits(CORE.Window.handle, width, height, mode->width, mode->height);
#endif
}
@@ -960,7 +970,7 @@ void SetWindowMinSize(int width, int height)
void SetWindowSize(int width, int height)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetWindowSize(window, width, height);
+ glfwSetWindowSize(CORE.Window.handle, width, height);
#endif
}
@@ -968,7 +978,7 @@ void SetWindowSize(int width, int height)
void UnhideWindow(void)
{
#if defined(PLATFORM_DESKTOP)
- glfwShowWindow(window);
+ glfwShowWindow(CORE.Window.handle);
#endif
}
@@ -976,20 +986,20 @@ void UnhideWindow(void)
void HideWindow(void)
{
#if defined(PLATFORM_DESKTOP)
- glfwHideWindow(window);
+ glfwHideWindow(CORE.Window.handle);
#endif
}
// Get current screen width
int GetScreenWidth(void)
{
- return screenWidth;
+ return CORE.Window.screen.width;
}
// Get current screen height
int GetScreenHeight(void)
{
- return screenHeight;
+ return CORE.Window.screen.height;
}
// Get native window handle
@@ -997,7 +1007,7 @@ void *GetWindowHandle(void)
{
#if defined(PLATFORM_DESKTOP) && defined(_WIN32)
// NOTE: Returned handle is: void *HWND (windows.h)
- return glfwGetWin32Window(window);
+ return glfwGetWin32Window(CORE.Window.handle);
#elif defined(__linux__)
// NOTE: Returned handle is: unsigned long Window (X.h)
// typedef unsigned long XID;
@@ -1100,7 +1110,7 @@ Vector2 GetWindowPosition(void)
int x = 0;
int y = 0;
#if defined(PLATFORM_DESKTOP)
- glfwGetWindowPos(window, &x, &y);
+ glfwGetWindowPos(CORE.Window.handle, &x, &y);
#endif
return (Vector2){ (float)x, (float)y };
}
@@ -1126,7 +1136,7 @@ const char *GetMonitorName(int monitor)
const char *GetClipboardText(void)
{
#if defined(PLATFORM_DESKTOP)
- return glfwGetClipboardString(window);
+ return glfwGetClipboardString(CORE.Window.handle);
#else
return NULL;
#endif
@@ -1136,7 +1146,7 @@ const char *GetClipboardText(void)
void SetClipboardText(const char *text)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetClipboardString(window, text);
+ glfwSetClipboardString(CORE.Window.handle, text);
#endif
}
@@ -1144,68 +1154,68 @@ void SetClipboardText(const char *text)
void ShowCursor(void)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
#if defined(PLATFORM_UWP)
UWPMessage *msg = CreateUWPMessage();
msg->type = UWP_MSG_SHOW_MOUSE;
SendMessageToUWP(msg);
#endif
- cursorHidden = false;
+ CORE.Input.Mouse.cursorHidden = false;
}
// Hides mouse cursor
void HideCursor(void)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+ glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#endif
#if defined(PLATFORM_UWP)
UWPMessage *msg = CreateUWPMessage();
msg->type = UWP_MSG_HIDE_MOUSE;
SendMessageToUWP(msg);
#endif
- cursorHidden = true;
+ CORE.Input.Mouse.cursorHidden = true;
}
// Check if cursor is not visible
bool IsCursorHidden(void)
{
- return cursorHidden;
+ return CORE.Input.Mouse.cursorHidden;
}
// Enables cursor (unlock cursor)
void EnableCursor(void)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
#endif
#if defined(PLATFORM_WEB)
- toggleCursorLock = true;
+ CORE.Input.Mouse.cursorLockRequired = true;
#endif
#if defined(PLATFORM_UWP)
UWPMessage *msg = CreateUWPMessage();
msg->type = UWP_MSG_LOCK_MOUSE;
SendMessageToUWP(msg);
#endif
- cursorHidden = false;
+ CORE.Input.Mouse.cursorHidden = false;
}
// Disables cursor (lock cursor)
void DisableCursor(void)
{
#if defined(PLATFORM_DESKTOP)
- glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ glfwSetInputMode(CORE.Window.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
#endif
#if defined(PLATFORM_WEB)
- toggleCursorLock = true;
+ CORE.Input.Mouse.cursorLockRequired = true;
#endif
#if defined(PLATFORM_UWP)
UWPMessage *msg = CreateUWPMessage();
msg->type = UWP_MSG_UNLOCK_MOUSE;
SendMessageToUWP(msg);
#endif
- cursorHidden = true;
+ CORE.Input.Mouse.cursorHidden = true;
}
// Set background color (framebuffer clear color)
@@ -1218,12 +1228,12 @@ void ClearBackground(Color color)
// Setup canvas (framebuffer) to start drawing
void BeginDrawing(void)
{
- currentTime = GetTime(); // Number of elapsed seconds since InitTimer()
- updateTime = currentTime - previousTime;
- previousTime = currentTime;
+ CORE.Time.current = GetTime(); // Number of elapsed seconds since InitTimer()
+ CORE.Time.update = CORE.Time.current - CORE.Time.previous;
+ CORE.Time.previous = CORE.Time.current;
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
- rlMultMatrixf(MatrixToFloat(screenScaling)); // Apply screen scaling
+ rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); // Apply screen scaling
//rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1
// NOTE: Not required with OpenGL 3.3+
@@ -1235,7 +1245,7 @@ void EndDrawing(void)
#if defined(PLATFORM_RPI) && defined(SUPPORT_MOUSE_CURSOR_RPI)
// On RPI native mode we have no system mouse cursor, so,
// we draw a small rectangle for user reference
- DrawRectangle(mousePosition.x, mousePosition.y, 3, 3, MAROON);
+ DrawRectangle(CORE.Input.Mouse.position.x, CORE.Input.Mouse.position.y, 3, 3, MAROON);
#endif
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
@@ -1253,16 +1263,16 @@ void EndDrawing(void)
{
// Get image data for the current frame (from backbuffer)
// NOTE: This process is very slow... :(
- unsigned char *screenData = rlReadScreenPixels(screenWidth, screenHeight);
- GifWriteFrame(screenData, screenWidth, screenHeight, 10, 8, false);
+ unsigned char *screenData = rlReadScreenPixels(CORE.Window.screen.width, CORE.Window.screen.height);
+ GifWriteFrame(screenData, CORE.Window.screen.width, CORE.Window.screen.height, 10, 8, false);
RL_FREE(screenData); // Free image data
}
if (((gifFramesCounter/15)%2) == 1)
{
- DrawCircle(30, screenHeight - 20, 10, RED);
- DrawText("RECORDING", 50, screenHeight - 25, 10, MAROON);
+ DrawCircle(30, CORE.Window.screen.height - 20, 10, RED);
+ DrawText("RECORDING", 50, CORE.Window.screen.height - 25, 10, MAROON);
}
rlglDraw(); // Draw RECORDING message
@@ -1273,26 +1283,26 @@ void EndDrawing(void)
PollInputEvents(); // Poll user events
// Frame time control system
- currentTime = GetTime();
- drawTime = currentTime - previousTime;
- previousTime = currentTime;
+ CORE.Time.current = GetTime();
+ CORE.Time.draw = CORE.Time.current - CORE.Time.previous;
+ CORE.Time.previous = CORE.Time.current;
- frameTime = updateTime + drawTime;
+ CORE.Time.frame = CORE.Time.update + CORE.Time.draw;
// Wait for some milliseconds...
- if (frameTime < targetTime)
+ if (CORE.Time.frame < CORE.Time.target)
{
- Wait((float)(targetTime - frameTime)*1000.0f);
+ Wait((float)(CORE.Time.target - CORE.Time.frame)*1000.0f);
- currentTime = GetTime();
- double waitTime = currentTime - previousTime;
- previousTime = currentTime;
+ CORE.Time.current = GetTime();
+ double waitTime = CORE.Time.current - CORE.Time.previous;
+ CORE.Time.previous = CORE.Time.current;
- frameTime += waitTime; // Total frame time: update + draw + wait
+ CORE.Time.frame += waitTime; // Total frame time: update + draw + wait
//SetWindowTitle(FormatText("Update: %f, Draw: %f, Req.Wait: %f, Real.Wait: %f, Total: %f, Target: %f\n",
- // (float)updateTime, (float)drawTime, (float)(targetTime - (updateTime + drawTime)),
- // (float)waitTime, (float)frameTime, (float)targetTime));
+ // (float)CORE.Time.update, (float)CORE.Time.draw, (float)(CORE.Time.target - (CORE.Time.update + CORE.Time.draw)),
+ // (float)waitTime, (float)CORE.Time.frame, (float)CORE.Time.target));
}
}
@@ -1307,7 +1317,7 @@ void BeginMode2D(Camera2D camera)
rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera)));
// Apply screen scaling if required
- rlMultMatrixf(MatrixToFloat(screenScaling));
+ rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale));
}
// Ends 2D mode with custom camera
@@ -1316,7 +1326,7 @@ void EndMode2D(void)
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
- rlMultMatrixf(MatrixToFloat(screenScaling)); // Apply screen scaling if required
+ rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); // Apply screen scaling if required
}
// Initializes 3D mode with custom camera (3D)
@@ -1328,7 +1338,7 @@ void BeginMode3D(Camera3D camera)
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
rlLoadIdentity(); // Reset current matrix (PROJECTION)
- float aspect = (float)currentWidth/(float)currentHeight;
+ float aspect = (float)CORE.Window.currentFbo.width/(float)CORE.Window.currentFbo.height;
if (camera.type == CAMERA_PERSPECTIVE)
{
@@ -1370,7 +1380,7 @@ void EndMode3D(void)
rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
- rlMultMatrixf(MatrixToFloat(screenScaling)); // Apply screen scaling if required
+ rlMultMatrixf(MatrixToFloat(CORE.Window.screenScale)); // Apply screen scaling if required
rlDisableDepthTest(); // Disable DEPTH_TEST for 2D
}
@@ -1399,8 +1409,8 @@ void BeginTextureMode(RenderTexture2D target)
// Setup current width/height for proper aspect ratio
// calculation when using BeginMode3D()
- currentWidth = target.texture.width;
- currentHeight = target.texture.height;
+ CORE.Window.currentFbo.width = target.texture.width;
+ CORE.Window.currentFbo.height = target.texture.height;
}
// Ends drawing to render texture
@@ -1411,11 +1421,11 @@ void EndTextureMode(void)
rlDisableRenderTexture(); // Disable render target
// Set viewport to default framebuffer size
- SetupViewport(renderWidth, renderHeight);
+ SetupViewport(CORE.Window.render.width, CORE.Window.render.height);
// Reset current screen size
- currentWidth = GetScreenWidth();
- currentHeight = GetScreenHeight();
+ CORE.Window.currentFbo.width = GetScreenWidth();
+ CORE.Window.currentFbo.height = GetScreenHeight();
}
// Begin scissor mode (define screen area for following drawing)
@@ -1436,14 +1446,14 @@ void EndScissorMode(void)
}
// Returns a ray trace from mouse position
-Ray GetMouseRay(Vector2 mousePosition, Camera camera)
+Ray GetMouseRay(Vector2 mouse, Camera camera)
{
Ray ray;
// Calculate normalized device coordinates
// NOTE: y value is negative
- float x = (2.0f*mousePosition.x)/(float)GetScreenWidth() - 1.0f;
- float y = 1.0f - (2.0f*mousePosition.y)/(float)GetScreenHeight();
+ float x = (2.0f*mouse.x)/(float)GetScreenWidth() - 1.0f;
+ float y = 1.0f - (2.0f*mouse.y)/(float)GetScreenHeight();
float z = 1.0f;
// Store values in a vector
@@ -1461,7 +1471,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
}
else if (camera.type == CAMERA_ORTHOGRAPHIC)
{
- float aspect = (float)screenWidth/(float)screenHeight;
+ float aspect = (float)CORE.Window.screen.width/(float)CORE.Window.screen.height;
double top = camera.fovy/2.0;
double right = top*aspect;
@@ -1535,43 +1545,43 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera)
// Returns size position for a 3d world space position (useful for texture drawing)
Vector2 GetWorldToScreenEx(Vector3 position, Camera camera, int width, int height)
{
- // Calculate projection matrix (from perspective instead of frustum
- Matrix matProj = MatrixIdentity();
+ // Calculate projection matrix (from perspective instead of frustum
+ Matrix matProj = MatrixIdentity();
- if (camera.type == CAMERA_PERSPECTIVE)
- {
- // Calculate projection matrix from perspective
+ if (camera.type == CAMERA_PERSPECTIVE)
+ {
+ // Calculate projection matrix from perspective
matProj = MatrixPerspective(camera.fovy * DEG2RAD, ((double)width/(double)height), DEFAULT_NEAR_CULL_DISTANCE, DEFAULT_FAR_CULL_DISTANCE);
- }
- else if (camera.type == CAMERA_ORTHOGRAPHIC)
- {
- float aspect = (float)width/(float)height;
- double top = camera.fovy/2.0;
- double right = top*aspect;
-
- // Calculate projection matrix from orthographic
+ }
+ else if (camera.type == CAMERA_ORTHOGRAPHIC)
+ {
+ float aspect = (float)CORE.Window.screen.width/(float)CORE.Window.screen.height;
+ double top = camera.fovy/2.0;
+ double right = top*aspect;
+
+ // Calculate projection matrix from orthographic
matProj = MatrixOrtho(-right, right, -top, top, DEFAULT_NEAR_CULL_DISTANCE, DEFAULT_FAR_CULL_DISTANCE);
- }
+ }
- // Calculate view matrix from camera look at (and transpose it)
- Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
+ // Calculate view matrix from camera look at (and transpose it)
+ Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
- // Convert world position vector to quaternion
- Quaternion worldPos = { position.x, position.y, position.z, 1.0f };
+ // Convert world position vector to quaternion
+ Quaternion worldPos = { position.x, position.y, position.z, 1.0f };
- // Transform world position to view
- worldPos = QuaternionTransform(worldPos, matView);
+ // Transform world position to view
+ worldPos = QuaternionTransform(worldPos, matView);
- // Transform result to projection (clip space position)
- worldPos = QuaternionTransform(worldPos, matProj);
+ // Transform result to projection (clip space position)
+ worldPos = QuaternionTransform(worldPos, matProj);
- // Calculate normalized device coordinates (inverted y)
- Vector3 ndcPos = { worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.w };
+ // Calculate normalized device coordinates (inverted y)
+ Vector3 ndcPos = { worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.w };
- // Calculate 2d screen position vector
- Vector2 sizePosition = { (ndcPos.x + 1.0f)/2.0f*(float)width, (ndcPos.y + 1.0f)/2.0f*(float)height };
+ // Calculate 2d screen position vector
+ Vector2 screenPosition = { (ndcPos.x + 1.0f)/2.0f*(float)width, (ndcPos.y + 1.0f)/2.0f*(float)height };
- return sizePosition;
+ return screenPosition;
}
// Returns the screen space position for a 2d camera world space position
@@ -1595,10 +1605,10 @@ Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera)
// Set target FPS (maximum)
void SetTargetFPS(int fps)
{
- if (fps < 1) targetTime = 0.0;
- else targetTime = 1.0/(double)fps;
+ if (fps < 1) CORE.Time.target = 0.0;
+ else CORE.Time.target = 1.0/(double)fps;
- TraceLog(LOG_INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000);
+ TraceLog(LOG_INFO, "Target time per frame: %02.03f milliseconds", (float)CORE.Time.target*1000);
}
// Returns current FPS
@@ -1610,7 +1620,7 @@ int GetFPS(void)
// Returns time in seconds for last frame drawn
float GetFrameTime(void)
{
- return (float)frameTime;
+ return (float)CORE.Time.frame;
}
// Get elapsed time measure in seconds since InitTimer()
@@ -1627,12 +1637,12 @@ double GetTime(void)
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
- return (double)(time - baseTime)*1e-9; // Elapsed time since InitTimer()
+ return (double)(time - CORE.Time.base)*1e-9; // Elapsed time since InitTimer()
#endif
#if defined(PLATFORM_UWP)
// Updated through messages
- return currentTime;
+ return CORE.Time.current;
#endif
}
@@ -1793,10 +1803,10 @@ Color Fade(Color color, float alpha)
// Setup window configuration flags (view FLAGS)
void SetConfigFlags(unsigned int flags)
{
- configFlags = flags;
+ CORE.Window.flags = flags;
- if (configFlags & FLAG_FULLSCREEN_MODE) fullscreenMode = true;
- if (configFlags & FLAG_WINDOW_ALWAYS_RUN) alwaysRun = true;
+ if (CORE.Window.flags & FLAG_FULLSCREEN_MODE) CORE.Window.fullscreen = true;
+ if (CORE.Window.flags & FLAG_WINDOW_ALWAYS_RUN) CORE.Window.alwaysRun = true;
}
// NOTE TraceLog() function is located in [utils.h]
@@ -1806,12 +1816,12 @@ void SetConfigFlags(unsigned int flags)
// have their own internal file-systems, to dowload image to user file-system some additional mechanism is required
void TakeScreenshot(const char *fileName)
{
- unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight);
- Image image = { imgData, renderWidth, renderHeight, 1, UNCOMPRESSED_R8G8B8A8 };
+ unsigned char *imgData = rlReadScreenPixels(CORE.Window.render.width, CORE.Window.render.height);
+ Image image = { imgData, CORE.Window.render.width, CORE.Window.render.height, 1, UNCOMPRESSED_R8G8B8A8 };
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
- strcpy(path, internalDataPath);
+ strcpy(path, CORE.Android.internalDataPath);
strcat(path, "/");
strcat(path, fileName);
#else
@@ -1959,15 +1969,15 @@ const char *GetDirectoryPath(const char *filePath)
// For security, we set starting path to current directory,
// obtained path will be concated to this
- dirPath[0] = '.';
- dirPath[1] = '/';
+ //dirPath[0] = '.';
+ //dirPath[1] = '/';
lastSlash = strprbrk(filePath, "\\/");
if (lastSlash)
{
// NOTE: Be careful, strncpy() is not safe, it does not care about '\0'
- strncpy(dirPath + 2, filePath, strlen(filePath) - (strlen(lastSlash) - 1));
- dirPath[2 + strlen(filePath) - strlen(lastSlash)] = '\0'; // Add '\0' manually
+ strncpy(dirPath, filePath, strlen(filePath) - (strlen(lastSlash) - 1));
+ dirPath[strlen(filePath) - strlen(lastSlash)] = '\0'; // Add '\0' manually
}
return dirPath;
@@ -2066,27 +2076,27 @@ bool ChangeDirectory(const char *dir)
// Check if a file has been dropped into window
bool IsFileDropped(void)
{
- if (dropFilesCount > 0) return true;
+ if (CORE.Window.dropFilesCount > 0) return true;
else return false;
}
// Get dropped files names
char **GetDroppedFiles(int *count)
{
- *count = dropFilesCount;
- return dropFilesPath;
+ *count = CORE.Window.dropFilesCount;
+ return CORE.Window.dropFilesPath;
}
// Clear dropped files paths buffer
void ClearDroppedFiles(void)
{
- if (dropFilesCount > 0)
+ if (CORE.Window.dropFilesCount > 0)
{
- for (int i = 0; i < dropFilesCount; i++) RL_FREE(dropFilesPath[i]);
+ for (int i = 0; i < CORE.Window.dropFilesCount; i++) RL_FREE(CORE.Window.dropFilesPath[i]);
- RL_FREE(dropFilesPath);
+ RL_FREE(CORE.Window.dropFilesPath);
- dropFilesCount = 0;
+ CORE.Window.dropFilesCount = 0;
}
}
@@ -2139,7 +2149,7 @@ void StorageSaveValue(int position, int value)
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
- strcpy(path, internalDataPath);
+ strcpy(path, CORE.Android.internalDataPath);
strcat(path, "/");
strcat(path, STORAGE_FILENAME);
#else
@@ -2179,7 +2189,7 @@ int StorageLoadValue(int position)
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
- strcpy(path, internalDataPath);
+ strcpy(path, CORE.Android.internalDataPath);
strcat(path, "/");
strcat(path, STORAGE_FILENAME);
#else
@@ -2247,7 +2257,7 @@ bool IsKeyPressed(int key)
{
bool pressed = false;
- if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 1)) pressed = true;
+ if ((CORE.Input.Keyboard.currentKeyState[key] != CORE.Input.Keyboard.previousKeyState[key]) && (CORE.Input.Keyboard.currentKeyState[key] == 1)) pressed = true;
else pressed = false;
return pressed;
@@ -2265,7 +2275,7 @@ bool IsKeyReleased(int key)
{
bool released = false;
- if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true;
+ if ((CORE.Input.Keyboard.currentKeyState[key] != CORE.Input.Keyboard.previousKeyState[key]) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true;
else released = false;
return released;
@@ -2283,17 +2293,17 @@ int GetKeyPressed(void)
{
int value = 0;
- if (keyPressedQueueCount > 0)
+ if (CORE.Input.Keyboard.keyPressedQueueCount > 0)
{
// Get character from the queue head
- value = keyPressedQueue[0];
+ value = CORE.Input.Keyboard.keyPressedQueue[0];
// Shift elements 1 step toward the head.
- for (int i = 0; i < (keyPressedQueueCount - 1); i++) keyPressedQueue[i] = keyPressedQueue[i + 1];
+ for (int i = 0; i < (CORE.Input.Keyboard.keyPressedQueueCount - 1); i++) CORE.Input.Keyboard.keyPressedQueue[i] = CORE.Input.Keyboard.keyPressedQueue[i + 1];
// Reset last character in the queue
- keyPressedQueue[keyPressedQueueCount] = 0;
- keyPressedQueueCount--;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 0;
+ CORE.Input.Keyboard.keyPressedQueueCount--;
}
return value;
@@ -2304,7 +2314,7 @@ int GetKeyPressed(void)
void SetExitKey(int key)
{
#if !defined(PLATFORM_ANDROID)
- exitKey = key;
+ CORE.Input.Keyboard.exitKey = key;
#endif
}
@@ -2316,7 +2326,7 @@ bool IsGamepadAvailable(int gamepad)
bool result = false;
#if !defined(PLATFORM_ANDROID)
- if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true;
+ if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad]) result = true;
#endif
return result;
@@ -2328,10 +2338,10 @@ bool IsGamepadName(int gamepad, const char *name)
bool result = false;
#if !defined(PLATFORM_ANDROID)
- const char *gamepadName = NULL;
+ const char *currentName = NULL;
- if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad);
- if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0);
+ if (CORE.Input.Gamepad.ready[gamepad]) currentName = GetGamepadName(gamepad);
+ if ((name != NULL) && (currentName != NULL)) result = (strcmp(name, currentName) == 0);
#endif
return result;
@@ -2341,12 +2351,12 @@ bool IsGamepadName(int gamepad, const char *name)
const char *GetGamepadName(int gamepad)
{
#if defined(PLATFORM_DESKTOP)
- if (gamepadReady[gamepad]) return glfwGetJoystickName(gamepad);
+ if (CORE.Input.Gamepad.ready[gamepad]) return glfwGetJoystickName(gamepad);
else return NULL;
#elif defined(PLATFORM_RPI)
- if (gamepadReady[gamepad]) ioctl(gamepadStream[gamepad], JSIOCGNAME(64), &gamepadName);
+ if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGNAME(64), &CORE.Input.Gamepad.name);
- return gamepadName;
+ return CORE.Input.Gamepad.name;
#else
return NULL;
#endif
@@ -2357,10 +2367,10 @@ int GetGamepadAxisCount(int gamepad)
{
#if defined(PLATFORM_RPI)
int axisCount = 0;
- if (gamepadReady[gamepad]) ioctl(gamepadStream[gamepad], JSIOCGAXES, &axisCount);
- gamepadAxisCount = axisCount;
+ if (CORE.Input.Gamepad.ready[gamepad]) ioctl(CORE.Input.Gamepad.streamId[gamepad], JSIOCGAXES, &axisCount);
+ CORE.Input.Gamepad.axisCount = axisCount;
#endif
- return gamepadAxisCount;
+ return CORE.Input.Gamepad.axisCount;
}
// Return axis movement vector for a gamepad
@@ -2369,7 +2379,7 @@ float GetGamepadAxisMovement(int gamepad, int axis)
float value = 0;
#if !defined(PLATFORM_ANDROID)
- if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis];
+ if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = CORE.Input.Gamepad.axisState[gamepad][axis];
#endif
return value;
@@ -2381,9 +2391,9 @@ bool IsGamepadButtonPressed(int gamepad, int button)
bool pressed = false;
#if !defined(PLATFORM_ANDROID)
- if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
- (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&
- (currentGamepadState[gamepad][button] == 1)) pressed = true;
+ if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
+ (CORE.Input.Gamepad.currentState[gamepad][button] != CORE.Input.Gamepad.previousState[gamepad][button]) &&
+ (CORE.Input.Gamepad.currentState[gamepad][button] == 1)) pressed = true;
#endif
return pressed;
@@ -2395,8 +2405,8 @@ bool IsGamepadButtonDown(int gamepad, int button)
bool result = false;
#if !defined(PLATFORM_ANDROID)
- if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
- (currentGamepadState[gamepad][button] == 1)) result = true;
+ if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
+ (CORE.Input.Gamepad.currentState[gamepad][button] == 1)) result = true;
#endif
return result;
@@ -2408,9 +2418,9 @@ bool IsGamepadButtonReleased(int gamepad, int button)
bool released = false;
#if !defined(PLATFORM_ANDROID)
- if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
- (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) &&
- (currentGamepadState[gamepad][button] == 0)) released = true;
+ if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
+ (CORE.Input.Gamepad.currentState[gamepad][button] != CORE.Input.Gamepad.previousState[gamepad][button]) &&
+ (CORE.Input.Gamepad.currentState[gamepad][button] == 0)) released = true;
#endif
return released;
@@ -2422,8 +2432,8 @@ bool IsGamepadButtonUp(int gamepad, int button)
bool result = false;
#if !defined(PLATFORM_ANDROID)
- if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
- (currentGamepadState[gamepad][button] == 0)) result = true;
+ if ((gamepad < MAX_GAMEPADS) && CORE.Input.Gamepad.ready[gamepad] && (button < MAX_GAMEPAD_BUTTONS) &&
+ (CORE.Input.Gamepad.currentState[gamepad][button] == 0)) result = true;
#endif
return result;
@@ -2432,7 +2442,7 @@ bool IsGamepadButtonUp(int gamepad, int button)
// Get the last gamepad button pressed
int GetGamepadButtonPressed(void)
{
- return lastGamepadButtonPressed;
+ return CORE.Input.Gamepad.lastButtonPressed;
}
// Detect if a mouse button has been pressed once
@@ -2444,7 +2454,8 @@ bool IsMouseButtonPressed(int button)
if (IsGestureDetected(GESTURE_TAP)) pressed = true;
#else
// NOTE: On PLATFORM_DESKTOP and PLATFORM_WEB IsMouseButtonPressed() is equivalent to GESTURE_TAP
- if (((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 1)) || IsGestureDetected(GESTURE_TAP)) pressed = true;
+ if (((CORE.Input.Mouse.currentButtonState[button] != CORE.Input.Mouse.previousButtonState[button]) &&
+ (CORE.Input.Mouse.currentButtonState[button] == 1)) || IsGestureDetected(GESTURE_TAP)) pressed = true;
#endif
return pressed;
@@ -2471,7 +2482,8 @@ bool IsMouseButtonReleased(int button)
bool released = false;
#if !defined(PLATFORM_ANDROID)
- if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 0)) released = true;
+ if ((CORE.Input.Mouse.currentButtonState[button] != CORE.Input.Mouse.previousButtonState[button]) &&
+ (CORE.Input.Mouse.currentButtonState[button] == 0)) released = true;
#endif
return released;
@@ -2493,9 +2505,9 @@ bool IsMouseButtonUp(int button)
int GetMouseX(void)
{
#if defined(PLATFORM_ANDROID)
- return (int)touchPosition[0].x;
+ return (int)CORE.Input.Touch.position[0].x;
#else
- return (int)((mousePosition.x + mouseOffset.x)*mouseScale.x);
+ return (int)((CORE.Input.Mouse.position.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x);
#endif
}
@@ -2503,9 +2515,9 @@ int GetMouseX(void)
int GetMouseY(void)
{
#if defined(PLATFORM_ANDROID)
- return (int)touchPosition[0].y;
+ return (int)CORE.Input.Touch.position[0].y;
#else
- return (int)((mousePosition.y + mouseOffset.y)*mouseScale.y);
+ return (int)((CORE.Input.Mouse.position.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y);
#endif
}
@@ -2517,7 +2529,7 @@ Vector2 GetMousePosition(void)
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
position = GetTouchPosition(0);
#else
- position = (Vector2){ (mousePosition.x + mouseOffset.x)*mouseScale.x, (mousePosition.y + mouseOffset.y)*mouseScale.y };
+ position = (Vector2){ (CORE.Input.Mouse.position.x + CORE.Input.Mouse.offset.x)*CORE.Input.Mouse.scale.x, (CORE.Input.Mouse.position.y + CORE.Input.Mouse.offset.y)*CORE.Input.Mouse.scale.y };
#endif
return position;
@@ -2526,16 +2538,16 @@ Vector2 GetMousePosition(void)
// Set mouse position XY
void SetMousePosition(int x, int y)
{
- mousePosition = (Vector2){ (float)x, (float)y };
+ CORE.Input.Mouse.position = (Vector2){ (float)x, (float)y };
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
// NOTE: emscripten not implemented
- glfwSetCursorPos(window, mousePosition.x, mousePosition.y);
+ glfwSetCursorPos(CORE.Window.handle, CORE.Input.Mouse.position.x, CORE.Input.Mouse.position.y);
#endif
#if defined(PLATFORM_UWP)
UWPMessage *msg = CreateUWPMessage();
msg->type = UWP_MSG_SET_MOUSE_LOCATION;
- msg->paramVector0.x = mousePosition.x;
- msg->paramVector0.y = mousePosition.y;
+ msg->paramVector0.x = CORE.Input.Mouse.position.x;
+ msg->paramVector0.y = CORE.Input.Mouse.position.y;
SendMessageToUWP(msg);
#endif
}
@@ -2544,14 +2556,14 @@ void SetMousePosition(int x, int y)
// NOTE: Useful when rendering to different size targets
void SetMouseOffset(int offsetX, int offsetY)
{
- mouseOffset = (Vector2){ (float)offsetX, (float)offsetY };
+ CORE.Input.Mouse.offset = (Vector2){ (float)offsetX, (float)offsetY };
}
// Set mouse scaling
// NOTE: Useful when rendering to different size targets
void SetMouseScale(float scaleX, float scaleY)
{
- mouseScale = (Vector2){ scaleX, scaleY };
+ CORE.Input.Mouse.scale = (Vector2){ scaleX, scaleY };
}
// Returns mouse wheel movement Y
@@ -2560,9 +2572,9 @@ int GetMouseWheelMove(void)
#if defined(PLATFORM_ANDROID)
return 0;
#elif defined(PLATFORM_WEB)
- return previousMouseWheelY/100;
+ return CORE.Input.Mouse.previousWheelMove/100;
#else
- return previousMouseWheelY;
+ return CORE.Input.Mouse.previousWheelMove;
#endif
}
@@ -2570,7 +2582,7 @@ int GetMouseWheelMove(void)
int GetTouchX(void)
{
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
- return (int)touchPosition[0].x;
+ return (int)CORE.Input.Touch.position[0].x;
#else // PLATFORM_DESKTOP, PLATFORM_RPI
return GetMouseX();
#endif
@@ -2580,7 +2592,7 @@ int GetTouchX(void)
int GetTouchY(void)
{
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
- return (int)touchPosition[0].y;
+ return (int)CORE.Input.Touch.position[0].y;
#else // PLATFORM_DESKTOP, PLATFORM_RPI
return GetMouseY();
#endif
@@ -2593,24 +2605,24 @@ Vector2 GetTouchPosition(int index)
Vector2 position = { -1.0f, -1.0f };
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
- if (index < MAX_TOUCH_POINTS) position = touchPosition[index];
+ if (index < MAX_TOUCH_POINTS) position = CORE.Input.Touch.position[index];
else TraceLog(LOG_WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS);
#if defined(PLATFORM_ANDROID)
- if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
+ if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height))
{
- position.x = position.x*((float)screenWidth/(float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
- position.y = position.y*((float)screenHeight/(float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
+ position.x = position.x*((float)CORE.Window.screen.width/(float)(CORE.Window.display.width - CORE.Window.renderOffset.x)) - CORE.Window.renderOffset.x/2;
+ position.y = position.y*((float)CORE.Window.screen.height/(float)(CORE.Window.display.height - CORE.Window.renderOffset.y)) - CORE.Window.renderOffset.y/2;
}
else
{
- position.x = position.x*((float)renderWidth/(float)displayWidth) - renderOffsetX/2;
- position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2;
+ position.x = position.x*((float)CORE.Window.render.width/(float)CORE.Window.display.width) - CORE.Window.renderOffset.x/2;
+ position.y = position.y*((float)CORE.Window.render.height/(float)CORE.Window.display.height) - CORE.Window.renderOffset.y/2;
}
#endif
#endif
#if defined(PLATFORM_RPI)
- position = touchPosition[index];
+ position = CORE.Input.Touch.position[index];
#endif
#if defined(PLATFORM_DESKTOP)
// TODO: GLFW is not supporting multi-touch input just yet
@@ -2633,12 +2645,12 @@ Vector2 GetTouchPosition(int index)
// NOTE: returns false in case graphic device could not be created
static bool InitGraphicsDevice(int width, int height)
{
- screenWidth = width; // User desired width
- screenHeight = height; // User desired height
+ CORE.Window.screen.width = width; // User desired width
+ CORE.Window.screen.height = height; // User desired height
- screenScaling = MatrixIdentity(); // No draw scaling required by default
+ CORE.Window.screenScale = MatrixIdentity(); // No draw scaling required by default
- // NOTE: Framebuffer (render area - renderWidth, renderHeight) could include black bars...
+ // NOTE: Framebuffer (render area - CORE.Window.render.width, CORE.Window.render.height) could include black bars...
// ...in top-down or left-right to match display aspect ratio (no weird scalings)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
@@ -2665,17 +2677,17 @@ static bool InitGraphicsDevice(int width, int height)
}
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
- displayWidth = mode->width;
- displayHeight = mode->height;
+ CORE.Window.display.width = mode->width;
+ CORE.Window.display.height = mode->height;
// Screen size security check
- if (screenWidth <= 0) screenWidth = displayWidth;
- if (screenHeight <= 0) screenHeight = displayHeight;
+ if (CORE.Window.screen.width <= 0) CORE.Window.screen.width = CORE.Window.display.width;
+ if (CORE.Window.screen.height <= 0) CORE.Window.screen.height = CORE.Window.display.height;
#endif // PLATFORM_DESKTOP
#if defined(PLATFORM_WEB)
- displayWidth = screenWidth;
- displayHeight = screenHeight;
+ CORE.Window.display.width = CORE.Window.screen.width;
+ CORE.Window.display.height = CORE.Window.screen.height;
#endif // PLATFORM_WEB
glfwDefaultWindowHints(); // Set default windows hints:
@@ -2695,21 +2707,21 @@ static bool InitGraphicsDevice(int width, int height)
#endif
// Check some Window creation flags
- if (configFlags & FLAG_WINDOW_HIDDEN) glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // Visible window
+ if (CORE.Window.flags & FLAG_WINDOW_HIDDEN) glfwWindowHint(GLFW_VISIBLE, GL_FALSE); // Visible window
else glfwWindowHint(GLFW_VISIBLE, GL_TRUE); // Window initially hidden
- if (configFlags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window
+ if (CORE.Window.flags & FLAG_WINDOW_RESIZABLE) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window
else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
- if (configFlags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window
+ if (CORE.Window.flags & FLAG_WINDOW_UNDECORATED) glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); // Border and buttons on Window
else glfwWindowHint(GLFW_DECORATED, GLFW_TRUE); // Decorated window
// FLAG_WINDOW_TRANSPARENT not supported on HTML5 and not included in any released GLFW version yet
#if defined(GLFW_TRANSPARENT_FRAMEBUFFER)
- if (configFlags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
+ if (CORE.Window.flags & FLAG_WINDOW_TRANSPARENT) glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE); // Transparent framebuffer
else glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE); // Opaque framebuffer
#endif
- if (configFlags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0
+ if (CORE.Window.flags & FLAG_MSAA_4X_HINT) glfwWindowHint(GLFW_SAMPLES, 4); // Tries to enable multisampling x4 (MSAA), default is 0
// NOTE: When asking for an OpenGL context version, most drivers provide highest supported version
// with forward compatibility to older OpenGL versions.
@@ -2746,28 +2758,28 @@ static bool InitGraphicsDevice(int width, int height)
#endif
}
- if (fullscreenMode)
+ if (CORE.Window.fullscreen)
{
// remember center for switchinging from fullscreen to window
- windowPositionX = displayWidth/2 - screenWidth/2;
- windowPositionY = displayHeight/2 - screenHeight/2;
+ CORE.Window.position.x = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
+ CORE.Window.position.y = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
- if (windowPositionX < 0) windowPositionX = 0;
- if (windowPositionY < 0) windowPositionY = 0;
+ if (CORE.Window.position.x < 0) CORE.Window.position.x = 0;
+ if (CORE.Window.position.y < 0) CORE.Window.position.y = 0;
- // Obtain recommended displayWidth/displayHeight from a valid videomode for the monitor
+ // Obtain recommended CORE.Window.display.width/CORE.Window.display.height from a valid videomode for the monitor
int count = 0;
const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count);
- // Get closest video mode to desired screenWidth/screenHeight
+ // Get closest video mode to desired CORE.Window.screen.width/CORE.Window.screen.height
for (int i = 0; i < count; i++)
{
- if (modes[i].width >= screenWidth)
+ if (modes[i].width >= CORE.Window.screen.width)
{
- if (modes[i].height >= screenHeight)
+ if (modes[i].height >= CORE.Window.screen.height)
{
- displayWidth = modes[i].width;
- displayHeight = modes[i].height;
+ CORE.Window.display.width = modes[i].width;
+ CORE.Window.display.height = modes[i].height;
break;
}
}
@@ -2775,13 +2787,13 @@ static bool InitGraphicsDevice(int width, int height)
#if defined(PLATFORM_DESKTOP)
// If we are windowed fullscreen, ensures that window does not minimize when focus is lost
- if ((screenHeight == displayHeight) && (screenWidth == displayWidth))
+ if ((CORE.Window.screen.height == CORE.Window.display.height) && (CORE.Window.screen.width == CORE.Window.display.width))
{
glfwWindowHint(GLFW_AUTO_ICONIFY, 0);
}
#endif
- TraceLog(LOG_WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight);
+ TraceLog(LOG_WARNING, "Closest fullscreen videomode: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
// NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example,
// for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3),
@@ -2790,39 +2802,39 @@ static bool InitGraphicsDevice(int width, int height)
// Try to setup the most appropiate fullscreen framebuffer for the requested screenWidth/screenHeight
// It considers device display resolution mode and setups a framebuffer with black bars if required (render size/offset)
- // Modified global variables: screenWidth/screenHeight - renderWidth/renderHeight - renderOffsetX/renderOffsetY - screenScaling
+ // Modified global variables: CORE.Window.screen.width/CORE.Window.screen.height - CORE.Window.render.width/CORE.Window.render.height - CORE.Window.renderOffset.x/CORE.Window.renderOffset.y - CORE.Window.screenScale
// TODO: It is a quite cumbersome solution to display size vs requested size, it should be reviewed or removed...
// HighDPI monitors are properly considered in a following similar function: SetupViewport()
- SetupFramebuffer(displayWidth, displayHeight);
+ SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
- window = glfwCreateWindow(displayWidth, displayHeight, windowTitle, glfwGetPrimaryMonitor(), NULL);
+ CORE.Window.handle = glfwCreateWindow(CORE.Window.display.width, CORE.Window.display.height, CORE.Window.title, glfwGetPrimaryMonitor(), NULL);
// NOTE: Full-screen change, not working properly...
- //glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE);
+ //glfwSetWindowMonitor(CORE.Window.handle, glfwGetPrimaryMonitor(), 0, 0, CORE.Window.screen.width, CORE.Window.screen.height, GLFW_DONT_CARE);
}
else
{
// No-fullscreen window creation
- window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, NULL, NULL);
+ CORE.Window.handle = glfwCreateWindow(CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.title, NULL, NULL);
- if (window)
+ if (CORE.Window.handle)
{
#if defined(PLATFORM_DESKTOP)
// Center window on screen
- int windowPosX = displayWidth/2 - screenWidth/2;
- int windowPosY = displayHeight/2 - screenHeight/2;
+ int windowPosX = CORE.Window.display.width/2 - CORE.Window.screen.width/2;
+ int windowPosY = CORE.Window.display.height/2 - CORE.Window.screen.height/2;
if (windowPosX < 0) windowPosX = 0;
if (windowPosY < 0) windowPosY = 0;
- glfwSetWindowPos(window, windowPosX, windowPosY);
+ glfwSetWindowPos(CORE.Window.handle, windowPosX, windowPosY);
#endif
- renderWidth = screenWidth;
- renderHeight = screenHeight;
+ CORE.Window.render.width = CORE.Window.screen.width;
+ CORE.Window.render.height = CORE.Window.screen.height;
}
}
- if (!window)
+ if (!CORE.Window.handle)
{
glfwTerminate();
TraceLog(LOG_WARNING, "GLFW Failed to initialize Window");
@@ -2832,24 +2844,24 @@ static bool InitGraphicsDevice(int width, int height)
{
TraceLog(LOG_INFO, "Display device initialized successfully");
#if defined(PLATFORM_DESKTOP)
- TraceLog(LOG_INFO, "Display size: %i x %i", displayWidth, displayHeight);
+ TraceLog(LOG_INFO, "Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
#endif
- TraceLog(LOG_INFO, "Render size: %i x %i", renderWidth, renderHeight);
- TraceLog(LOG_INFO, "Screen size: %i x %i", screenWidth, screenHeight);
- TraceLog(LOG_INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY);
+ TraceLog(LOG_INFO, "Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
+ TraceLog(LOG_INFO, "Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
+ TraceLog(LOG_INFO, "Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
}
- glfwSetWindowSizeCallback(window, WindowSizeCallback); // NOTE: Resizing not allowed by default!
- glfwSetCursorEnterCallback(window, CursorEnterCallback);
- glfwSetKeyCallback(window, KeyCallback);
- glfwSetMouseButtonCallback(window, MouseButtonCallback);
- glfwSetCursorPosCallback(window, MouseCursorPosCallback); // Track mouse position changes
- glfwSetCharCallback(window, CharCallback);
- glfwSetScrollCallback(window, ScrollCallback);
- glfwSetWindowIconifyCallback(window, WindowIconifyCallback);
- glfwSetDropCallback(window, WindowDropCallback);
+ glfwSetWindowSizeCallback(CORE.Window.handle, WindowSizeCallback); // NOTE: Resizing not allowed by default!
+ glfwSetCursorEnterCallback(CORE.Window.handle, CursorEnterCallback);
+ glfwSetKeyCallback(CORE.Window.handle, KeyCallback);
+ glfwSetMouseButtonCallback(CORE.Window.handle, MouseButtonCallback);
+ glfwSetCursorPosCallback(CORE.Window.handle, MouseCursorPosCallback); // Track mouse position changes
+ glfwSetCharCallback(CORE.Window.handle, CharCallback);
+ glfwSetScrollCallback(CORE.Window.handle, ScrollCallback);
+ glfwSetWindowIconifyCallback(CORE.Window.handle, WindowIconifyCallback);
+ glfwSetDropCallback(CORE.Window.handle, WindowDropCallback);
- glfwMakeContextCurrent(window);
+ glfwMakeContextCurrent(CORE.Window.handle);
#if !defined(PLATFORM_WEB)
glfwSwapInterval(0); // No V-Sync by default
@@ -2863,7 +2875,7 @@ static bool InitGraphicsDevice(int width, int height)
// Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS)
// NOTE: V-Sync can be enabled by graphic driver configuration
- if (configFlags & FLAG_VSYNC_HINT)
+ if (CORE.Window.flags & FLAG_VSYNC_HINT)
{
// WARNING: It seems to hits a critical render path in Intel HD Graphics
glfwSwapInterval(1);
@@ -2872,11 +2884,11 @@ static bool InitGraphicsDevice(int width, int height)
#endif // PLATFORM_DESKTOP || PLATFORM_WEB
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
- fullscreenMode = true;
+ CORE.Window.fullscreen = true;
// Screen size security check
- if (screenWidth <= 0) screenWidth = displayWidth;
- if (screenHeight <= 0) screenHeight = displayHeight;
+ if (CORE.Window.screen.width <= 0) CORE.Window.screen.width = CORE.Window.display.width;
+ if (CORE.Window.screen.height <= 0) CORE.Window.screen.height = CORE.Window.display.height;
#if defined(PLATFORM_RPI)
bcm_host_init();
@@ -2891,7 +2903,7 @@ static bool InitGraphicsDevice(int width, int height)
EGLint samples = 0;
EGLint sampleBuffer = 0;
- if (configFlags & FLAG_MSAA_4X_HINT)
+ if (CORE.Window.flags & FLAG_MSAA_4X_HINT)
{
samples = 4;
sampleBuffer = 1;
@@ -2969,8 +2981,6 @@ static bool InitGraphicsDevice(int width, int height)
EGL_NONE,
};
- EGLConfig config = NULL;
-
// eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11.
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)(eglGetProcAddress("eglGetPlatformDisplayEXT"));
if (!eglGetPlatformDisplayEXT)
@@ -2990,34 +3000,34 @@ static bool InitGraphicsDevice(int width, int height)
//
// This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
- display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
- if (display == EGL_NO_DISPLAY)
+ CORE.Window.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
+ if (CORE.Window.device == EGL_NO_DISPLAY)
{
- TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ TraceLog(LOG_WARNING, "Failed to initialize EGL device");
return false;
}
- if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE)
{
// This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
- display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
- if (display == EGL_NO_DISPLAY)
+ CORE.Window.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
+ if (CORE.Window.device == EGL_NO_DISPLAY)
{
- TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ TraceLog(LOG_WARNING, "Failed to initialize EGL device");
return false;
}
- if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE)
{
// This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
- display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
- if (display == EGL_NO_DISPLAY)
+ CORE.Window.device = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
+ if (CORE.Window.device == EGL_NO_DISPLAY)
{
- TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ TraceLog(LOG_WARNING, "Failed to initialize EGL device");
return false;
}
- if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE)
{
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
TraceLog(LOG_WARNING, "Failed to initialize EGL");
@@ -3027,7 +3037,7 @@ static bool InitGraphicsDevice(int width, int height)
}
EGLint numConfigs = 0;
- if ((eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
+ if ((eglChooseConfig(CORE.Window.device, framebufferAttribs, &CORE.Window.config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
{
TraceLog(LOG_WARNING, "Failed to choose first EGLConfig");
return false;
@@ -3063,38 +3073,38 @@ static bool InitGraphicsDevice(int width, int height)
//https://stackoverflow.com/questions/46550182/how-to-create-eglsurface-using-c-winrt-and-angle
- //surface = eglCreateWindowSurface(display, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);
- surface = eglCreateWindowSurface(display, config, uwpWindow, surfaceAttributes);
- if (surface == EGL_NO_SURFACE)
+ //CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);
+ CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, handle, surfaceAttributes);
+ if (CORE.Window.surface == EGL_NO_SURFACE)
{
TraceLog(LOG_WARNING, "Failed to create EGL fullscreen surface");
return false;
}
- context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
- if (context == EGL_NO_CONTEXT)
+ CORE.Window.context = eglCreateContext(CORE.Window.device, CORE.Window.config, EGL_NO_CONTEXT, contextAttribs);
+ if (CORE.Window.context == EGL_NO_CONTEXT)
{
TraceLog(LOG_WARNING, "Failed to create EGL context");
return false;
}
- // Get EGL display window size
- eglQuerySurface(display, surface, EGL_WIDTH, &screenWidth);
- eglQuerySurface(display, surface, EGL_HEIGHT, &screenHeight);
+ // Get EGL device window size
+ eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_WIDTH, &CORE.Window.screen.width);
+ eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_HEIGHT, &CORE.Window.screen.height);
#else // PLATFORM_ANDROID, PLATFORM_RPI
EGLint numConfigs;
- // Get an EGL display connection
- display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- if (display == EGL_NO_DISPLAY)
+ // Get an EGL device connection
+ CORE.Window.device = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (CORE.Window.device == EGL_NO_DISPLAY)
{
- TraceLog(LOG_WARNING, "Failed to initialize EGL display");
+ TraceLog(LOG_WARNING, "Failed to initialize EGL device");
return false;
}
- // Initialize the EGL display connection
- if (eglInitialize(display, NULL, NULL) == EGL_FALSE)
+ // Initialize the EGL device connection
+ if (eglInitialize(CORE.Window.device, NULL, NULL) == EGL_FALSE)
{
// If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
TraceLog(LOG_WARNING, "Failed to initialize EGL");
@@ -3102,14 +3112,14 @@ static bool InitGraphicsDevice(int width, int height)
}
// Get an appropriate EGL framebuffer configuration
- eglChooseConfig(display, framebufferAttribs, &config, 1, &numConfigs);
+ eglChooseConfig(CORE.Window.device, framebufferAttribs, &CORE.Window.config, 1, &numConfigs);
// Set rendering API
eglBindAPI(EGL_OPENGL_ES_API);
// Create an EGL rendering context
- context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
- if (context == EGL_NO_CONTEXT)
+ CORE.Window.context = eglCreateContext(CORE.Window.device, CORE.Window.config, EGL_NO_CONTEXT, contextAttribs);
+ if (CORE.Window.context == EGL_NO_CONTEXT)
{
TraceLog(LOG_WARNING, "Failed to create EGL context");
return false;
@@ -3121,39 +3131,39 @@ static bool InitGraphicsDevice(int width, int height)
#if defined(PLATFORM_ANDROID)
EGLint displayFormat;
- displayWidth = ANativeWindow_getWidth(androidApp->window);
- displayHeight = ANativeWindow_getHeight(androidApp->window);
+ CORE.Window.display.width = ANativeWindow_getWidth(CORE.Android.app->window);
+ CORE.Window.display.height = ANativeWindow_getHeight(CORE.Android.app->window);
// EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is guaranteed to be accepted by ANativeWindow_setBuffersGeometry()
// As soon as we picked a EGLConfig, we can safely reconfigure the ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID
- eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &displayFormat);
+ eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
// At this point we need to manage render size vs screen size
- // NOTE: This function use and modify global module variables: screenWidth/screenHeight and renderWidth/renderHeight and screenScaling
- SetupFramebuffer(displayWidth, displayHeight);
+ // NOTE: This function use and modify global module variables: CORE.Window.screen.width/CORE.Window.screen.height and CORE.Window.render.width/CORE.Window.render.height and CORE.Window.screenScale
+ SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
- ANativeWindow_setBuffersGeometry(androidApp->window, renderWidth, renderHeight, displayFormat);
- //ANativeWindow_setBuffersGeometry(androidApp->window, 0, 0, displayFormat); // Force use of native display size
+ ANativeWindow_setBuffersGeometry(CORE.Android.app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat);
+ //ANativeWindow_setBuffersGeometry(CORE.Android.app->window, 0, 0, displayFormat); // Force use of native display size
- surface = eglCreateWindowSurface(display, config, androidApp->window, NULL);
+ CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, CORE.Android.app->window, NULL);
#endif // PLATFORM_ANDROID
#if defined(PLATFORM_RPI)
- graphics_get_display_size(0, &displayWidth, &displayHeight);
+ graphics_get_display_size(0, &CORE.Window.display.width, &CORE.Window.display.height);
// At this point we need to manage render size vs screen size
- // NOTE: This function use and modify global module variables: screenWidth/screenHeight and renderWidth/renderHeight and screenScaling
- SetupFramebuffer(displayWidth, displayHeight);
+ // NOTE: This function use and modify global module variables: CORE.Window.screen.width/CORE.Window.screen.height and CORE.Window.render.width/CORE.Window.render.height and CORE.Window.screenScale
+ SetupFramebuffer(CORE.Window.display.width, CORE.Window.display.height);
dstRect.x = 0;
dstRect.y = 0;
- dstRect.width = displayWidth;
- dstRect.height = displayHeight;
+ dstRect.width = CORE.Window.display.width;
+ dstRect.height = CORE.Window.display.height;
srcRect.x = 0;
srcRect.y = 0;
- srcRect.width = renderWidth << 16;
- srcRect.height = renderHeight << 16;
+ srcRect.width = CORE.Window.render.width << 16;
+ srcRect.height = CORE.Window.render.height << 16;
// NOTE: RPI dispmanx windowing system takes care of srcRec scaling to dstRec by hardware (no cost)
// Take care that renderWidth/renderHeight fit on displayWidth/displayHeight aspect ratio
@@ -3170,18 +3180,18 @@ static bool InitGraphicsDevice(int width, int height)
&srcRect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, DISPMANX_NO_ROTATE);
window.element = dispmanElement;
- window.width = renderWidth;
- window.height = renderHeight;
+ window.width = CORE.Window.render.width;
+ window.height = CORE.Window.render.height;
vc_dispmanx_update_submit_sync(dispmanUpdate);
- surface = eglCreateWindowSurface(display, config, &window, NULL);
+ CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, &window, NULL);
//---------------------------------------------------------------------------------
#endif // PLATFORM_RPI
// There must be at least one frame displayed before the buffers are swapped
- //eglSwapInterval(display, 1);
+ //eglSwapInterval(CORE.Window.device, 1);
- if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
+ if (eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context) == EGL_FALSE)
{
TraceLog(LOG_WARNING, "Unable to attach EGL rendering context to EGL surface");
return false;
@@ -3189,44 +3199,44 @@ static bool InitGraphicsDevice(int width, int height)
else
{
// Grab the width and height of the surface
- //eglQuerySurface(display, surface, EGL_WIDTH, &renderWidth);
- //eglQuerySurface(display, surface, EGL_HEIGHT, &renderHeight);
+ //eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_WIDTH, &CORE.Window.render.width);
+ //eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_HEIGHT, &CORE.Window.render.height);
TraceLog(LOG_INFO, "Display device initialized successfully");
- TraceLog(LOG_INFO, "Display size: %i x %i", displayWidth, displayHeight);
- TraceLog(LOG_INFO, "Render size: %i x %i", renderWidth, renderHeight);
- TraceLog(LOG_INFO, "Screen size: %i x %i", screenWidth, screenHeight);
- TraceLog(LOG_INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY);
+ TraceLog(LOG_INFO, "Display size: %i x %i", CORE.Window.display.width, CORE.Window.display.height);
+ TraceLog(LOG_INFO, "Render size: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
+ TraceLog(LOG_INFO, "Screen size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height);
+ TraceLog(LOG_INFO, "Viewport offsets: %i, %i", CORE.Window.renderOffset.x, CORE.Window.renderOffset.y);
}
#endif // PLATFORM_ANDROID || PLATFORM_RPI
// Initialize OpenGL context (states and resources)
- // NOTE: screenWidth and screenHeight not used, just stored as globals in rlgl
- rlglInit(screenWidth, screenHeight);
+ // NOTE: CORE.Window.screen.width and CORE.Window.screen.height not used, just stored as globals in rlgl
+ rlglInit(CORE.Window.screen.width, CORE.Window.screen.height);
- int fbWidth = renderWidth;
- int fbHeight = renderHeight;
+ int fbWidth = CORE.Window.render.width;
+ int fbHeight = CORE.Window.render.height;
#if defined(PLATFORM_DESKTOP) && defined(SUPPORT_HIGH_DPI)
- glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
+ glfwGetFramebufferSize(CORE.Window.handle, &fbWidth, &fbHeight);
// Screen scaling matrix is required in case desired screen area is different than display area
- screenScaling = MatrixScale((float)fbWidth/screenWidth, (float)fbHeight/screenHeight, 1.0f);
+ CORE.Window.screenScale = MatrixScale((float)fbWidth/CORE.Window.screen.width, (float)fbHeight/CORE.Window.screen.height, 1.0f);
#if !defined(__APPLE__)
- SetMouseScale((float)screenWidth/fbWidth, (float)screenHeight/fbHeight);
+ SetMouseScale((float)CORE.Window.screen.width/fbWidth, (float)CORE.Window.screen.height/fbHeight);
#endif
#endif // PLATFORM_DESKTOP && SUPPORT_HIGH_DPI
// Setup default viewport
SetupViewport(fbWidth, fbHeight);
- currentWidth = screenWidth;
- currentHeight = screenHeight;
+ CORE.Window.currentFbo.width = CORE.Window.screen.width;
+ CORE.Window.currentFbo.height = CORE.Window.screen.height;
ClearBackground(RAYWHITE); // Default background color for raylib games :P
#if defined(PLATFORM_ANDROID)
- windowReady = true; // IMPORTANT!
+ CORE.Window.ready = true;
#endif
return true;
}
@@ -3234,94 +3244,94 @@ static bool InitGraphicsDevice(int width, int height)
// Set viewport for a provided width and height
static void SetupViewport(int width, int height)
{
- renderWidth = width;
- renderHeight = height;
+ CORE.Window.render.width = width;
+ CORE.Window.render.height = height;
// Set viewport width and height
// NOTE: We consider render size and offset in case black bars are required and
// render area does not match full display area (this situation is only applicable on fullscreen mode)
- rlViewport(renderOffsetX/2, renderOffsetY/2, renderWidth - renderOffsetX, renderHeight - renderOffsetY);
+ rlViewport(CORE.Window.renderOffset.x/2, CORE.Window.renderOffset.y/2, CORE.Window.render.width - CORE.Window.renderOffset.x, CORE.Window.render.height - CORE.Window.renderOffset.y);
rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix
rlLoadIdentity(); // Reset current matrix (PROJECTION)
// Set orthographic projection to current framebuffer size
// NOTE: Configured top-left corner as (0, 0)
- rlOrtho(0, renderWidth, renderHeight, 0, 0.0f, 1.0f);
+ rlOrtho(0, CORE.Window.render.width, CORE.Window.render.height, 0, 0.0f, 1.0f);
rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
}
// Compute framebuffer size relative to screen size and display size
-// NOTE: Global variables renderWidth/renderHeight and renderOffsetX/renderOffsetY can be modified
+// NOTE: Global variables CORE.Window.render.width/CORE.Window.render.height and CORE.Window.renderOffset.x/CORE.Window.renderOffset.y can be modified
static void SetupFramebuffer(int width, int height)
{
- // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var)
- if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
+ // Calculate CORE.Window.render.width and CORE.Window.render.height, we have the display size (input params) and the desired screen size (global var)
+ if ((CORE.Window.screen.width > CORE.Window.display.width) || (CORE.Window.screen.height > CORE.Window.display.height))
{
- TraceLog(LOG_WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight);
+ TraceLog(LOG_WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.display.width, CORE.Window.display.height);
// Downscaling to fit display with border-bars
- float widthRatio = (float)displayWidth/(float)screenWidth;
- float heightRatio = (float)displayHeight/(float)screenHeight;
+ float widthRatio = (float)CORE.Window.display.width/(float)CORE.Window.screen.width;
+ float heightRatio = (float)CORE.Window.display.height/(float)CORE.Window.screen.height;
if (widthRatio <= heightRatio)
{
- renderWidth = displayWidth;
- renderHeight = (int)round((float)screenHeight*widthRatio);
- renderOffsetX = 0;
- renderOffsetY = (displayHeight - renderHeight);
+ CORE.Window.render.width = CORE.Window.display.width;
+ CORE.Window.render.height = (int)round((float)CORE.Window.screen.height*widthRatio);
+ CORE.Window.renderOffset.x = 0;
+ CORE.Window.renderOffset.y = (CORE.Window.display.height - CORE.Window.render.height);
}
else
{
- renderWidth = (int)round((float)screenWidth*heightRatio);
- renderHeight = displayHeight;
- renderOffsetX = (displayWidth - renderWidth);
- renderOffsetY = 0;
+ CORE.Window.render.width = (int)round((float)CORE.Window.screen.width*heightRatio);
+ CORE.Window.render.height = CORE.Window.display.height;
+ CORE.Window.renderOffset.x = (CORE.Window.display.width - CORE.Window.render.width);
+ CORE.Window.renderOffset.y = 0;
}
// Screen scaling required
- float scaleRatio = (float)renderWidth/(float)screenWidth;
- screenScaling = MatrixScale(scaleRatio, scaleRatio, 1.0f);
+ float scaleRatio = (float)CORE.Window.render.width/(float)CORE.Window.screen.width;
+ CORE.Window.screenScale = MatrixScale(scaleRatio, scaleRatio, 1.0f);
// NOTE: We render to full display resolution!
// We just need to calculate above parameters for downscale matrix and offsets
- renderWidth = displayWidth;
- renderHeight = displayHeight;
+ CORE.Window.render.width = CORE.Window.display.width;
+ CORE.Window.render.height = CORE.Window.display.height;
- TraceLog(LOG_WARNING, "Downscale matrix generated, content will be rendered at: %i x %i", renderWidth, renderHeight);
+ TraceLog(LOG_WARNING, "Downscale matrix generated, content will be rendered at: %i x %i", CORE.Window.render.width, CORE.Window.render.height);
}
- else if ((screenWidth < displayWidth) || (screenHeight < displayHeight))
+ else if ((CORE.Window.screen.width < CORE.Window.display.width) || (CORE.Window.screen.height < CORE.Window.display.height))
{
// Required screen size is smaller than display size
- TraceLog(LOG_INFO, "UPSCALING: Required screen size: %i x %i -> Display size: %i x %i", screenWidth, screenHeight, displayWidth, displayHeight);
+ TraceLog(LOG_INFO, "UPSCALING: Required screen size: %i x %i -> Display size: %i x %i", CORE.Window.screen.width, CORE.Window.screen.height, CORE.Window.display.width, CORE.Window.display.height);
// Upscaling to fit display with border-bars
- float displayRatio = (float)displayWidth/(float)displayHeight;
- float screenRatio = (float)screenWidth/(float)screenHeight;
+ float displayRatio = (float)CORE.Window.display.width/(float)CORE.Window.display.height;
+ float screenRatio = (float)CORE.Window.screen.width/(float)CORE.Window.screen.height;
if (displayRatio <= screenRatio)
{
- renderWidth = screenWidth;
- renderHeight = (int)round((float)screenWidth/displayRatio);
- renderOffsetX = 0;
- renderOffsetY = (renderHeight - screenHeight);
+ CORE.Window.render.width = CORE.Window.screen.width;
+ CORE.Window.render.height = (int)round((float)CORE.Window.screen.width/displayRatio);
+ CORE.Window.renderOffset.x = 0;
+ CORE.Window.renderOffset.y = (CORE.Window.render.height - CORE.Window.screen.height);
}
else
{
- renderWidth = (int)round((float)screenHeight*displayRatio);
- renderHeight = screenHeight;
- renderOffsetX = (renderWidth - screenWidth);
- renderOffsetY = 0;
+ CORE.Window.render.width = (int)round((float)CORE.Window.screen.height*displayRatio);
+ CORE.Window.render.height = CORE.Window.screen.height;
+ CORE.Window.renderOffset.x = (CORE.Window.render.width - CORE.Window.screen.width);
+ CORE.Window.renderOffset.y = 0;
}
}
- else // screen == display
+ else
{
- renderWidth = screenWidth;
- renderHeight = screenHeight;
- renderOffsetX = 0;
- renderOffsetY = 0;
+ CORE.Window.render.width = CORE.Window.screen.width;
+ CORE.Window.render.height = CORE.Window.screen.height;
+ CORE.Window.renderOffset.x = 0;
+ CORE.Window.renderOffset.y = 0;
}
}
@@ -3339,12 +3349,12 @@ static void InitTimer(void)
if (clock_gettime(CLOCK_MONOTONIC, &now) == 0) // Success
{
- baseTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec;
+ CORE.Time.base = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec;
}
else TraceLog(LOG_WARNING, "No hi-resolution timer available");
#endif
- previousTime = GetTime(); // Get time as double
+ CORE.Time.previous = GetTime(); // Get time as double
}
// Wait for some milliseconds (stop program execution)
@@ -3392,15 +3402,15 @@ static void Wait(float ms)
static bool GetKeyStatus(int key)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
- return glfwGetKey(window, key);
+ return glfwGetKey(CORE.Window.handle, key);
#elif defined(PLATFORM_ANDROID)
// NOTE: Android supports up to 260 keys
if (key < 0 || key > 260) return false;
- else return currentKeyState[key];
+ else return CORE.Input.Keyboard.currentKeyState[key];
#elif defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
// NOTE: Keys states are filled in PollInputEvents()
if (key < 0 || key > 511) return false;
- else return currentKeyState[key];
+ else return CORE.Input.Keyboard.currentKeyState[key];
#endif
}
@@ -3408,13 +3418,13 @@ static bool GetKeyStatus(int key)
static bool GetMouseButtonStatus(int button)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
- return glfwGetMouseButton(window, button);
+ return glfwGetMouseButton(CORE.Window.handle, button);
#elif defined(PLATFORM_ANDROID)
// TODO: Check for virtual mouse?
return false;
#elif defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
// NOTE: Mouse buttons states are filled in PollInputEvents()
- return currentMouseState[button];
+ return CORE.Input.Mouse.currentButtonState[button];
#endif
}
@@ -3521,53 +3531,53 @@ static void PollInputEvents(void)
#endif
// Reset key pressed registered
- keyPressedQueueCount = 0;
+ CORE.Input.Keyboard.keyPressedQueueCount = 0;
#if !defined(PLATFORM_RPI)
// Reset last gamepad button/axis registered state
- lastGamepadButtonPressed = -1;
- gamepadAxisCount = 0;
+ CORE.Input.Gamepad.lastButtonPressed = -1;
+ CORE.Input.Gamepad.axisCount = 0;
#endif
#if defined(PLATFORM_RPI)
// Register previous keys states
- for (int i = 0; i < 512; i++)previousKeyState[i] = currentKeyState[i];
+ for (int i = 0; i < 512; i++)CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
// Grab a keypress from the evdev fifo if avalable
- if (lastKeyPressedEvdev.Head != lastKeyPressedEvdev.Tail)
+ if (CORE.Input.Keyboard.lastKeyPressed.Head != CORE.Input.Keyboard.lastKeyPressed.Tail)
{
- keyPressedQueue[keyPressedQueueCount] = lastKeyPressedEvdev.Contents[lastKeyPressedEvdev.Tail]; // Read the key from the buffer
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = CORE.Input.Keyboard.lastKeyPressed.Contents[CORE.Input.Keyboard.lastKeyPressed.Tail]; // Read the key from the buffer
+ CORE.Input.Keyboard.keyPressedQueueCount++;
- lastKeyPressedEvdev.Tail = (lastKeyPressedEvdev.Tail + 1) & 0x07; // Increment the tail pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
+ CORE.Input.Keyboard.lastKeyPressed.Tail = (CORE.Input.Keyboard.lastKeyPressed.Tail + 1) & 0x07; // Increment the tail pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
}
// Register previous mouse states
- previousMouseWheelY = currentMouseWheelY;
- currentMouseWheelY = 0;
+ CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
+ CORE.Input.Mouse.currentWheelMove = 0;
for (int i = 0; i < 3; i++)
{
- previousMouseState[i] = currentMouseState[i];
- currentMouseState[i] = currentMouseStateEvdev[i];
+ CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
+ CORE.Input.Mouse.currentButtonState[i] = currentButtonStateEvdev[i];
}
#endif
#if defined(PLATFORM_UWP)
// Register previous keys states
- for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
+ for (int i = 0; i < 512; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
for (int i = 0; i < MAX_GAMEPADS; i++)
{
- if (gamepadReady[i])
+ if (CORE.Input.Gamepad.ready[i])
{
- for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k];
+ for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousState[i][k] = CORE.Input.Gamepad.currentState[i][k];
}
}
// Register previous mouse states
- previousMouseWheelY = currentMouseWheelY;
- currentMouseWheelY = 0;
- for (int i = 0; i < 3; i++) previousMouseState[i] = currentMouseState[i];
+ CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
+ CORE.Input.Mouse.currentWheelMove = 0;
+ for (int i = 0; i < 3; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
// Loop over pending messages
while (HasMessageFromUWP())
@@ -3649,40 +3659,40 @@ static void PollInputEvents(void)
default: break;
}
- if (actualKey > -1) currentKeyState[actualKey] = msg->paramChar0;
+ if (actualKey > -1) CORE.Input.Keyboard.currentKeyState[actualKey] = msg->paramChar0;
} break;
- case UWP_MSG_REGISTER_CLICK: currentMouseState[msg->paramInt0] = msg->paramChar0; break;
- case UWP_MSG_SCROLL_WHEEL_UPDATE: currentMouseWheelY += msg->paramInt0; break;
- case UWP_MSG_UPDATE_MOUSE_LOCATION: mousePosition = msg->paramVector0; break;
- case UWP_MSG_SET_GAMEPAD_ACTIVE: if (msg->paramInt0 < MAX_GAMEPADS) gamepadReady[msg->paramInt0] = msg->paramBool0; break;
+ case UWP_MSG_REGISTER_CLICK: CORE.Input.Mouse.currentButtonState[msg->paramInt0] = msg->paramChar0; break;
+ case UWP_MSG_SCROLL_WHEEL_UPDATE: CORE.Input.Mouse.currentWheelMove += msg->paramInt0; break;
+ case UWP_MSG_UPDATE_MOUSE_LOCATION: CORE.Input.Mouse.position = msg->paramVector0; break;
+ case UWP_MSG_SET_GAMEPAD_ACTIVE: if (msg->paramInt0 < MAX_GAMEPADS) CORE.Input.Gamepad.ready[msg->paramInt0] = msg->paramBool0; break;
case UWP_MSG_SET_GAMEPAD_BUTTON:
{
- if ((msg->paramInt0 < MAX_GAMEPADS) && (msg->paramInt1 < MAX_GAMEPAD_BUTTONS)) currentGamepadState[msg->paramInt0][msg->paramInt1] = msg->paramChar0;
+ if ((msg->paramInt0 < MAX_GAMEPADS) && (msg->paramInt1 < MAX_GAMEPAD_BUTTONS)) CORE.Input.Gamepad.currentState[msg->paramInt0][msg->paramInt1] = msg->paramChar0;
} break;
case UWP_MSG_SET_GAMEPAD_AXIS:
{
- if ((msg->paramInt0 < MAX_GAMEPADS) && (msg->paramInt1 < MAX_GAMEPAD_AXIS)) gamepadAxisState[msg->paramInt0][msg->paramInt1] = msg->paramFloat0;
+ if ((msg->paramInt0 < MAX_GAMEPADS) && (msg->paramInt1 < MAX_GAMEPAD_AXIS)) CORE.Input.Gamepad.axisState[msg->paramInt0][msg->paramInt1] = msg->paramFloat0;
// Register buttons for 2nd triggers
- currentGamepadState[msg->paramInt0][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(gamepadAxisState[msg->paramInt0][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1);
- currentGamepadState[msg->paramInt0][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(gamepadAxisState[msg->paramInt0][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1);
+ CORE.Input.Gamepad.currentState[msg->paramInt0][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[msg->paramInt0][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1);
+ CORE.Input.Gamepad.currentState[msg->paramInt0][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[msg->paramInt0][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1);
} break;
case UWP_MSG_SET_DISPLAY_DIMS:
{
- displayWidth = msg->paramVector0.x;
- displayHeight = msg->paramVector0.y;
+ CORE.Window.display.width = msg->paramVector0.x;
+ CORE.Window.display.height = msg->paramVector0.y;
} break;
case UWP_MSG_HANDLE_RESIZE:
{
- eglQuerySurface(display, surface, EGL_WIDTH, &screenWidth);
- eglQuerySurface(display, surface, EGL_HEIGHT, &screenHeight);
+ eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_WIDTH, &CORE.Window.screen.width);
+ eglQuerySurface(CORE.Window.device, CORE.Window.surface, EGL_HEIGHT, &CORE.Window.screen.height);
// If window is resized, viewport and projection matrix needs to be re-calculated
- rlViewport(0, 0, screenWidth, screenHeight); // Set viewport width and height
+ rlViewport(0, 0, CORE.Window.screen.width, CORE.Window.screen.height); // Set viewport width and height
rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix
rlLoadIdentity(); // Reset current matrix (PROJECTION)
- rlOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); // Orthographic projection mode with top-left corner at (0,0)
+ rlOrtho(0, CORE.Window.screen.width, CORE.Window.screen.height, 0, 0.0f, 1.0f); // Orthographic projection mode with top-left corner at (0,0)
rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
rlClearScreenBuffers(); // Clear screen buffers (color and depth)
@@ -3690,15 +3700,15 @@ static void PollInputEvents(void)
// Window size must be updated to be used on 3D mode to get new aspect ratio (BeginMode3D())
// NOTE: Be careful! GLFW3 will choose the closest fullscreen resolution supported by current monitor,
// for example, if reescaling back to 800x450 (desired), it could set 720x480 (closest fullscreen supported)
- currentWidth = screenWidth;
- currentHeight = screenHeight;
+ CORE.Window.currentFbo.width = CORE.Window.screen.width;
+ CORE.Window.currentFbo.height = CORE.Window.screen.height;
// NOTE: Postprocessing texture is not scaled to new size
- windowResized = true;
+ CORE.Window.resized = true;
} break;
- case UWP_MSG_SET_GAME_TIME: currentTime = msg->paramDouble0; break;
+ case UWP_MSG_SET_GAME_TIME: CORE.Time.current = msg->paramDouble0; break;
default: break;
}
@@ -3711,21 +3721,21 @@ static void PollInputEvents(void)
double mouseX;
double mouseY;
- glfwGetCursorPos(window, &mouseX, &mouseY);
+ glfwGetCursorPos(CORE.Window.handle, &mouseX, &mouseY);
- mousePosition.x = (float)mouseX;
- mousePosition.y = (float)mouseY;
+ CORE.Input.Mouse.position.x = (float)mouseX;
+ CORE.Input.Mouse.position.y = (float)mouseY;
// Keyboard input polling (automatically managed by GLFW3 through callback)
// Register previous keys states
- for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
+ for (int i = 0; i < 512; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
// Register previous mouse states
- for (int i = 0; i < 3; i++) previousMouseState[i] = currentMouseState[i];
+ for (int i = 0; i < 3; i++) CORE.Input.Mouse.previousButtonState[i] = CORE.Input.Mouse.currentButtonState[i];
- previousMouseWheelY = currentMouseWheelY;
- currentMouseWheelY = 0;
+ CORE.Input.Mouse.previousWheelMove = CORE.Input.Mouse.currentWheelMove;
+ CORE.Input.Mouse.currentWheelMove = 0;
#endif
#if defined(PLATFORM_DESKTOP)
@@ -3733,17 +3743,17 @@ static void PollInputEvents(void)
// NOTE: We do it here in case of disconnection
for (int i = 0; i < MAX_GAMEPADS; i++)
{
- if (glfwJoystickPresent(i)) gamepadReady[i] = true;
- else gamepadReady[i] = false;
+ if (glfwJoystickPresent(i)) CORE.Input.Gamepad.ready[i] = true;
+ else CORE.Input.Gamepad.ready[i] = false;
}
// Register gamepads buttons events
for (int i = 0; i < MAX_GAMEPADS; i++)
{
- if (gamepadReady[i]) // Check if gamepad is available
+ if (CORE.Input.Gamepad.ready[i]) // Check if gamepad is available
{
// Register previous gamepad states
- for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k];
+ for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousState[i][k] = CORE.Input.Gamepad.currentState[i][k];
// Get current gamepad state
// NOTE: There is no callback available, so we get it manually
@@ -3758,10 +3768,10 @@ static void PollInputEvents(void)
if (buttons[k] == GLFW_PRESS)
{
- currentGamepadState[i][button] = 1;
- lastGamepadButtonPressed = button;
+ CORE.Input.Gamepad.currentState[i][button] = 1;
+ CORE.Input.Gamepad.lastButtonPressed = button;
}
- else currentGamepadState[i][button] = 0;
+ else CORE.Input.Gamepad.currentState[i][button] = 0;
}
// Get current axis state
@@ -3770,18 +3780,18 @@ static void PollInputEvents(void)
for (int k = 0; (axes != NULL) && (k < GLFW_GAMEPAD_AXIS_LAST + 1) && (k < MAX_GAMEPAD_AXIS); k++)
{
const int axis = GetGamepadAxis(k);
- gamepadAxisState[i][axis] = axes[k];
+ CORE.Input.Gamepad.axisState[i][axis] = axes[k];
}
// Register buttons for 2nd triggers (because GLFW doesn't count these as buttons but rather axis)
- currentGamepadState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(gamepadAxisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1);
- currentGamepadState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(gamepadAxisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1);
+ CORE.Input.Gamepad.currentState[i][GAMEPAD_BUTTON_LEFT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_LEFT_TRIGGER] > 0.1);
+ CORE.Input.Gamepad.currentState[i][GAMEPAD_BUTTON_RIGHT_TRIGGER_2] = (char)(CORE.Input.Gamepad.axisState[i][GAMEPAD_AXIS_RIGHT_TRIGGER] > 0.1);
- gamepadAxisCount = GLFW_GAMEPAD_AXIS_LAST;
+ CORE.Input.Gamepad.axisCount = GLFW_GAMEPAD_AXIS_LAST;
}
}
- windowResized = false;
+ CORE.Window.resized = false;
#if defined(SUPPORT_EVENTS_WAITING)
glfwWaitEvents();
@@ -3800,7 +3810,7 @@ static void PollInputEvents(void)
for (int i = 0; (i < numGamepads) && (i < MAX_GAMEPADS); i++)
{
// Register previous gamepad button states
- for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k];
+ for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) CORE.Input.Gamepad.previousState[i][k] = CORE.Input.Gamepad.currentState[i][k];
EmscriptenGamepadEvent gamepadState;
@@ -3814,10 +3824,10 @@ static void PollInputEvents(void)
const GamepadButton button = GetGamepadButton(j);
if (gamepadState.digitalButton[j] == 1)
{
- currentGamepadState[i][button] = 1;
- lastGamepadButtonPressed = button;
+ CORE.Input.Gamepad.currentState[i][button] = 1;
+ CORE.Input.Gamepad.lastButtonPressed = button;
}
- else currentGamepadState[i][button] = 0;
+ else CORE.Input.Gamepad.currentState[i][button] = 0;
//TraceLog(LOG_DEBUG, "Gamepad %d, button %d: Digital: %d, Analog: %g", gamepadState.index, j, gamepadState.digitalButton[j], gamepadState.analogButton[j]);
}
@@ -3826,10 +3836,10 @@ static void PollInputEvents(void)
for (int j = 0; (j < gamepadState.numAxes) && (j < MAX_GAMEPAD_AXIS); j++)
{
const int axis = GetGamepadAxis(j);
- gamepadAxisState[i][axis] = gamepadState.axis[j];
+ CORE.Input.Gamepad.axisState[i][axis] = gamepadState.axis[j];
}
- gamepadAxisCount = gamepadState.numAxes;
+ CORE.Input.Gamepad.axisCount = gamepadState.numAxes;
}
}
#endif
@@ -3837,20 +3847,24 @@ static void PollInputEvents(void)
#if defined(PLATFORM_ANDROID)
// Register previous keys states
// NOTE: Android supports up to 260 keys
- for (int i = 0; i < 260; i++) previousKeyState[i] = currentKeyState[i];
+ for (int i = 0; i < 260; i++) CORE.Input.Keyboard.previousKeyState[i] = CORE.Input.Keyboard.currentKeyState[i];
+ // Android ALooper_pollAll() variables
+ int pollResult = 0;
+ int pollEvents = 0;
+
// Poll Events (registered events)
- // NOTE: Activity is paused if not enabled (appEnabled)
- while ((ident = ALooper_pollAll(appEnabled? 0 : -1, NULL, &events,(void**)&source)) >= 0)
+ // NOTE: Activity is paused if not enabled (CORE.Android.appEnabled)
+ while ((pollResult = ALooper_pollAll(CORE.Android.appEnabled? 0 : -1, NULL, &pollEvents, (void**)&CORE.Android.source)) >= 0)
{
// Process this event
- if (source != NULL) source->process(androidApp, source);
+ if (CORE.Android.source != NULL) CORE.Android.source->process(CORE.Android.app, CORE.Android.source);
// NOTE: Never close window, native activity is controlled by the system!
- if (androidApp->destroyRequested != 0)
+ if (CORE.Android.app->destroyRequested != 0)
{
- //windowShouldClose = true;
- //ANativeActivity_finish(androidApp->activity);
+ //CORE.Window.shouldClose = true;
+ //ANativeActivity_finish(CORE.Android.app->activity);
}
}
#endif
@@ -3869,11 +3883,11 @@ static void PollInputEvents(void)
static void SwapBuffers(void)
{
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
- glfwSwapBuffers(window);
+ glfwSwapBuffers(CORE.Window.handle);
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) || defined(PLATFORM_UWP)
- eglSwapBuffers(display, surface);
+ eglSwapBuffers(CORE.Window.device, CORE.Window.surface);
#endif
}
@@ -3887,15 +3901,15 @@ static void ErrorCallback(int error, const char *description)
// GLFW3 Srolling Callback, runs on mouse wheel
static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset)
{
- currentMouseWheelY = (int)yoffset;
+ CORE.Input.Mouse.currentWheelMove = (int)yoffset;
}
// GLFW3 Keyboard Callback, runs on key pressed
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
- if (key == exitKey && action == GLFW_PRESS)
+ if (key == CORE.Input.Keyboard.exitKey && action == GLFW_PRESS)
{
- glfwSetWindowShouldClose(window, GLFW_TRUE);
+ glfwSetWindowShouldClose(CORE.Window.handle, GLFW_TRUE);
// NOTE: Before closing window, while loop must be left!
}
@@ -3924,7 +3938,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
char path[512] = { 0 };
#if defined(PLATFORM_ANDROID)
- strcpy(path, internalDataPath);
+ strcpy(path, CORE.Android.internalDataPath);
strcat(path, TextFormat("./screenrec%03i.gif", screenshotCounter));
#else
strcpy(path, TextFormat("./screenrec%03i.gif", screenshotCounter));
@@ -3932,7 +3946,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
// NOTE: delay represents the time between frames in the gif, if we capture a gif frame every
// 10 game frames and each frame trakes 16.6ms (60fps), delay between gif frames should be ~16.6*10.
- GifBegin(path, screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false);
+ GifBegin(path, CORE.Window.screen.width, CORE.Window.screen.height, (int)(GetFrameTime()*10.0f), 8, false);
screenshotCounter++;
TraceLog(LOG_INFO, "Begin animated GIF recording: %s", TextFormat("screenrec%03i.gif", screenshotCounter));
@@ -3947,14 +3961,14 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i
}
#endif // SUPPORT_SCREEN_CAPTURE
}
- else currentKeyState[key] = action;
+ else CORE.Input.Keyboard.currentKeyState[key] = action;
}
// GLFW3 Mouse Button Callback, runs on mouse button pressed
static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
{
- previousMouseState[button] = currentMouseState[button];
- currentMouseState[button] = action;
+ CORE.Input.Mouse.previousButtonState[button] = CORE.Input.Mouse.currentButtonState[button];
+ CORE.Input.Mouse.currentButtonState[button] = action;
#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES)
// Process mouse events as touches to be able to use mouse-gestures
@@ -3975,7 +3989,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
// Register touch points position, only one point registered
gestureEvent.position[0] = GetMousePosition();
- // Normalize gestureEvent.position[0] for screenWidth and screenHeight
+ // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
gestureEvent.position[0].x /= (float)GetScreenWidth();
gestureEvent.position[0].y /= (float)GetScreenHeight();
@@ -4002,9 +4016,9 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y)
// Register touch points position, only one point registered
gestureEvent.position[0] = (Vector2){ (float)x, (float)y };
- touchPosition[0] = gestureEvent.position[0];
+ CORE.Input.Touch.position[0] = gestureEvent.position[0];
- // Normalize gestureEvent.position[0] for screenWidth and screenHeight
+ // Normalize gestureEvent.position[0] for CORE.Window.screen.width and CORE.Window.screen.height
gestureEvent.position[0].x /= (float)GetScreenWidth();
gestureEvent.position[0].y /= (float)GetScreenHeight();
@@ -4022,19 +4036,19 @@ static void CharCallback(GLFWwindow *window, unsigned int key)
// Ref: https://www.glfw.org/docs/latest/input_guide.html#input_char
// Check if there is space available in the queue
- if (keyPressedQueueCount < MAX_CHARS_QUEUE)
+ if (CORE.Input.Keyboard.keyPressedQueueCount < MAX_CHARS_QUEUE)
{
// Add character to the queue
- keyPressedQueue[keyPressedQueueCount] = key;
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = key;
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
}
// GLFW3 CursorEnter Callback, when cursor enters the window
static void CursorEnterCallback(GLFWwindow *window, int enter)
{
- if (enter == true) cursorOnScreen = true;
- else cursorOnScreen = false;
+ if (enter == true) CORE.Input.Mouse.cursorOnScreen = true;
+ else CORE.Input.Mouse.cursorOnScreen = false;
}
// GLFW3 WindowSize Callback, runs when window is resized
@@ -4044,21 +4058,21 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
SetupViewport(width, height); // Reset viewport and projection matrix for new size
// Set current screen size
- screenWidth = width;
- screenHeight = height;
- currentWidth = width;
- currentHeight = height;
+ CORE.Window.screen.width = width;
+ CORE.Window.screen.height = height;
+ CORE.Window.currentFbo.width = width;
+ CORE.Window.currentFbo.height = height;
// NOTE: Postprocessing texture is not scaled to new size
- windowResized = true;
+ CORE.Window.resized = true;
}
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow *window, int iconified)
{
- if (iconified) windowMinimized = true; // The window was iconified
- else windowMinimized = false; // The window was restored
+ if (iconified) CORE.Window.minimized = true; // The window was iconified
+ else CORE.Window.minimized = false; // The window was restored
}
// GLFW3 Window Drop Callback, runs when drop files into window
@@ -4068,15 +4082,15 @@ static void WindowDropCallback(GLFWwindow *window, int count, const char **paths
{
ClearDroppedFiles();
- dropFilesPath = (char **)RL_MALLOC(sizeof(char *)*count);
+ CORE.Window.dropFilesPath = (char **)RL_MALLOC(sizeof(char *)*count);
for (int i = 0; i < count; i++)
{
- dropFilesPath[i] = (char *)RL_MALLOC(sizeof(char)*MAX_FILEPATH_LENGTH);
- strcpy(dropFilesPath[i], paths[i]);
+ CORE.Window.dropFilesPath[i] = (char *)RL_MALLOC(sizeof(char)*MAX_FILEPATH_LENGTH);
+ strcpy(CORE.Window.dropFilesPath[i], paths[i]);
}
- dropFilesCount = count;
+ CORE.Window.dropFilesCount = count;
}
#endif
@@ -4095,23 +4109,23 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
{
if (app->window != NULL)
{
- if (contextRebindRequired)
+ if (CORE.Android.contextRebindRequired)
{
// Reset screen scaling to full display size
EGLint displayFormat;
- eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &displayFormat);
- ANativeWindow_setBuffersGeometry(app->window, renderWidth, renderHeight, displayFormat);
+ eglGetConfigAttrib(CORE.Window.device, CORE.Window.config, EGL_NATIVE_VISUAL_ID, &displayFormat);
+ ANativeWindow_setBuffersGeometry(app->window, CORE.Window.render.width, CORE.Window.render.height, displayFormat);
// Recreate display surface and re-attach OpenGL context
- surface = eglCreateWindowSurface(display, config, app->window, NULL);
- eglMakeCurrent(display, surface, surface, context);
+ CORE.Window.surface = eglCreateWindowSurface(CORE.Window.device, CORE.Window.config, app->window, NULL);
+ eglMakeCurrent(CORE.Window.device, CORE.Window.surface, CORE.Window.surface, CORE.Window.context);
- contextRebindRequired = false;
+ CORE.Android.contextRebindRequired = false;
}
else
{
// Init graphics device (display device and OpenGL context)
- InitGraphicsDevice(screenWidth, screenHeight);
+ InitGraphicsDevice(CORE.Window.screen.width, CORE.Window.screen.height);
// Init hi-res timer
InitTimer();
@@ -4120,6 +4134,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Load default font
// NOTE: External function (defined in module: text)
LoadFontDefault();
+ SetShapesTexture(GetFontDefault().texture, GetFontDefault().recs[95]);
#endif
// TODO: GPU assets reload in case of lost focus (lost context)
@@ -4141,13 +4156,13 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
} break;
case APP_CMD_GAINED_FOCUS:
{
- appEnabled = true;
+ CORE.Android.appEnabled = true;
//ResumeMusicStream();
} break;
case APP_CMD_PAUSE: break;
case APP_CMD_LOST_FOCUS:
{
- appEnabled = false;
+ CORE.Android.appEnabled = false;
//PauseMusicStream();
} break;
case APP_CMD_TERM_WINDOW:
@@ -4155,22 +4170,22 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
// Dettach OpenGL context and destroy display surface
// NOTE 1: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...)
// NOTE 2: In some cases (too many context loaded), OS could unload context automatically... :(
- eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroySurface(display, surface);
+ eglMakeCurrent(CORE.Window.device, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(CORE.Window.device, CORE.Window.surface);
- contextRebindRequired = true;
+ CORE.Android.contextRebindRequired = true;
} break;
case APP_CMD_SAVE_STATE: break;
case APP_CMD_STOP: break;
case APP_CMD_DESTROY:
{
// TODO: Finish activity?
- //ANativeActivity_finish(androidApp->activity);
+ //ANativeActivity_finish(CORE.Android.app->activity);
} break;
case APP_CMD_CONFIG_CHANGED:
{
- //AConfiguration_fromAssetManager(androidApp->config, androidApp->activity->assetManager);
- //print_cur_config(androidApp);
+ //AConfiguration_fromAssetManager(CORE.Android.app->config, CORE.Android.app->activity->assetManager);
+ //print_cur_config(CORE.Android.app);
// Check screen orientation here!
} break;
@@ -4189,12 +4204,12 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
if (type == AINPUT_EVENT_TYPE_MOTION)
{
// Get first touch position
- touchPosition[0].x = AMotionEvent_getX(event, 0);
- touchPosition[0].y = AMotionEvent_getY(event, 0);
+ CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
+ CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
// Get second touch position
- touchPosition[1].x = AMotionEvent_getX(event, 1);
- touchPosition[1].y = AMotionEvent_getY(event, 1);
+ CORE.Input.Touch.position[1].x = AMotionEvent_getX(event, 1);
+ CORE.Input.Touch.position[1].y = AMotionEvent_getY(event, 1);
// Useful functions for gamepad inputs:
//AMotionEvent_getAction()
@@ -4207,12 +4222,12 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
int32_t keycode = AKeyEvent_getKeyCode(event);
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
{
- currentKeyState[keycode] = 1; // Key down
+ CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
- keyPressedQueue[keyPressedQueueCount] = keycode;
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
- else currentKeyState[keycode] = 0; // Key up
+ else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
}
else if (type == AINPUT_EVENT_TYPE_KEY)
@@ -4224,12 +4239,12 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
// NOTE: Android key action is 0 for down and 1 for up
if (AKeyEvent_getAction(event) == AKEY_EVENT_ACTION_DOWN)
{
- currentKeyState[keycode] = 1; // Key down
+ CORE.Input.Keyboard.currentKeyState[keycode] = 1; // Key down
- keyPressedQueue[keyPressedQueueCount] = keycode;
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode;
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
- else currentKeyState[keycode] = 0; // Key up
+ else CORE.Input.Keyboard.currentKeyState[keycode] = 0; // Key up
if (keycode == AKEYCODE_POWER)
{
@@ -4280,7 +4295,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
- // Normalize gestureEvent.position[x] for screenWidth and screenHeight
+ // Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height
gestureEvent.position[0].x /= (float)GetScreenWidth();
gestureEvent.position[0].y /= (float)GetScreenHeight();
@@ -4295,11 +4310,11 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
if (flags == AMOTION_EVENT_ACTION_DOWN)
{
// Get first touch position
- touchPosition[0].x = AMotionEvent_getX(event, 0);
- touchPosition[0].y = AMotionEvent_getY(event, 0);
+ CORE.Input.Touch.position[0].x = AMotionEvent_getX(event, 0);
+ CORE.Input.Touch.position[0].y = AMotionEvent_getY(event, 0);
- touchPosition[0].x /= (float)GetScreenWidth();
- touchPosition[0].y /= (float)GetScreenHeight();
+ CORE.Input.Touch.position[0].x /= (float)GetScreenWidth();
+ CORE.Input.Touch.position[0].y /= (float)GetScreenHeight();
}
#endif
@@ -4310,25 +4325,23 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
#if defined(PLATFORM_WEB)
// Register fullscreen change events
-static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData)
+static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *event, void *userData)
{
- //isFullscreen: int e->isFullscreen
- //fullscreenEnabled: int e->fullscreenEnabled
- //fs element nodeName: (char *) e->nodeName
- //fs element id: (char *) e->id
- //Current element size: (int) e->elementWidth, (int) e->elementHeight // WARNING: Not canvas size but full page!
- //Screen size:(int) e->screenWidth, (int) e->screenHeight
+ //isFullscreen: int event->isFullscreen
+ //fullscreenEnabled: int event->fullscreenEnabled
+ //fs element nodeName: (char *) event->nodeName
+ //fs element id: (char *) event->id
+ //Current element size: (int) event->elementWidth, (int) event->elementHeight
+ //Screen size:(int) event->screenWidth, (int) event->screenHeight
- if (e->isFullscreen)
+ if (event->isFullscreen)
{
- TraceLog(LOG_INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight);
+ TraceLog(LOG_INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight);
}
else
{
- TraceLog(LOG_INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight);
+ TraceLog(LOG_INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", event->elementWidth, event->elementHeight, event->screenWidth, event->screenHeight);
}
-
- TraceLog(LOG_INFO, "Canvas resize?");
// TODO: Depending on scaling factor (screen vs element), calculate factor to scale mouse/touch input
@@ -4350,7 +4363,7 @@ static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboar
static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
// Lock mouse pointer when click on screen
- if ((eventType == EMSCRIPTEN_EVENT_CLICK) && toggleCursorLock)
+ if ((eventType == EMSCRIPTEN_EVENT_CLICK) && CORE.Input.Mouse.cursorLockRequired)
{
EmscriptenPointerlockChangeEvent plce;
emscripten_get_pointerlock_status(&plce);
@@ -4363,7 +4376,7 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent
//if (plce.isActive) TraceLog(LOG_WARNING, "Pointer lock exit did not work!");
}
- toggleCursorLock = false;
+ CORE.Input.Mouse.cursorLockRequired = false;
}
return 0;
@@ -4393,17 +4406,19 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY };
double canvasWidth, canvasHeight;
+ // NOTE: emscripten_get_canvas_element_size() returns canvas.width and canvas.height but
+ // we are looking for actual CSS size: canvas.style.width and canvas.style.height
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
- // Normalize gestureEvent.position[x] for screenWidth and screenHeight
+ // Normalize gestureEvent.position[x] for CORE.Window.screen.width and CORE.Window.screen.height
gestureEvent.position[0].x *= ((float)GetScreenWidth()/(float)canvasWidth);
gestureEvent.position[0].y *= ((float)GetScreenHeight()/(float)canvasHeight);
gestureEvent.position[1].x *= ((float)GetScreenWidth()/(float)canvasWidth);
gestureEvent.position[1].y *= ((float)GetScreenHeight()/(float)canvasHeight);
- touchPosition[0] = gestureEvent.position[0];
- touchPosition[1] = gestureEvent.position[1];
+ CORE.Input.Touch.position[0] = gestureEvent.position[0];
+ CORE.Input.Touch.position[1] = gestureEvent.position[1];
// Gesture data is sent to gestures system for processing
ProcessGestureEvent(gestureEvent);
@@ -4412,15 +4427,15 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART)
{
// Get first touch position
- touchPosition[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
+ CORE.Input.Touch.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
double canvasWidth, canvasHeight;
//EMSCRIPTEN_RESULT res = emscripten_get_canvas_element_size("#canvas", &canvasWidth, &canvasHeight);
emscripten_get_element_css_size("#canvas", &canvasWidth, &canvasHeight);
// Normalize gestureEvent.position[x] for screenWidth and screenHeight
- gestureEvent.position[0].x *= ((float)GetScreenWidth()/(float)canvasWidth);
- gestureEvent.position[0].y *= ((float)GetScreenHeight()/(float)canvasHeight);
+ CORE.Input.Touch.position[0].x *= ((float)GetScreenWidth()/(float)canvasWidth);
+ CORE.Input.Touch.position[0].y *= ((float)GetScreenHeight()/(float)canvasHeight);
}
#endif
@@ -4439,8 +4454,8 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
for (int i = 0; i < gamepadEvent->numButtons; ++i) TraceLog(LOG_DEBUG, "Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
*/
- if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) gamepadReady[gamepadEvent->index] = true;
- else gamepadReady[gamepadEvent->index] = false;
+ if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) CORE.Input.Gamepad.ready[gamepadEvent->index] = true;
+ else CORE.Input.Gamepad.ready[gamepadEvent->index] = false;
// TODO: Test gamepadEvent->index
@@ -4462,8 +4477,8 @@ static void InitKeyboard(void)
// Save terminal keyboard settings and reconfigure terminal with new settings
struct termios keyboardNewSettings;
- tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings
- keyboardNewSettings = defaultKeyboardSettings;
+ tcgetattr(STDIN_FILENO, &CORE.Input.Keyboard.defaultSettings); // Get current keyboard settings
+ keyboardNewSettings = CORE.Input.Keyboard.defaultSettings;
// New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing
// NOTE: ISIG controls if ^C and ^Z generate break signals or not
@@ -4478,7 +4493,7 @@ static void InitKeyboard(void)
// NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE
// Save old keyboard mode to restore it at the end
- if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0)
+ if (ioctl(STDIN_FILENO, KDGKBMODE, &CORE.Input.Keyboard.defaultMode) < 0)
{
// NOTE: It could mean we are using a remote keyboard through ssh!
TraceLog(LOG_WARNING, "Could not change keyboard mode (SSH keyboard?)");
@@ -4511,10 +4526,10 @@ static void ProcessKeyboard(void)
bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call
// Reset pressed keys array (it will be filled below)
- for (int i = 0; i < 512; i++) currentKeyState[i] = 0;
+ for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyState[i] = 0;
// Check keys from event input workers (This is the new keyboard reading method)
- for (int i = 0; i < 512; i++) currentKeyState[i] = currentKeyStateEvdev[i];
+ //for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyState[i] = CORE.Input.Keyboard.currentKeyStateEvdev[i];
// Fill all read bytes (looking for keys)
for (int i = 0; i < bufferByteCount; i++)
@@ -4526,7 +4541,7 @@ static void ProcessKeyboard(void)
if (keysBuffer[i] == 0x1b)
{
// Detect ESC to stop program
- if (bufferByteCount == 1) currentKeyState[256] = 1; // raylib key: KEY_ESCAPE
+ if (bufferByteCount == 1) CORE.Input.Keyboard.currentKeyState[256] = 1; // raylib key: KEY_ESCAPE
else
{
if (keysBuffer[i + 1] == 0x5b) // Special function key
@@ -4536,18 +4551,18 @@ static void ProcessKeyboard(void)
// Process special function keys (F1 - F12)
switch (keysBuffer[i + 3])
{
- case 0x41: currentKeyState[290] = 1; break; // raylib KEY_F1
- case 0x42: currentKeyState[291] = 1; break; // raylib KEY_F2
- case 0x43: currentKeyState[292] = 1; break; // raylib KEY_F3
- case 0x44: currentKeyState[293] = 1; break; // raylib KEY_F4
- case 0x45: currentKeyState[294] = 1; break; // raylib KEY_F5
- case 0x37: currentKeyState[295] = 1; break; // raylib KEY_F6
- case 0x38: currentKeyState[296] = 1; break; // raylib KEY_F7
- case 0x39: currentKeyState[297] = 1; break; // raylib KEY_F8
- case 0x30: currentKeyState[298] = 1; break; // raylib KEY_F9
- case 0x31: currentKeyState[299] = 1; break; // raylib KEY_F10
- case 0x33: currentKeyState[300] = 1; break; // raylib KEY_F11
- case 0x34: currentKeyState[301] = 1; break; // raylib KEY_F12
+ case 0x41: CORE.Input.Keyboard.currentKeyState[290] = 1; break; // raylib KEY_F1
+ case 0x42: CORE.Input.Keyboard.currentKeyState[291] = 1; break; // raylib KEY_F2
+ case 0x43: CORE.Input.Keyboard.currentKeyState[292] = 1; break; // raylib KEY_F3
+ case 0x44: CORE.Input.Keyboard.currentKeyState[293] = 1; break; // raylib KEY_F4
+ case 0x45: CORE.Input.Keyboard.currentKeyState[294] = 1; break; // raylib KEY_F5
+ case 0x37: CORE.Input.Keyboard.currentKeyState[295] = 1; break; // raylib KEY_F6
+ case 0x38: CORE.Input.Keyboard.currentKeyState[296] = 1; break; // raylib KEY_F7
+ case 0x39: CORE.Input.Keyboard.currentKeyState[297] = 1; break; // raylib KEY_F8
+ case 0x30: CORE.Input.Keyboard.currentKeyState[298] = 1; break; // raylib KEY_F9
+ case 0x31: CORE.Input.Keyboard.currentKeyState[299] = 1; break; // raylib KEY_F10
+ case 0x33: CORE.Input.Keyboard.currentKeyState[300] = 1; break; // raylib KEY_F11
+ case 0x34: CORE.Input.Keyboard.currentKeyState[301] = 1; break; // raylib KEY_F12
default: break;
}
@@ -4558,10 +4573,10 @@ static void ProcessKeyboard(void)
{
switch (keysBuffer[i + 2])
{
- case 0x41: currentKeyState[265] = 1; break; // raylib KEY_UP
- case 0x42: currentKeyState[264] = 1; break; // raylib KEY_DOWN
- case 0x43: currentKeyState[262] = 1; break; // raylib KEY_RIGHT
- case 0x44: currentKeyState[263] = 1; break; // raylib KEY_LEFT
+ case 0x41: CORE.Input.Keyboard.currentKeyState[265] = 1; break; // raylib KEY_UP
+ case 0x42: CORE.Input.Keyboard.currentKeyState[264] = 1; break; // raylib KEY_DOWN
+ case 0x43: CORE.Input.Keyboard.currentKeyState[262] = 1; break; // raylib KEY_RIGHT
+ case 0x44: CORE.Input.Keyboard.currentKeyState[263] = 1; break; // raylib KEY_LEFT
default: break;
}
@@ -4574,17 +4589,17 @@ static void ProcessKeyboard(void)
}
else if (keysBuffer[i] == 0x0a) // raylib KEY_ENTER (don't mix with <linux/input.h> KEY_*)
{
- currentKeyState[257] = 1;
+ CORE.Input.Keyboard.currentKeyState[257] = 1;
- keyPressedQueue[keyPressedQueueCount] = 257; // Add keys pressed into queue
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 257; // Add keys pressed into queue
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
else if (keysBuffer[i] == 0x7f) // raylib KEY_BACKSPACE
{
- currentKeyState[259] = 1;
+ CORE.Input.Keyboard.currentKeyState[259] = 1;
- keyPressedQueue[keyPressedQueueCount] = 257; // Add keys pressed into queue
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = 257; // Add keys pressed into queue
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
else
{
@@ -4593,21 +4608,21 @@ static void ProcessKeyboard(void)
// Translate lowercase a-z letters to A-Z
if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122))
{
- currentKeyState[(int)keysBuffer[i] - 32] = 1;
+ CORE.Input.Keyboard.currentKeyState[(int)keysBuffer[i] - 32] = 1;
}
- else currentKeyState[(int)keysBuffer[i]] = 1;
+ else CORE.Input.Keyboard.currentKeyState[(int)keysBuffer[i]] = 1;
- keyPressedQueue[keyPressedQueueCount] = keysBuffer[i]; // Add keys pressed into queue
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keysBuffer[i]; // Add keys pressed into queue
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
}
// Check exit key (same functionality as GLFW3 KeyCallback())
- if (currentKeyState[exitKey] == 1) windowShouldClose = true;
+ if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true;
#if defined(SUPPORT_SCREEN_CAPTURE)
// Check screen capture key (raylib key: KEY_F12)
- if (currentKeyState[301] == 1)
+ if (CORE.Input.Keyboard.currentKeyState[301] == 1)
{
TakeScreenshot(FormatText("screenshot%03i.png", screenshotCounter));
screenshotCounter++;
@@ -4619,10 +4634,10 @@ static void ProcessKeyboard(void)
static void RestoreKeyboard(void)
{
// Reset to default keyboard settings
- tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings);
+ tcsetattr(STDIN_FILENO, TCSANOW, &CORE.Input.Keyboard.defaultSettings);
// Reconfigure keyboard to default mode
- ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode);
+ ioctl(STDIN_FILENO, KDSKBMODE, CORE.Input.Keyboard.defaultMode);
}
#endif //SUPPORT_SSH_KEYBOARD_RPI
@@ -4636,14 +4651,14 @@ static void InitEvdevInput(void)
// Reset variables
for (int i = 0; i < MAX_TOUCH_POINTS; ++i)
{
- touchPosition[i].x = -1;
- touchPosition[i].y = -1;
+ CORE.Input.Touch.position[i].x = -1;
+ CORE.Input.Touch.position[i].y = -1;
}
// Reset keypress buffer
- lastKeyPressedEvdev.Head = 0;
- lastKeyPressedEvdev.Tail = 0;
+ CORE.Input.Keyboard.lastKeyPressed.Head = 0;
+ CORE.Input.Keyboard.lastKeyPressed.Tail = 0;
// Reset keyboard key state
- for (int i = 0; i < 512; i++) currentKeyStateEvdev[i] = 0;
+ for (int i = 0; i < 512; i++) CORE.Input.Keyboard.currentKeyStateEvdev[i] = 0;
// Open the linux directory of "/dev/input"
directory = opendir(DEFAULT_EVDEV_PATH);
@@ -4690,9 +4705,9 @@ static void EventThreadSpawn(char *device)
// Open the device and allocate worker
//-------------------------------------------------------------------------------------------------------
// Find a free spot in the workers array
- for (int i = 0; i < sizeof(eventWorkers)/sizeof(InputEventWorker); ++i)
+ for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{
- if (eventWorkers[i].threadId == 0)
+ if (CORE.Input.eventWorker[i].threadId == 0)
{
freeWorkerId = i;
break;
@@ -4702,7 +4717,7 @@ static void EventThreadSpawn(char *device)
// Select the free worker from array
if (freeWorkerId >= 0)
{
- worker = &(eventWorkers[freeWorkerId]); // Grab a pointer to the worker
+ worker = &(CORE.Input.eventWorker[freeWorkerId]); // Grab a pointer to the worker
memset(worker, 0, sizeof(InputEventWorker)); // Clear the worker
}
else
@@ -4836,21 +4851,21 @@ static void EventThreadSpawn(char *device)
// Find touchscreen with the highest index
int maxTouchNumber = -1;
- for (int i = 0; i < sizeof(eventWorkers)/sizeof(InputEventWorker); ++i)
+ for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{
- if (eventWorkers[i].isTouch && (eventWorkers[i].eventNum > maxTouchNumber)) maxTouchNumber = eventWorkers[i].eventNum;
+ if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum > maxTouchNumber)) maxTouchNumber = CORE.Input.eventWorker[i].eventNum;
}
// Find toucnscreens with lower indexes
- for (int i = 0; i < sizeof(eventWorkers)/sizeof(InputEventWorker); ++i)
+ for (int i = 0; i < sizeof(CORE.Input.eventWorker)/sizeof(InputEventWorker); ++i)
{
- if (eventWorkers[i].isTouch && (eventWorkers[i].eventNum < maxTouchNumber))
+ if (CORE.Input.eventWorker[i].isTouch && (CORE.Input.eventWorker[i].eventNum < maxTouchNumber))
{
- if (eventWorkers[i].threadId != 0)
+ if (CORE.Input.eventWorker[i].threadId != 0)
{
TraceLog(LOG_WARNING, "Duplicate touchscreen found, killing touchscreen on event: %d", i);
- pthread_cancel(eventWorkers[i].threadId);
- close(eventWorkers[i].fd);
+ pthread_cancel(CORE.Input.eventWorker[i].threadId);
+ close(CORE.Input.eventWorker[i].fd);
}
}
}
@@ -4890,7 +4905,7 @@ static void *EventThread(void *arg)
bool gestureUpdate = false;
int keycode;
- while (!windowShouldClose)
+ while (!CORE.Window.shouldClose)
{
// Try to read data from the device and only continue if successful
if (read(worker->fd, &event, sizeof(event)) == (int)sizeof(event))
@@ -4900,8 +4915,8 @@ static void *EventThread(void *arg)
{
if (event.code == REL_X)
{
- mousePosition.x += event.value;
- touchPosition[0].x = mousePosition.x;
+ CORE.Input.Mouse.position.x += event.value;
+ CORE.Input.Touch.position[0].x = CORE.Input.Mouse.position.x;
#if defined(SUPPORT_GESTURES_SYSTEM)
touchAction = TOUCH_MOVE;
@@ -4911,8 +4926,8 @@ static void *EventThread(void *arg)
if (event.code == REL_Y)
{
- mousePosition.y += event.value;
- touchPosition[0].y = mousePosition.y;
+ CORE.Input.Mouse.position.y += event.value;
+ CORE.Input.Touch.position[0].y = CORE.Input.Mouse.position.y;
#if defined(SUPPORT_GESTURES_SYSTEM)
touchAction = TOUCH_MOVE;
@@ -4920,7 +4935,7 @@ static void *EventThread(void *arg)
#endif
}
- if (event.code == REL_WHEEL) currentMouseWheelY += event.value;
+ if (event.code == REL_WHEEL) CORE.Input.Mouse.currentWheelMove += event.value;
}
// Absolute movement parsing
@@ -4929,7 +4944,7 @@ static void *EventThread(void *arg)
// Basic movement
if (event.code == ABS_X)
{
- mousePosition.x = (event.value - worker->absRange.x)*screenWidth/worker->absRange.width; // Scale acording to absRange
+ CORE.Input.Mouse.position.x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
#if defined(SUPPORT_GESTURES_SYSTEM)
touchAction = TOUCH_MOVE;
@@ -4939,7 +4954,7 @@ static void *EventThread(void *arg)
if (event.code == ABS_Y)
{
- mousePosition.y = (event.value - worker->absRange.y)*screenHeight/worker->absRange.height; // Scale acording to absRange
+ CORE.Input.Mouse.position.y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
#if defined(SUPPORT_GESTURES_SYSTEM)
touchAction = TOUCH_MOVE;
@@ -4952,12 +4967,12 @@ static void *EventThread(void *arg)
if (event.code == ABS_MT_POSITION_X)
{
- if (worker->touchSlot < MAX_TOUCH_POINTS) touchPosition[worker->touchSlot].x = (event.value - worker->absRange.x)*screenWidth/worker->absRange.width; // Scale acording to absRange
+ if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].x = (event.value - worker->absRange.x)*CORE.Window.screen.width/worker->absRange.width; // Scale acording to absRange
}
if (event.code == ABS_MT_POSITION_Y)
{
- if (worker->touchSlot < MAX_TOUCH_POINTS) touchPosition[worker->touchSlot].y = (event.value - worker->absRange.y)*screenHeight/worker->absRange.height; // Scale acording to absRange
+ if (worker->touchSlot < MAX_TOUCH_POINTS) CORE.Input.Touch.position[worker->touchSlot].y = (event.value - worker->absRange.y)*CORE.Window.screen.height/worker->absRange.height; // Scale acording to absRange
}
if (event.code == ABS_MT_TRACKING_ID)
@@ -4965,8 +4980,8 @@ static void *EventThread(void *arg)
if ((event.value < 0) && (worker->touchSlot < MAX_TOUCH_POINTS))
{
// Touch has ended for this point
- touchPosition[worker->touchSlot].x = -1;
- touchPosition[worker->touchSlot].y = -1;
+ CORE.Input.Touch.position[worker->touchSlot].x = -1;
+ CORE.Input.Touch.position[worker->touchSlot].y = -1;
}
}
}
@@ -4977,7 +4992,7 @@ static void *EventThread(void *arg)
// Mouse button parsing
if ((event.code == BTN_TOUCH) || (event.code == BTN_LEFT))
{
- currentMouseStateEvdev[MOUSE_LEFT_BUTTON] = event.value;
+ currentButtonStateEvdev[MOUSE_LEFT_BUTTON] = event.value;
#if defined(SUPPORT_GESTURES_SYSTEM)
if (event.value > 0) touchAction = TOUCH_DOWN;
@@ -4986,9 +5001,9 @@ static void *EventThread(void *arg)
#endif
}
- if (event.code == BTN_RIGHT) currentMouseStateEvdev[MOUSE_RIGHT_BUTTON] = event.value;
+ if (event.code == BTN_RIGHT) currentButtonStateEvdev[MOUSE_RIGHT_BUTTON] = event.value;
- if (event.code == BTN_MIDDLE) currentMouseStateEvdev[MOUSE_MIDDLE_BUTTON] = event.value;
+ if (event.code == BTN_MIDDLE) currentButtonStateEvdev[MOUSE_MIDDLE_BUTTON] = event.value;
// Keyboard button parsing
if ((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
@@ -4996,37 +5011,37 @@ static void *EventThread(void *arg)
keycode = keymap_US[event.code & 0xFF]; // The code we get is a scancode so we look up the apropriate keycode
// Make sure we got a valid keycode
- if ((keycode > 0) && (keycode < sizeof(currentKeyState)))
+ if ((keycode > 0) && (keycode < sizeof(CORE.Input.Keyboard.currentKeyState)))
{
/* Disabled buffer !!
// Store the key information for raylib to later use
- currentKeyStateEvdev[keycode] = event.value;
+ CORE.Input.Keyboard.currentKeyState[keycode] = event.value;
if (event.value > 0)
{
// Add the key int the fifo
- lastKeyPressedEvdev.Contents[lastKeyPressedEvdev.Head] = keycode; // Put the data at the front of the fifo snake
- lastKeyPressedEvdev.Head = (lastKeyPressedEvdev.Head + 1) & 0x07; // Increment the head pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
+ CORE.Input.Keyboard.lastKeyPressed.Contents[CORE.Input.Keyboard.lastKeyPressed.Head] = keycode; // Put the data at the front of the fifo snake
+ CORE.Input.Keyboard.lastKeyPressed.Head = (CORE.Input.Keyboard.lastKeyPressed.Head + 1) & 0x07; // Increment the head pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
// TODO: This fifo is not fully threadsafe with multiple writers, so multiple keyboards hitting a key at the exact same time could miss a key (double write to head before it was incremented)
}
*/
- currentKeyState[keycode] = event.value;
+ CORE.Input.Keyboard.currentKeyState[keycode] = event.value;
if (event.value == 1)
{
- keyPressedQueue[keyPressedQueueCount] = keycode; // Register last key pressed
- keyPressedQueueCount++;
+ CORE.Input.Keyboard.keyPressedQueue[CORE.Input.Keyboard.keyPressedQueueCount] = keycode; // Register last key pressed
+ CORE.Input.Keyboard.keyPressedQueueCount++;
}
#if defined(SUPPORT_SCREEN_CAPTURE)
// Check screen capture key (raylib key: KEY_F12)
- if (currentKeyState[301] == 1)
+ if (CORE.Input.Keyboard.currentKeyState[301] == 1)
{
TakeScreenshot(FormatText("screenshot%03i.png", screenshotCounter));
screenshotCounter++;
}
#endif
- if (currentKeyState[exitKey] == 1) windowShouldClose = true;
+ if (CORE.Input.Keyboard.currentKeyState[CORE.Input.Keyboard.exitKey] == 1) CORE.Window.shouldClose = true;
TraceLog(LOG_DEBUG, "KEY%s ScanCode: %4i KeyCode: %4i",event.value == 0 ? "UP":"DOWN", event.code, keycode);
}
@@ -5034,11 +5049,11 @@ static void *EventThread(void *arg)
}
// Screen confinement
- if (mousePosition.x < 0) mousePosition.x = 0;
- if (mousePosition.x > screenWidth/mouseScale.x) mousePosition.x = screenWidth/mouseScale.x;
+ if (CORE.Input.Mouse.position.x < 0) CORE.Input.Mouse.position.x = 0;
+ if (CORE.Input.Mouse.position.x > CORE.Window.screen.width/CORE.Input.Mouse.scale.x) CORE.Input.Mouse.position.x = CORE.Window.screen.width/CORE.Input.Mouse.scale.x;
- if (mousePosition.y < 0) mousePosition.y = 0;
- if (mousePosition.y > screenHeight/mouseScale.y) mousePosition.y = screenHeight/mouseScale.y;
+ if (CORE.Input.Mouse.position.y < 0) CORE.Input.Mouse.position.y = 0;
+ if (CORE.Input.Mouse.position.y > CORE.Window.screen.height/CORE.Input.Mouse.scale.y) CORE.Input.Mouse.position.y = CORE.Window.screen.height/CORE.Input.Mouse.scale.y;
// Gesture update
if (gestureUpdate)
@@ -5049,20 +5064,20 @@ static void *EventThread(void *arg)
gestureEvent.pointCount = 0;
gestureEvent.touchAction = touchAction;
- if (touchPosition[0].x >= 0) gestureEvent.pointCount++;
- if (touchPosition[1].x >= 0) gestureEvent.pointCount++;
- if (touchPosition[2].x >= 0) gestureEvent.pointCount++;
- if (touchPosition[3].x >= 0) gestureEvent.pointCount++;
+ if (CORE.Input.Touch.position[0].x >= 0) gestureEvent.pointCount++;
+ if (CORE.Input.Touch.position[1].x >= 0) gestureEvent.pointCount++;
+ if (CORE.Input.Touch.position[2].x >= 0) gestureEvent.pointCount++;
+ if (CORE.Input.Touch.position[3].x >= 0) gestureEvent.pointCount++;
gestureEvent.pointerId[0] = 0;
gestureEvent.pointerId[1] = 1;
gestureEvent.pointerId[2] = 2;
gestureEvent.pointerId[3] = 3;
- gestureEvent.position[0] = touchPosition[0];
- gestureEvent.position[1] = touchPosition[1];
- gestureEvent.position[2] = touchPosition[2];
- gestureEvent.position[3] = touchPosition[3];
+ gestureEvent.position[0] = CORE.Input.Touch.position[0];
+ gestureEvent.position[1] = CORE.Input.Touch.position[1];
+ gestureEvent.position[2] = CORE.Input.Touch.position[2];
+ gestureEvent.position[3] = CORE.Input.Touch.position[3];
ProcessGestureEvent(gestureEvent);
#endif
@@ -5088,19 +5103,19 @@ static void InitGamepad(void)
{
sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i);
- if ((gamepadStream[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0)
+ if ((CORE.Input.Gamepad.streamId[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0)
{
// NOTE: Only show message for first gamepad
if (i == 0) TraceLog(LOG_WARNING, "Gamepad device could not be opened, no gamepad available");
}
else
{
- gamepadReady[i] = true;
+ CORE.Input.Gamepad.ready[i] = true;
// NOTE: Only create one thread
if (i == 0)
{
- int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL);
+ int error = pthread_create(&CORE.Input.Gamepad.threadId, NULL, &GamepadThread, NULL);
if (error != 0) TraceLog(LOG_WARNING, "Error creating gamepad input event thread");
else TraceLog(LOG_INFO, "Gamepad device initialized successfully");
@@ -5126,11 +5141,11 @@ static void *GamepadThread(void *arg)
// Read gamepad event
struct js_event gamepadEvent;
- while (!windowShouldClose)
+ while (!CORE.Window.shouldClose)
{
for (int i = 0; i < MAX_GAMEPADS; i++)
{
- if (read(gamepadStream[i], &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
+ if (read(CORE.Input.Gamepad.streamId[i], &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event))
{
gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events
@@ -5142,10 +5157,10 @@ static void *GamepadThread(void *arg)
if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS)
{
// 1 - button pressed, 0 - button released
- currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value;
+ CORE.Input.Gamepad.currentState[i][gamepadEvent.number] = (int)gamepadEvent.value;
- if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number;
- else lastGamepadButtonPressed = -1;
+ if ((int)gamepadEvent.value == 1) CORE.Input.Gamepad.lastButtonPressed = gamepadEvent.number;
+ else CORE.Input.Gamepad.lastButtonPressed = -1;
}
}
else if (gamepadEvent.type == JS_EVENT_AXIS)
@@ -5155,7 +5170,7 @@ static void *GamepadThread(void *arg)
if (gamepadEvent.number < MAX_GAMEPAD_AXIS)
{
// NOTE: Scaling of gamepadEvent.value to get values between -1..1
- gamepadAxisState[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
+ CORE.Input.Gamepad.axisState[i][gamepadEvent.number] = (float)gamepadEvent.value/32768;
}
}
}
diff --git a/src/gestures.h b/src/gestures.h
index 38df8905..07de3137 100644
--- a/src/gestures.h
+++ b/src/gestures.h
@@ -149,75 +149,76 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199309L // Required for CLOCK_MONOTONIC if compiled with c99 without gnu ext.
#endif
- #include <sys/time.h> // Required for: timespec
- #include <time.h> // Required for: clock_gettime()
+ #include <sys/time.h> // Required for: timespec
+ #include <time.h> // Required for: clock_gettime()
- #include <math.h> // Required for: atan2(), sqrt()
- #include <stdint.h> // Required for: uint64_t
+ #include <math.h> // Required for: atan2(), sqrt()
+ #include <stdint.h> // Required for: uint64_t
#endif
-#if defined(__APPLE__) // macOS also defines __MACH__
- #include <mach/clock.h> // Required for: clock_get_time()
- #include <mach/mach.h> // Required for: mach_timespec_t
+#if defined(__APPLE__) // macOS also defines __MACH__
+ #include <mach/clock.h> // Required for: clock_get_time()
+ #include <mach/mach.h> // Required for: mach_timespec_t
#endif
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
-#define FORCE_TO_SWIPE 0.0005f // Measured in normalized screen units/time
-#define MINIMUM_DRAG 0.015f // Measured in normalized screen units (0.0f to 1.0f)
-#define MINIMUM_PINCH 0.005f // Measured in normalized screen units (0.0f to 1.0f)
-#define TAP_TIMEOUT 300 // Time in milliseconds
-#define PINCH_TIMEOUT 300 // Time in milliseconds
-#define DOUBLETAP_RANGE 0.03f // Measured in normalized screen units (0.0f to 1.0f)
+#define FORCE_TO_SWIPE 0.0005f // Measured in normalized screen units/time
+#define MINIMUM_DRAG 0.015f // Measured in normalized screen units (0.0f to 1.0f)
+#define MINIMUM_PINCH 0.005f // Measured in normalized screen units (0.0f to 1.0f)
+#define TAP_TIMEOUT 300 // Time in milliseconds
+#define PINCH_TIMEOUT 300 // Time in milliseconds
+#define DOUBLETAP_RANGE 0.03f // Measured in normalized screen units (0.0f to 1.0f)
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
-// ...
+
+typedef struct {
+ int current; // Current detected gesture
+ unsigned int enabledFlags; // Enabled gestures flags
+ struct {
+ int firstId; // Touch id for first touch point
+ int pointCount; // Touch points counter
+ double eventTime; // Time stamp when an event happened
+ Vector2 upPosition; // Touch up position
+ Vector2 downPositionA; // First touch down position
+ Vector2 downPositionB; // Second touch down position
+ Vector2 downDragPosition; // Touch drag position
+ Vector2 moveDownPositionA; // First touch down position on move
+ Vector2 moveDownPositionB; // Second touch down position on move
+ int tapCounter; // TAP counter (one tap implies TOUCH_DOWN and TOUCH_UP actions)
+ } Touch;
+ struct {
+ bool resetRequired; // HOLD reset to get first touch point again
+ double timeDuration; // HOLD duration in milliseconds
+ } Hold;
+ struct {
+ Vector2 vector; // DRAG vector (between initial and current position)
+ float angle; // DRAG angle (relative to x-axis)
+ float distance; // DRAG distance (from initial touch point to final) (normalized [0..1])
+ float intensity; // DRAG intensity, how far why did the DRAG (pixels per frame)
+ } Drag;
+ struct {
+ bool start; // SWIPE used to define when start measuring GESTURES.Swipe.timeDuration
+ double timeDuration; // SWIPE time to calculate drag intensity
+ } Swipe;
+ struct {
+ Vector2 vector; // PINCH vector (between first and second touch points)
+ float angle; // PINCH angle (relative to x-axis)
+ float distance; // PINCH displacement distance (normalized [0..1])
+ } Pinch;
+} GesturesData;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-
-// Touch gesture variables
-static Vector2 touchDownPosition = { 0.0f, 0.0f }; // First touch down position
-static Vector2 touchDownPosition2 = { 0.0f, 0.0f }; // Second touch down position
-static Vector2 touchDownDragPosition = { 0.0f, 0.0f }; // Touch drag position
-static Vector2 touchUpPosition = { 0.0f, 0.0f }; // Touch up position
-static Vector2 moveDownPosition = { 0.0f, 0.0f }; // First touch down position on move
-static Vector2 moveDownPosition2 = { 0.0f, 0.0f }; // Second touch down position on move
-
-static int pointCount = 0; // Touch points counter
-static int firstTouchId = -1; // Touch id for first touch point
-static double eventTime = 0.0; // Time stamp when an event happened
-
-// Tap gesture variables
-static int tapCounter = 0; // TAP counter (one tap implies TOUCH_DOWN and TOUCH_UP actions)
-
-// Hold gesture variables
-static bool resetHold = false; // HOLD reset to get first touch point again
-static double timeHold = 0.0f; // HOLD duration in milliseconds
-
-// Drag gesture variables
-static Vector2 dragVector = { 0.0f , 0.0f }; // DRAG vector (between initial and current position)
-static float dragAngle = 0.0f; // DRAG angle (relative to x-axis)
-static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) (normalized [0..1])
-static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame)
-
-// Swipe gestures variables
-static bool startMoving = false; // SWIPE used to define when start measuring swipeTime
-static double swipeTime = 0.0; // SWIPE time to calculate drag intensity
-
-// Pinch gesture variables
-static Vector2 pinchVector = { 0.0f , 0.0f }; // PINCH vector (between first and second touch points)
-static float pinchAngle = 0.0f; // PINCH angle (relative to x-axis)
-static float pinchDistance = 0.0f; // PINCH displacement distance (normalized [0..1])
-
-static int currentGesture = GESTURE_NONE; // Current detected gesture
-
-// Enabled gestures flags, all gestures enabled by default
-static unsigned int enabledGestures = 0b0000001111111111;
+static GesturesData GESTURES = {
+ .Touch.firstId = -1,
+ .current = GESTURE_NONE,
+ .enabledFlags = 0b0000001111111111 // All gestures enabled by default
+};
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
@@ -236,13 +237,13 @@ static double GetCurrentTime(void);
// Enable only desired getures to be detected
void SetGesturesEnabled(unsigned int gestureFlags)
{
- enabledGestures = gestureFlags;
+ GESTURES.enabledFlags = gestureFlags;
}
// Check if a gesture have been detected
bool IsGestureDetected(int gesture)
{
- if ((enabledGestures & currentGesture) == gesture) return true;
+ if ((GESTURES.enabledFlags & GESTURES.current) == gesture) return true;
else return false;
}
@@ -250,150 +251,150 @@ bool IsGestureDetected(int gesture)
void ProcessGestureEvent(GestureEvent event)
{
// Reset required variables
- pointCount = event.pointCount; // Required on UpdateGestures()
+ GESTURES.Touch.pointCount = event.pointCount; // Required on UpdateGestures()
- if (pointCount < 2)
+ if (GESTURES.Touch.pointCount < 2)
{
if (event.touchAction == TOUCH_DOWN)
{
- tapCounter++; // Tap counter
+ GESTURES.Touch.tapCounter++; // Tap counter
// Detect GESTURE_DOUBLE_TAP
- if ((currentGesture == GESTURE_NONE) && (tapCounter >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (Vector2Distance(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE))
+ if ((GESTURES.current == GESTURE_NONE) && (GESTURES.Touch.tapCounter >= 2) && ((GetCurrentTime() - GESTURES.Touch.eventTime) < TAP_TIMEOUT) && (Vector2Distance(GESTURES.Touch.downPositionA, event.position[0]) < DOUBLETAP_RANGE))
{
- currentGesture = GESTURE_DOUBLETAP;
- tapCounter = 0;
+ GESTURES.current = GESTURE_DOUBLETAP;
+ GESTURES.Touch.tapCounter = 0;
}
else // Detect GESTURE_TAP
{
- tapCounter = 1;
- currentGesture = GESTURE_TAP;
+ GESTURES.Touch.tapCounter = 1;
+ GESTURES.current = GESTURE_TAP;
}
- touchDownPosition = event.position[0];
- touchDownDragPosition = event.position[0];
+ GESTURES.Touch.downPositionA = event.position[0];
+ GESTURES.Touch.downDragPosition = event.position[0];
- touchUpPosition = touchDownPosition;
- eventTime = GetCurrentTime();
+ GESTURES.Touch.upPosition = GESTURES.Touch.downPositionA;
+ GESTURES.Touch.eventTime = GetCurrentTime();
- firstTouchId = event.pointerId[0];
+ GESTURES.Touch.firstId = event.pointerId[0];
- dragVector = (Vector2){ 0.0f, 0.0f };
+ GESTURES.Drag.vector = (Vector2){ 0.0f, 0.0f };
}
else if (event.touchAction == TOUCH_UP)
{
- if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0];
+ if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
- // NOTE: dragIntensity dependend on the resolution of the screen
- dragDistance = Vector2Distance(touchDownPosition, touchUpPosition);
- dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime));
+ // NOTE: GESTURES.Drag.intensity dependend on the resolution of the screen
+ GESTURES.Drag.distance = Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
+ GESTURES.Drag.intensity = GESTURES.Drag.distance/(float)((GetCurrentTime() - GESTURES.Swipe.timeDuration));
- startMoving = false;
+ GESTURES.Swipe.start = false;
// Detect GESTURE_SWIPE
- if ((dragIntensity > FORCE_TO_SWIPE) && (firstTouchId == event.pointerId[0]))
+ if ((GESTURES.Drag.intensity > FORCE_TO_SWIPE) && (GESTURES.Touch.firstId == event.pointerId[0]))
{
// NOTE: Angle should be inverted in Y
- dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);
+ GESTURES.Drag.angle = 360.0f - Vector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
- if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right
- else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up
- else if ((dragAngle > 120) && (dragAngle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left
- else if ((dragAngle > 210) && (dragAngle < 300)) currentGesture = GESTURE_SWIPE_DOWN; // Down
- else currentGesture = GESTURE_NONE;
+ if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
+ else if ((GESTURES.Drag.angle > 30) && (GESTURES.Drag.angle < 120)) GESTURES.current = GESTURE_SWIPE_UP; // Up
+ else if ((GESTURES.Drag.angle > 120) && (GESTURES.Drag.angle < 210)) GESTURES.current = GESTURE_SWIPE_LEFT; // Left
+ else if ((GESTURES.Drag.angle > 210) && (GESTURES.Drag.angle < 300)) GESTURES.current = GESTURE_SWIPE_DOWN; // Down
+ else GESTURES.current = GESTURE_NONE;
}
else
{
- dragDistance = 0.0f;
- dragIntensity = 0.0f;
- dragAngle = 0.0f;
+ GESTURES.Drag.distance = 0.0f;
+ GESTURES.Drag.intensity = 0.0f;
+ GESTURES.Drag.angle = 0.0f;
- currentGesture = GESTURE_NONE;
+ GESTURES.current = GESTURE_NONE;
}
- touchDownDragPosition = (Vector2){ 0.0f, 0.0f };
- pointCount = 0;
+ GESTURES.Touch.downDragPosition = (Vector2){ 0.0f, 0.0f };
+ GESTURES.Touch.pointCount = 0;
}
else if (event.touchAction == TOUCH_MOVE)
{
- if (currentGesture == GESTURE_DRAG) eventTime = GetCurrentTime();
+ if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.eventTime = GetCurrentTime();
- if (!startMoving)
+ if (!GESTURES.Swipe.start)
{
- swipeTime = GetCurrentTime();
- startMoving = true;
+ GESTURES.Swipe.timeDuration = GetCurrentTime();
+ GESTURES.Swipe.start = true;
}
- moveDownPosition = event.position[0];
+ GESTURES.Touch.moveDownPositionA = event.position[0];
- if (currentGesture == GESTURE_HOLD)
+ if (GESTURES.current == GESTURE_HOLD)
{
- if (resetHold) touchDownPosition = event.position[0];
+ if (GESTURES.Hold.resetRequired) GESTURES.Touch.downPositionA = event.position[0];
- resetHold = false;
+ GESTURES.Hold.resetRequired = false;
// Detect GESTURE_DRAG
- if (Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_DRAG)
+ if (Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
{
- eventTime = GetCurrentTime();
- currentGesture = GESTURE_DRAG;
+ GESTURES.Touch.eventTime = GetCurrentTime();
+ GESTURES.current = GESTURE_DRAG;
}
}
- dragVector.x = moveDownPosition.x - touchDownDragPosition.x;
- dragVector.y = moveDownPosition.y - touchDownDragPosition.y;
+ GESTURES.Drag.vector.x = GESTURES.Touch.moveDownPositionA.x - GESTURES.Touch.downDragPosition.x;
+ GESTURES.Drag.vector.y = GESTURES.Touch.moveDownPositionA.y - GESTURES.Touch.downDragPosition.y;
}
}
else // Two touch points
{
if (event.touchAction == TOUCH_DOWN)
{
- touchDownPosition = event.position[0];
- touchDownPosition2 = event.position[1];
+ GESTURES.Touch.downPositionA = event.position[0];
+ GESTURES.Touch.downPositionB = event.position[1];
- //pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2);
+ //GESTURES.Pinch.distance = Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
- pinchVector.x = touchDownPosition2.x - touchDownPosition.x;
- pinchVector.y = touchDownPosition2.y - touchDownPosition.y;
+ GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
+ GESTURES.Pinch.vector.y = GESTURES.Touch.downPositionB.y - GESTURES.Touch.downPositionA.y;
- currentGesture = GESTURE_HOLD;
- timeHold = GetCurrentTime();
+ GESTURES.current = GESTURE_HOLD;
+ GESTURES.Hold.timeDuration = GetCurrentTime();
}
else if (event.touchAction == TOUCH_MOVE)
{
- pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2);
+ GESTURES.Pinch.distance = Vector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
- touchDownPosition = moveDownPosition;
- touchDownPosition2 = moveDownPosition2;
+ GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
+ GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
- moveDownPosition = event.position[0];
- moveDownPosition2 = event.position[1];
+ GESTURES.Touch.moveDownPositionA = event.position[0];
+ GESTURES.Touch.moveDownPositionB = event.position[1];
- pinchVector.x = moveDownPosition2.x - moveDownPosition.x;
- pinchVector.y = moveDownPosition2.y - moveDownPosition.y;
+ GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
+ GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
- if ((Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) >= MINIMUM_PINCH))
+ if ((Vector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (Vector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
{
- if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN;
- else currentGesture = GESTURE_PINCH_OUT;
+ if ((Vector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current = GESTURE_PINCH_IN;
+ else GESTURES.current = GESTURE_PINCH_OUT;
}
else
{
- currentGesture = GESTURE_HOLD;
- timeHold = GetCurrentTime();
+ GESTURES.current = GESTURE_HOLD;
+ GESTURES.Hold.timeDuration = GetCurrentTime();
}
// NOTE: Angle should be inverted in Y
- pinchAngle = 360.0f - Vector2Angle(moveDownPosition, moveDownPosition2);
+ GESTURES.Pinch.angle = 360.0f - Vector2Angle(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
}
else if (event.touchAction == TOUCH_UP)
{
- pinchDistance = 0.0f;
- pinchAngle = 0.0f;
- pinchVector = (Vector2){ 0.0f, 0.0f };
- pointCount = 0;
+ GESTURES.Pinch.distance = 0.0f;
+ GESTURES.Pinch.angle = 0.0f;
+ GESTURES.Pinch.vector = (Vector2){ 0.0f, 0.0f };
+ GESTURES.Touch.pointCount = 0;
- currentGesture = GESTURE_NONE;
+ GESTURES.current = GESTURE_NONE;
}
}
}
@@ -404,23 +405,23 @@ void UpdateGestures(void)
// NOTE: Gestures are processed through system callbacks on touch events
// Detect GESTURE_HOLD
- if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && (pointCount < 2))
+ if (((GESTURES.current == GESTURE_TAP) || (GESTURES.current == GESTURE_DOUBLETAP)) && (GESTURES.Touch.pointCount < 2))
{
- currentGesture = GESTURE_HOLD;
- timeHold = GetCurrentTime();
+ GESTURES.current = GESTURE_HOLD;
+ GESTURES.Hold.timeDuration = GetCurrentTime();
}
- if (((GetCurrentTime() - eventTime) > TAP_TIMEOUT) && (currentGesture == GESTURE_DRAG) && (pointCount < 2))
+ if (((GetCurrentTime() - GESTURES.Touch.eventTime) > TAP_TIMEOUT) && (GESTURES.current == GESTURE_DRAG) && (GESTURES.Touch.pointCount < 2))
{
- currentGesture = GESTURE_HOLD;
- timeHold = GetCurrentTime();
- resetHold = true;
+ GESTURES.current = GESTURE_HOLD;
+ GESTURES.Hold.timeDuration = GetCurrentTime();
+ GESTURES.Hold.resetRequired = true;
}
// Detect GESTURE_NONE
- if ((currentGesture == GESTURE_SWIPE_RIGHT) || (currentGesture == GESTURE_SWIPE_UP) || (currentGesture == GESTURE_SWIPE_LEFT) || (currentGesture == GESTURE_SWIPE_DOWN))
+ if ((GESTURES.current == GESTURE_SWIPE_RIGHT) || (GESTURES.current == GESTURE_SWIPE_UP) || (GESTURES.current == GESTURE_SWIPE_LEFT) || (GESTURES.current == GESTURE_SWIPE_DOWN))
{
- currentGesture = GESTURE_NONE;
+ GESTURES.current = GESTURE_NONE;
}
}
@@ -429,14 +430,14 @@ int GetTouchPointsCount(void)
{
// NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called
- return pointCount;
+ return GESTURES.Touch.pointCount;
}
// Get latest detected gesture
int GetGestureDetected(void)
{
// Get current gesture only if enabled
- return (enabledGestures & currentGesture);
+ return (GESTURES.enabledFlags & GESTURES.current);
}
// Hold time measured in ms
@@ -446,7 +447,7 @@ float GetGestureHoldDuration(void)
double time = 0.0;
- if (currentGesture == GESTURE_HOLD) time = GetCurrentTime() - timeHold;
+ if (GESTURES.current == GESTURE_HOLD) time = GetCurrentTime() - GESTURES.Hold.timeDuration;
return (float)time;
}
@@ -456,7 +457,7 @@ Vector2 GetGestureDragVector(void)
{
// NOTE: drag vector is calculated on one touch points TOUCH_MOVE
- return dragVector;
+ return GESTURES.Drag.vector;
}
// Get drag angle
@@ -465,16 +466,16 @@ float GetGestureDragAngle(void)
{
// NOTE: drag angle is calculated on one touch points TOUCH_UP
- return dragAngle;
+ return GESTURES.Drag.angle;
}
// Get distance between two pinch points
Vector2 GetGesturePinchVector(void)
{
- // NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index)
+ // NOTE: The position values used for GESTURES.Pinch.distance are not modified like the position values of [core.c]-->GetTouchPosition(int index)
// NOTE: pinch distance is calculated on two touch points TOUCH_MOVE
- return pinchVector;
+ return GESTURES.Pinch.vector;
}
// Get angle beween two pinch points
@@ -483,7 +484,7 @@ float GetGesturePinchAngle(void)
{
// NOTE: pinch angle is calculated on two touch points TOUCH_MOVE
- return pinchAngle;
+ return GESTURES.Pinch.angle;
}
//----------------------------------------------------------------------------------
diff --git a/src/raudio.c b/src/raudio.c
index ed2eef18..ca82fef6 100644
--- a/src/raudio.c
+++ b/src/raudio.c
@@ -4,11 +4,11 @@
*
* FEATURES:
* - Manage audio device (init/close)
+* - Manage raw audio context
+* - Manage mixing channels
* - Load and unload audio files
* - Format wave data (sample rate, size, channels)
* - Play/Stop/Pause/Resume loaded audio
-* - Manage mixing channels
-* - Manage raw audio context
*
* CONFIGURATION:
*
@@ -124,7 +124,15 @@
// After some math, considering a sampleRate of 48000, a buffer refill rate of 1/60 seconds and a
// standard double-buffering system, a 4096 samples buffer has been chosen, it should be enough
// In case of music-stalls, just increase this number
-#define AUDIO_BUFFER_SIZE 4096 // PCM data samples (i.e. 16bit, Mono: 8Kb)
+#if !defined(AUDIO_BUFFER_SIZE)
+ #define AUDIO_BUFFER_SIZE 4096 // PCM data samples (i.e. 16bit, Mono: 8Kb)
+#endif
+
+#define DEVICE_FORMAT ma_format_f32
+#define DEVICE_CHANNELS 2
+#define DEVICE_SAMPLE_RATE 44100
+
+#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16
//----------------------------------------------------------------------------------
// Types and Structures Definition
@@ -155,14 +163,74 @@ typedef enum {
} TraceLogType;
#endif
+// NOTE: Different logic is used when feeding data to the playback device
+// depending on whether or not data is streamed (Music vs Sound)
+typedef enum {
+ AUDIO_BUFFER_USAGE_STATIC = 0,
+ AUDIO_BUFFER_USAGE_STREAM
+} AudioBufferUsage;
+
+// Audio buffer structure
+struct rAudioBuffer {
+ ma_pcm_converter dsp; // PCM data converter
+
+ float volume; // Audio buffer volume
+ float pitch; // Audio buffer pitch
+
+ bool playing; // Audio buffer state: AUDIO_PLAYING
+ bool paused; // Audio buffer state: AUDIO_PAUSED
+ bool looping; // Audio buffer looping, always true for AudioStreams
+ int usage; // Audio buffer usage mode: STATIC or STREAM
+
+ bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer)
+ unsigned int sizeInFrames; // Total buffer size in frames
+ unsigned int frameCursorPos; // Frame cursor position
+ unsigned int totalFramesProcessed; // Total frames processed in this buffer (required for play timming)
+
+ unsigned char *data; // Data buffer, on music stream keeps filling
+
+ rAudioBuffer *next; // Next audio buffer on the list
+ rAudioBuffer *prev; // Previous audio buffer on the list
+};
+
+#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision
+
+// Audio data context
+typedef struct AudioData {
+ struct {
+ ma_context context; // miniaudio context data
+ ma_device device; // miniaudio device
+ ma_mutex lock; // miniaudio mutex lock
+ bool isReady; // Check if audio device is ready
+ float masterVolume; // Master volume (multiplied on output mixing)
+ } System;
+ struct {
+ AudioBuffer *first; // Pointer to first AudioBuffer in the list
+ AudioBuffer *last; // Pointer to last AudioBuffer in the list
+ } Buffer;
+ struct {
+ AudioBuffer *pool[MAX_AUDIO_BUFFER_POOL_CHANNELS]; // Multichannel AudioBuffer pointers pool
+ unsigned int poolCounter; // AudioBuffer pointers pool counter
+ unsigned int channels[MAX_AUDIO_BUFFER_POOL_CHANNELS]; // AudioBuffer pool channels
+ } MultiChannel;
+} AudioData;
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-// ...
+static AudioData AUDIO = { 0 }; // Global CORE context
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
+static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message);
+static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount);
+static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, ma_uint32 frameCount, void *pUserData);
+static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume);
+
+static void InitAudioBufferPool(void); // Initialise the multichannel buffer pool
+static void CloseAudioBufferPool(void); // Close the audio buffers pool
+
#if defined(SUPPORT_FILEFORMAT_WAV)
static Wave LoadWAV(const char *fileName); // Load WAV file
static int SaveWAV(Wave wave, const char *fileName); // Save wave data as WAV file
@@ -178,73 +246,15 @@ static Wave LoadMP3(const char *fileName); // Load MP3 file
#endif
#if defined(RAUDIO_STANDALONE)
-bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
-void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
+bool IsFileExtension(const char *fileName, const char *ext);// Check file extension
+void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG)
#endif
//----------------------------------------------------------------------------------
-// AudioBuffer Functionality
-//----------------------------------------------------------------------------------
-#define DEVICE_FORMAT ma_format_f32
-#define DEVICE_CHANNELS 2
-#define DEVICE_SAMPLE_RATE 44100
-
-#define MAX_AUDIO_BUFFER_POOL_CHANNELS 16
-
-typedef enum { AUDIO_BUFFER_USAGE_STATIC = 0, AUDIO_BUFFER_USAGE_STREAM } AudioBufferUsage;
-
-// Audio buffer structure
-// NOTE: Slightly different logic is used when feeding data to the
-// playback device depending on whether or not data is streamed
-struct rAudioBuffer {
- ma_pcm_converter dsp; // PCM data converter
-
- float volume; // Audio buffer volume
- float pitch; // Audio buffer pitch
-
- bool playing; // Audio buffer state: AUDIO_PLAYING
- bool paused; // Audio buffer state: AUDIO_PAUSED
- bool looping; // Audio buffer looping, always true for AudioStreams
- int usage; // Audio buffer usage mode: STATIC or STREAM
-
- bool isSubBufferProcessed[2]; // SubBuffer processed (virtual double buffer)
- unsigned int frameCursorPos; // Frame cursor position
- unsigned int bufferSizeInFrames; // Total buffer size in frames
- unsigned int totalFramesProcessed; // Total frames processed in this buffer (required for play timming)
-
- unsigned char *buffer; // Data buffer, on music stream keeps filling
-
- rAudioBuffer *next; // Next audio buffer on the list
- rAudioBuffer *prev; // Previous audio buffer on the list
-};
-
-#define AudioBuffer rAudioBuffer // HACK: To avoid CoreAudio (macOS) symbol collision
-
-// Audio buffers are tracked in a linked list
-static AudioBuffer *firstAudioBuffer = NULL; // Pointer to first AudioBuffer in the list
-static AudioBuffer *lastAudioBuffer = NULL; // Pointer to last AudioBuffer in the list
-
-// miniaudio global variables
-static ma_context context; // miniaudio context data
-static ma_device device; // miniaudio device
-static ma_mutex audioLock; // miniaudio mutex lock
-static bool isAudioInitialized = false; // Check if audio device is initialized
-static float masterVolume = 1.0f; // Master volume (multiplied on output mixing)
-
-// Multi channel playback global variables
-static AudioBuffer *audioBufferPool[MAX_AUDIO_BUFFER_POOL_CHANNELS] = { 0 }; // Multichannel AudioBuffer pointers pool
-static unsigned int audioBufferPoolCounter = 0; // AudioBuffer pointers pool counter
-static unsigned int audioBufferPoolChannels[MAX_AUDIO_BUFFER_POOL_CHANNELS] = { 0 }; // AudioBuffer pool channels
-
-// miniaudio functions declaration
-static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message);
-static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount);
-static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, ma_uint32 frameCount, void *pUserData);
-static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume);
-
// AudioBuffer management functions declaration
// NOTE: Those functions are not exposed by raylib... for the moment
-AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 bufferSizeInFrames, int usage);
+//----------------------------------------------------------------------------------
+AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames, int usage);
void CloseAudioBuffer(AudioBuffer *buffer);
bool IsAudioBufferPlaying(AudioBuffer *buffer);
void PlayAudioBuffer(AudioBuffer *buffer);
@@ -256,248 +266,20 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch);
void TrackAudioBuffer(AudioBuffer *buffer);
void UntrackAudioBuffer(AudioBuffer *buffer);
-
-//----------------------------------------------------------------------------------
-// miniaudio functions definitions
-//----------------------------------------------------------------------------------
-
-// Log callback function
-static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message)
-{
- (void)pContext;
- (void)pDevice;
-
- TraceLog(LOG_ERROR, message); // All log messages from miniaudio are errors
-}
-
-// Sending audio data to device callback function
-// NOTE: All the mixing takes place here
-static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount)
-{
- (void)pDevice;
-
- // Mixing is basically just an accumulation, we need to initialize the output buffer to 0
- memset(pFramesOut, 0, frameCount*pDevice->playback.channels*ma_get_bytes_per_sample(pDevice->playback.format));
-
- // Using a mutex here for thread-safety which makes things not real-time
- // This is unlikely to be necessary for this project, but may want to consider how you might want to avoid this
- ma_mutex_lock(&audioLock);
- {
- for (AudioBuffer *audioBuffer = firstAudioBuffer; audioBuffer != NULL; audioBuffer = audioBuffer->next)
- {
- // Ignore stopped or paused sounds
- if (!audioBuffer->playing || audioBuffer->paused) continue;
-
- ma_uint32 framesRead = 0;
-
- while (1)
- {
- if (framesRead > frameCount)
- {
- TraceLog(LOG_DEBUG, "Mixed too many frames from audio buffer");
- break;
- }
-
- if (framesRead == frameCount) break;
-
- // Just read as much data as we can from the stream
- ma_uint32 framesToRead = (frameCount - framesRead);
-
- while (framesToRead > 0)
- {
- float tempBuffer[1024]; // 512 frames for stereo
-
- ma_uint32 framesToReadRightNow = framesToRead;
- if (framesToReadRightNow > sizeof(tempBuffer)/sizeof(tempBuffer[0])/DEVICE_CHANNELS)
- {
- framesToReadRightNow = sizeof(tempBuffer)/sizeof(tempBuffer[0])/DEVICE_CHANNELS;
- }
-
- ma_uint32 framesJustRead = (ma_uint32)ma_pcm_converter_read(&audioBuffer->dsp, tempBuffer, framesToReadRightNow);
- if (framesJustRead > 0)
- {
- float *framesOut = (float *)pFramesOut + (framesRead*device.playback.channels);
- float *framesIn = tempBuffer;
-
- MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer->volume);
-
- framesToRead -= framesJustRead;
- framesRead += framesJustRead;
- }
-
- if (!audioBuffer->playing)
- {
- framesRead = frameCount;
- break;
- }
-
- // If we weren't able to read all the frames we requested, break
- if (framesJustRead < framesToReadRightNow)
- {
- if (!audioBuffer->looping)
- {
- StopAudioBuffer(audioBuffer);
- break;
- }
- else
- {
- // Should never get here, but just for safety,
- // move the cursor position back to the start and continue the loop
- audioBuffer->frameCursorPos = 0;
- continue;
- }
- }
- }
-
- // If for some reason we weren't able to read every frame we'll need to break from the loop
- // Not doing this could theoretically put us into an infinite loop
- if (framesToRead > 0) break;
- }
- }
- }
-
- ma_mutex_unlock(&audioLock);
-}
-
-// DSP read from audio buffer callback function
-static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, ma_uint32 frameCount, void *pUserData)
-{
- AudioBuffer *audioBuffer = (AudioBuffer *)pUserData;
-
- ma_uint32 subBufferSizeInFrames = (audioBuffer->bufferSizeInFrames > 1)? audioBuffer->bufferSizeInFrames/2 : audioBuffer->bufferSizeInFrames;
- ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
-
- if (currentSubBufferIndex > 1)
- {
- TraceLog(LOG_DEBUG, "Frame cursor position moved too far forward in audio stream");
- return 0;
- }
-
- // Another thread can update the processed state of buffers so
- // we just take a copy here to try and avoid potential synchronization problems
- bool isSubBufferProcessed[2];
- isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
- isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
-
- ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)*audioBuffer->dsp.formatConverterIn.config.channels;
-
- // Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0
- ma_uint32 framesRead = 0;
- while (1)
- {
- // We break from this loop differently depending on the buffer's usage
- // - For static buffers, we simply fill as much data as we can
- // - For streaming buffers we only fill the halves of the buffer that are processed
- // Unprocessed halves must keep their audio data in-tact
- if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
- {
- if (framesRead >= frameCount) break;
- }
- else
- {
- if (isSubBufferProcessed[currentSubBufferIndex]) break;
- }
-
- ma_uint32 totalFramesRemaining = (frameCount - framesRead);
- if (totalFramesRemaining == 0) break;
-
- ma_uint32 framesRemainingInOutputBuffer;
- if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
- {
- framesRemainingInOutputBuffer = audioBuffer->bufferSizeInFrames - audioBuffer->frameCursorPos;
- }
- else
- {
- ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames*currentSubBufferIndex;
- framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer);
- }
-
- ma_uint32 framesToRead = totalFramesRemaining;
- if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer;
-
- memcpy((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), audioBuffer->buffer + (audioBuffer->frameCursorPos*frameSizeInBytes), framesToRead*frameSizeInBytes);
- audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->bufferSizeInFrames;
- framesRead += framesToRead;
-
- // If we've read to the end of the buffer, mark it as processed
- if (framesToRead == framesRemainingInOutputBuffer)
- {
- audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true;
- isSubBufferProcessed[currentSubBufferIndex] = true;
-
- currentSubBufferIndex = (currentSubBufferIndex + 1)%2;
-
- // We need to break from this loop if we're not looping
- if (!audioBuffer->looping)
- {
- StopAudioBuffer(audioBuffer);
- break;
- }
- }
- }
-
- // Zero-fill excess
- ma_uint32 totalFramesRemaining = (frameCount - framesRead);
- if (totalFramesRemaining > 0)
- {
- memset((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), 0, totalFramesRemaining*frameSizeInBytes);
-
- // For static buffers we can fill the remaining frames with silence for safety, but we don't want
- // to report those frames as "read". The reason for this is that the caller uses the return value
- // to know whether or not a non-looping sound has finished playback.
- if (audioBuffer->usage != AUDIO_BUFFER_USAGE_STATIC) framesRead += totalFramesRemaining;
- }
-
- return framesRead;
-}
-
-// This is the main mixing function. Mixing is pretty simple in this project - it's just an accumulation.
-// NOTE: framesOut is both an input and an output. It will be initially filled with zeros outside of this function.
-static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume)
-{
- for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
- {
- for (ma_uint32 iChannel = 0; iChannel < device.playback.channels; ++iChannel)
- {
- float *frameOut = framesOut + (iFrame*device.playback.channels);
- const float *frameIn = framesIn + (iFrame*device.playback.channels);
-
- frameOut[iChannel] += (frameIn[iChannel]*masterVolume*localVolume);
- }
- }
-}
-
-// Initialise the multichannel buffer pool
-static void InitAudioBufferPool()
-{
- // Dummy buffers
- for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
- {
- audioBufferPool[i] = InitAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, 0, AUDIO_BUFFER_USAGE_STATIC);
- }
-}
-
-// Close the audio buffers pool
-static void CloseAudioBufferPool()
-{
- for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
- {
- RL_FREE(audioBufferPool[i]->buffer);
- RL_FREE(audioBufferPool[i]);
- }
-}
-
//----------------------------------------------------------------------------------
// Module Functions Definition - Audio Device initialization and Closing
//----------------------------------------------------------------------------------
// Initialize audio device
void InitAudioDevice(void)
{
+ // TODO: Load AUDIO context memory dynamically?
+ AUDIO.System.masterVolume = 1.0f;
+
// Init audio context
- ma_context_config contextConfig = ma_context_config_init();
- contextConfig.logCallback = OnLog;
+ ma_context_config ctxConfig = ma_context_config_init();
+ ctxConfig.logCallback = OnLog;
- ma_result result = ma_context_init(NULL, 0, &contextConfig, &context);
+ ma_result result = ma_context_init(NULL, 0, &ctxConfig, &AUDIO.System.context);
if (result != MA_SUCCESS)
{
TraceLog(LOG_ERROR, "Failed to initialize audio context");
@@ -507,78 +289,78 @@ void InitAudioDevice(void)
// Init audio device
// NOTE: Using the default device. Format is floating point because it simplifies mixing.
ma_device_config config = ma_device_config_init(ma_device_type_playback);
- config.playback.pDeviceID = NULL; // NULL for the default playback device.
+ config.playback.pDeviceID = NULL; // NULL for the default playback AUDIO.System.device.
config.playback.format = DEVICE_FORMAT;
config.playback.channels = DEVICE_CHANNELS;
- config.capture.pDeviceID = NULL; // NULL for the default capture device.
+ config.capture.pDeviceID = NULL; // NULL for the default capture AUDIO.System.device.
config.capture.format = ma_format_s16;
config.capture.channels = 1;
config.sampleRate = DEVICE_SAMPLE_RATE;
config.dataCallback = OnSendAudioDataToDevice;
config.pUserData = NULL;
- result = ma_device_init(&context, &config, &device);
+ result = ma_device_init(&AUDIO.System.context, &config, &AUDIO.System.device);
if (result != MA_SUCCESS)
{
- TraceLog(LOG_ERROR, "Failed to initialize audio playback device");
- ma_context_uninit(&context);
+ TraceLog(LOG_ERROR, "Failed to initialize audio playback AUDIO.System.device");
+ ma_context_uninit(&AUDIO.System.context);
return;
}
// Keep the device running the whole time. May want to consider doing something a bit smarter and only have the device running
// while there's at least one sound being played.
- result = ma_device_start(&device);
+ result = ma_device_start(&AUDIO.System.device);
if (result != MA_SUCCESS)
{
- TraceLog(LOG_ERROR, "Failed to start audio playback device");
- ma_device_uninit(&device);
- ma_context_uninit(&context);
+ TraceLog(LOG_ERROR, "Failed to start audio playback AUDIO.System.device");
+ ma_device_uninit(&AUDIO.System.device);
+ ma_context_uninit(&AUDIO.System.context);
return;
}
// Mixing happens on a seperate thread which means we need to synchronize. I'm using a mutex here to make things simple, but may
// want to look at something a bit smarter later on to keep everything real-time, if that's necessary.
- if (ma_mutex_init(&context, &audioLock) != MA_SUCCESS)
+ if (ma_mutex_init(&AUDIO.System.context, &AUDIO.System.lock) != MA_SUCCESS)
{
TraceLog(LOG_ERROR, "Failed to create mutex for audio mixing");
- ma_device_uninit(&device);
- ma_context_uninit(&context);
+ ma_device_uninit(&AUDIO.System.device);
+ ma_context_uninit(&AUDIO.System.context);
return;
}
TraceLog(LOG_INFO, "Audio device initialized successfully");
- TraceLog(LOG_INFO, "Audio backend: miniaudio / %s", ma_get_backend_name(context.backend));
- TraceLog(LOG_INFO, "Audio format: %s -> %s", ma_get_format_name(device.playback.format), ma_get_format_name(device.playback.internalFormat));
- TraceLog(LOG_INFO, "Audio channels: %d -> %d", device.playback.channels, device.playback.internalChannels);
- TraceLog(LOG_INFO, "Audio sample rate: %d -> %d", device.sampleRate, device.playback.internalSampleRate);
- TraceLog(LOG_INFO, "Audio buffer size: %d", device.playback.internalBufferSizeInFrames);
+ TraceLog(LOG_INFO, "Audio backend: miniaudio / %s", ma_get_backend_name(AUDIO.System.context.backend));
+ TraceLog(LOG_INFO, "Audio format: %s -> %s", ma_get_format_name(AUDIO.System.device.playback.format), ma_get_format_name(AUDIO.System.device.playback.internalFormat));
+ TraceLog(LOG_INFO, "Audio channels: %d -> %d", AUDIO.System.device.playback.channels, AUDIO.System.device.playback.internalChannels);
+ TraceLog(LOG_INFO, "Audio sample rate: %d -> %d", AUDIO.System.device.sampleRate, AUDIO.System.device.playback.internalSampleRate);
+ TraceLog(LOG_INFO, "Audio buffer size: %d", AUDIO.System.device.playback.internalBufferSizeInFrames);
InitAudioBufferPool();
TraceLog(LOG_INFO, "Audio multichannel pool size: %i", MAX_AUDIO_BUFFER_POOL_CHANNELS);
- isAudioInitialized = true;
+ AUDIO.System.isReady = true;
}
// Close the audio device for all contexts
void CloseAudioDevice(void)
{
- if (isAudioInitialized)
+ if (AUDIO.System.isReady)
{
- ma_mutex_uninit(&audioLock);
- ma_device_uninit(&device);
- ma_context_uninit(&context);
+ ma_mutex_uninit(&AUDIO.System.lock);
+ ma_device_uninit(&AUDIO.System.device);
+ ma_context_uninit(&AUDIO.System.context);
CloseAudioBufferPool();
- TraceLog(LOG_INFO, "Audio device closed successfully");
+ TraceLog(LOG_INFO, "Audio AUDIO.System.device closed successfully");
}
- else TraceLog(LOG_WARNING, "Could not close audio device because it is not currently initialized");
+ else TraceLog(LOG_WARNING, "Could not close audio AUDIO.System.device because it is not currently initialized");
}
// Check if device has been initialized successfully
bool IsAudioDeviceReady(void)
{
- return isAudioInitialized;
+ return AUDIO.System.isReady;
}
// Set master volume (listener)
@@ -587,7 +369,7 @@ void SetMasterVolume(float volume)
if (volume < 0.0f) volume = 0.0f;
else if (volume > 1.0f) volume = 1.0f;
- masterVolume = volume;
+ AUDIO.System.masterVolume = volume;
}
//----------------------------------------------------------------------------------
@@ -595,7 +377,7 @@ void SetMasterVolume(float volume)
//----------------------------------------------------------------------------------
// Initialize a new audio buffer (filled with silence)
-AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 bufferSizeInFrames, int usage)
+AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 sizeInFrames, int usage)
{
AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer));
@@ -605,7 +387,7 @@ AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
return NULL;
}
- audioBuffer->buffer = RL_CALLOC(bufferSizeInFrames*channels*ma_get_bytes_per_sample(format), 1);
+ audioBuffer->data = RL_CALLOC(sizeInFrames*channels*ma_get_bytes_per_sample(format), 1);
// Audio data runs through a format converter
ma_pcm_converter_config dspConfig;
@@ -637,7 +419,7 @@ AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sam
audioBuffer->looping = false;
audioBuffer->usage = usage;
audioBuffer->frameCursorPos = 0;
- audioBuffer->bufferSizeInFrames = bufferSizeInFrames;
+ audioBuffer->sizeInFrames = sizeInFrames;
// Buffers should be marked as processed by default so that a call to
// UpdateAudioStream() immediately after initialization works correctly
@@ -656,7 +438,7 @@ void CloseAudioBuffer(AudioBuffer *buffer)
if (buffer != NULL)
{
UntrackAudioBuffer(buffer);
- RL_FREE(buffer->buffer);
+ RL_FREE(buffer->data);
RL_FREE(buffer);
}
else TraceLog(LOG_ERROR, "CloseAudioBuffer() : No audio buffer");
@@ -748,35 +530,35 @@ void SetAudioBufferPitch(AudioBuffer *buffer, float pitch)
// Track audio buffer to linked list next position
void TrackAudioBuffer(AudioBuffer *buffer)
{
- ma_mutex_lock(&audioLock);
+ ma_mutex_lock(&AUDIO.System.lock);
{
- if (firstAudioBuffer == NULL) firstAudioBuffer = buffer;
+ if (AUDIO.Buffer.first == NULL) AUDIO.Buffer.first = buffer;
else
{
- lastAudioBuffer->next = buffer;
- buffer->prev = lastAudioBuffer;
+ AUDIO.Buffer.last->next = buffer;
+ buffer->prev = AUDIO.Buffer.last;
}
- lastAudioBuffer = buffer;
+ AUDIO.Buffer.last = buffer;
}
- ma_mutex_unlock(&audioLock);
+ ma_mutex_unlock(&AUDIO.System.lock);
}
// Untrack audio buffer from linked list
void UntrackAudioBuffer(AudioBuffer *buffer)
{
- ma_mutex_lock(&audioLock);
+ ma_mutex_lock(&AUDIO.System.lock);
{
- if (buffer->prev == NULL) firstAudioBuffer = buffer->next;
+ if (buffer->prev == NULL) AUDIO.Buffer.first = buffer->next;
else buffer->prev->next = buffer->next;
- if (buffer->next == NULL) lastAudioBuffer = buffer->prev;
+ if (buffer->next == NULL) AUDIO.Buffer.last = buffer->prev;
else buffer->next->prev = buffer->prev;
buffer->prev = NULL;
buffer->next = NULL;
}
- ma_mutex_unlock(&audioLock);
+ ma_mutex_unlock(&AUDIO.System.lock);
}
//----------------------------------------------------------------------------------
@@ -829,7 +611,7 @@ Sound LoadSoundFromWave(Wave wave)
{
// When using miniaudio we need to do our own mixing.
// To simplify this we need convert the format of each sound to be consistent with
- // the format used to open the playback device. We can do this two ways:
+ // the format used to open the playback AUDIO.System.device. We can do this two ways:
//
// 1) Convert the whole sound in one go at load time (here).
// 2) Convert the audio data in chunks at mixing time.
@@ -845,7 +627,7 @@ Sound LoadSoundFromWave(Wave wave)
AudioBuffer *audioBuffer = InitAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, frameCount, AUDIO_BUFFER_USAGE_STATIC);
if (audioBuffer == NULL) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Failed to create audio buffer");
- frameCount = (ma_uint32)ma_convert_frames(audioBuffer->buffer, audioBuffer->dsp.formatConverterIn.config.formatIn, audioBuffer->dsp.formatConverterIn.config.channels, audioBuffer->dsp.src.config.sampleRateIn, wave.data, formatIn, wave.channels, wave.sampleRate, frameCountIn);
+ frameCount = (ma_uint32)ma_convert_frames(audioBuffer->data, audioBuffer->dsp.formatConverterIn.config.formatIn, audioBuffer->dsp.formatConverterIn.config.channels, audioBuffer->dsp.src.config.sampleRateIn, wave.data, formatIn, wave.channels, wave.sampleRate, frameCountIn);
if (frameCount == 0) TraceLog(LOG_WARNING, "LoadSoundFromWave() : Format conversion failed");
sound.sampleCount = frameCount*DEVICE_CHANNELS;
@@ -884,7 +666,7 @@ void UpdateSound(Sound sound, const void *data, int samplesCount)
StopAudioBuffer(audioBuffer);
// TODO: May want to lock/unlock this since this data buffer is read at mixing time
- memcpy(audioBuffer->buffer, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn));
+ memcpy(audioBuffer->data, data, samplesCount*audioBuffer->dsp.formatConverterIn.config.channels*ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn));
}
else TraceLog(LOG_ERROR, "UpdateSound() : Invalid sound - no audio buffer");
}
@@ -973,13 +755,13 @@ void PlaySoundMulti(Sound sound)
// find the first non playing pool entry
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
{
- if (audioBufferPoolChannels[i] > oldAge)
+ if (AUDIO.MultiChannel.channels[i] > oldAge)
{
- oldAge = audioBufferPoolChannels[i];
+ oldAge = AUDIO.MultiChannel.channels[i];
oldIndex = i;
}
- if (!IsAudioBufferPlaying(audioBufferPool[i]))
+ if (!IsAudioBufferPlaying(AUDIO.MultiChannel.pool[i]))
{
index = i;
break;
@@ -989,7 +771,7 @@ void PlaySoundMulti(Sound sound)
// If no none playing pool members can be index choose the oldest
if (index == -1)
{
- TraceLog(LOG_WARNING,"pool age %i ended a sound early no room in buffer pool", audioBufferPoolCounter);
+ TraceLog(LOG_WARNING,"pool age %i ended a sound early no room in buffer pool", AUDIO.MultiChannel.poolCounter);
if (oldIndex == -1)
{
@@ -1002,32 +784,32 @@ void PlaySoundMulti(Sound sound)
index = oldIndex;
// Just in case...
- StopAudioBuffer(audioBufferPool[index]);
+ StopAudioBuffer(AUDIO.MultiChannel.pool[index]);
}
// Experimentally mutex lock doesn't seem to be needed this makes sense
- // as audioBufferPool[index] isn't playing and the only stuff we're copying
+ // as AUDIO.MultiChannel.pool[index] isn't playing and the only stuff we're copying
// shouldn't be changing...
- audioBufferPoolChannels[index] = audioBufferPoolCounter;
- audioBufferPoolCounter++;
+ AUDIO.MultiChannel.channels[index] = AUDIO.MultiChannel.poolCounter;
+ AUDIO.MultiChannel.poolCounter++;
- audioBufferPool[index]->volume = sound.stream.buffer->volume;
- audioBufferPool[index]->pitch = sound.stream.buffer->pitch;
- audioBufferPool[index]->looping = sound.stream.buffer->looping;
- audioBufferPool[index]->usage = sound.stream.buffer->usage;
- audioBufferPool[index]->isSubBufferProcessed[0] = false;
- audioBufferPool[index]->isSubBufferProcessed[1] = false;
- audioBufferPool[index]->bufferSizeInFrames = sound.stream.buffer->bufferSizeInFrames;
- audioBufferPool[index]->buffer = sound.stream.buffer->buffer;
+ AUDIO.MultiChannel.pool[index]->volume = sound.stream.buffer->volume;
+ AUDIO.MultiChannel.pool[index]->pitch = sound.stream.buffer->pitch;
+ AUDIO.MultiChannel.pool[index]->looping = sound.stream.buffer->looping;
+ AUDIO.MultiChannel.pool[index]->usage = sound.stream.buffer->usage;
+ AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[0] = false;
+ AUDIO.MultiChannel.pool[index]->isSubBufferProcessed[1] = false;
+ AUDIO.MultiChannel.pool[index]->sizeInFrames = sound.stream.buffer->sizeInFrames;
+ AUDIO.MultiChannel.pool[index]->data = sound.stream.buffer->data;
- PlayAudioBuffer(audioBufferPool[index]);
+ PlayAudioBuffer(AUDIO.MultiChannel.pool[index]);
}
// Stop any sound played with PlaySoundMulti()
void StopSoundMulti(void)
{
- for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) StopAudioBuffer(audioBufferPool[i]);
+ for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++) StopAudioBuffer(AUDIO.MultiChannel.pool[i]);
}
// Get number of sounds playing in the multichannel buffer pool
@@ -1037,7 +819,7 @@ int GetSoundsPlaying(void)
for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
{
- if (IsAudioBufferPlaying(audioBufferPool[i])) counter++;
+ if (IsAudioBufferPlaying(AUDIO.MultiChannel.pool[i])) counter++;
}
return counter;
@@ -1243,7 +1025,7 @@ Music LoadMusicStream(const char *fileName)
int result = jar_xm_create_context_from_file(&ctxXm, 48000, fileName);
- if (result == 0) // XM context created successfully
+ if (result == 0) // XM AUDIO.System.context created successfully
{
music.ctxType = MUSIC_MODULE_XM;
jar_xm_set_max_loop_count(ctxXm, 0); // Set infinite number of loops
@@ -1374,7 +1156,6 @@ void StopMusicStream(Music music)
{
StopAudioStream(music.stream);
- // Restart music context
switch (music.ctxType)
{
#if defined(SUPPORT_FILEFORMAT_OGG)
@@ -1401,7 +1182,7 @@ void UpdateMusicStream(Music music)
{
bool streamEnding = false;
- unsigned int subBufferSizeInFrames = music.stream.buffer->bufferSizeInFrames/2;
+ unsigned int subBufferSizeInFrames = music.stream.buffer->sizeInFrames/2;
// NOTE: Using dynamic allocation because it could require more than 16KB
void *pcm = RL_CALLOC(subBufferSizeInFrames*music.stream.channels*music.stream.sampleSize/8, 1);
@@ -1559,7 +1340,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un
ma_format formatIn = ((stream.sampleSize == 8)? ma_format_u8 : ((stream.sampleSize == 16)? ma_format_s16 : ma_format_f32));
// The size of a streaming buffer must be at least double the size of a period
- unsigned int periodSize = device.playback.internalBufferSizeInFrames/device.playback.internalPeriods;
+ unsigned int periodSize = AUDIO.System.device.playback.internalBufferSizeInFrames/AUDIO.System.device.playback.internalPeriods;
unsigned int subBufferSize = AUDIO_BUFFER_SIZE;
if (subBufferSize < periodSize) subBufferSize = periodSize;
@@ -1610,8 +1391,8 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount)
subBufferToUpdate = (audioBuffer->isSubBufferProcessed[0])? 0 : 1;
}
- ma_uint32 subBufferSizeInFrames = audioBuffer->bufferSizeInFrames/2;
- unsigned char *subBuffer = audioBuffer->buffer + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);
+ ma_uint32 subBufferSizeInFrames = audioBuffer->sizeInFrames/2;
+ unsigned char *subBuffer = audioBuffer->data + ((subBufferSizeInFrames*stream.channels*(stream.sampleSize/8))*subBufferToUpdate);
// TODO: Get total frames processed on this buffer... DOES NOT WORK.
audioBuffer->totalFramesProcessed += subBufferSizeInFrames;
@@ -1697,6 +1478,232 @@ void SetAudioStreamPitch(AudioStream stream, float pitch)
// Module specific Functions Definition
//----------------------------------------------------------------------------------
+// Log callback function
+static void OnLog(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message)
+{
+ (void)pContext;
+ (void)pDevice;
+
+ TraceLog(LOG_ERROR, message); // All log messages from miniaudio are errors
+}
+
+// Sending audio data to device callback function
+// NOTE: All the mixing takes place here
+static void OnSendAudioDataToDevice(ma_device *pDevice, void *pFramesOut, const void *pFramesInput, ma_uint32 frameCount)
+{
+ (void)pDevice;
+
+ // Mixing is basically just an accumulation, we need to initialize the output buffer to 0
+ memset(pFramesOut, 0, frameCount*pDevice->playback.channels*ma_get_bytes_per_sample(pDevice->playback.format));
+
+ // Using a mutex here for thread-safety which makes things not real-time
+ // This is unlikely to be necessary for this project, but may want to consider how you might want to avoid this
+ ma_mutex_lock(&AUDIO.System.lock);
+ {
+ for (AudioBuffer *audioBuffer = AUDIO.Buffer.first; audioBuffer != NULL; audioBuffer = audioBuffer->next)
+ {
+ // Ignore stopped or paused sounds
+ if (!audioBuffer->playing || audioBuffer->paused) continue;
+
+ ma_uint32 framesRead = 0;
+
+ while (1)
+ {
+ if (framesRead > frameCount)
+ {
+ TraceLog(LOG_DEBUG, "Mixed too many frames from audio buffer");
+ break;
+ }
+
+ if (framesRead == frameCount) break;
+
+ // Just read as much data as we can from the stream
+ ma_uint32 framesToRead = (frameCount - framesRead);
+
+ while (framesToRead > 0)
+ {
+ float tempBuffer[1024]; // 512 frames for stereo
+
+ ma_uint32 framesToReadRightNow = framesToRead;
+ if (framesToReadRightNow > sizeof(tempBuffer)/sizeof(tempBuffer[0])/DEVICE_CHANNELS)
+ {
+ framesToReadRightNow = sizeof(tempBuffer)/sizeof(tempBuffer[0])/DEVICE_CHANNELS;
+ }
+
+ ma_uint32 framesJustRead = (ma_uint32)ma_pcm_converter_read(&audioBuffer->dsp, tempBuffer, framesToReadRightNow);
+ if (framesJustRead > 0)
+ {
+ float *framesOut = (float *)pFramesOut + (framesRead*AUDIO.System.device.playback.channels);
+ float *framesIn = tempBuffer;
+
+ MixAudioFrames(framesOut, framesIn, framesJustRead, audioBuffer->volume);
+
+ framesToRead -= framesJustRead;
+ framesRead += framesJustRead;
+ }
+
+ if (!audioBuffer->playing)
+ {
+ framesRead = frameCount;
+ break;
+ }
+
+ // If we weren't able to read all the frames we requested, break
+ if (framesJustRead < framesToReadRightNow)
+ {
+ if (!audioBuffer->looping)
+ {
+ StopAudioBuffer(audioBuffer);
+ break;
+ }
+ else
+ {
+ // Should never get here, but just for safety,
+ // move the cursor position back to the start and continue the loop
+ audioBuffer->frameCursorPos = 0;
+ continue;
+ }
+ }
+ }
+
+ // If for some reason we weren't able to read every frame we'll need to break from the loop
+ // Not doing this could theoretically put us into an infinite loop
+ if (framesToRead > 0) break;
+ }
+ }
+ }
+
+ ma_mutex_unlock(&AUDIO.System.lock);
+}
+
+// DSP read from audio buffer callback function
+static ma_uint32 OnAudioBufferDSPRead(ma_pcm_converter *pDSP, void *pFramesOut, ma_uint32 frameCount, void *pUserData)
+{
+ AudioBuffer *audioBuffer = (AudioBuffer *)pUserData;
+
+ ma_uint32 subBufferSizeInFrames = (audioBuffer->sizeInFrames > 1)? audioBuffer->sizeInFrames/2 : audioBuffer->sizeInFrames;
+ ma_uint32 currentSubBufferIndex = audioBuffer->frameCursorPos/subBufferSizeInFrames;
+
+ if (currentSubBufferIndex > 1)
+ {
+ TraceLog(LOG_DEBUG, "Frame cursor position moved too far forward in audio stream");
+ return 0;
+ }
+
+ // Another thread can update the processed state of buffers so
+ // we just take a copy here to try and avoid potential synchronization problems
+ bool isSubBufferProcessed[2];
+ isSubBufferProcessed[0] = audioBuffer->isSubBufferProcessed[0];
+ isSubBufferProcessed[1] = audioBuffer->isSubBufferProcessed[1];
+
+ ma_uint32 frameSizeInBytes = ma_get_bytes_per_sample(audioBuffer->dsp.formatConverterIn.config.formatIn)*audioBuffer->dsp.formatConverterIn.config.channels;
+
+ // Fill out every frame until we find a buffer that's marked as processed. Then fill the remainder with 0
+ ma_uint32 framesRead = 0;
+ while (1)
+ {
+ // We break from this loop differently depending on the buffer's usage
+ // - For static buffers, we simply fill as much data as we can
+ // - For streaming buffers we only fill the halves of the buffer that are processed
+ // Unprocessed halves must keep their audio data in-tact
+ if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
+ {
+ if (framesRead >= frameCount) break;
+ }
+ else
+ {
+ if (isSubBufferProcessed[currentSubBufferIndex]) break;
+ }
+
+ ma_uint32 totalFramesRemaining = (frameCount - framesRead);
+ if (totalFramesRemaining == 0) break;
+
+ ma_uint32 framesRemainingInOutputBuffer;
+ if (audioBuffer->usage == AUDIO_BUFFER_USAGE_STATIC)
+ {
+ framesRemainingInOutputBuffer = audioBuffer->sizeInFrames - audioBuffer->frameCursorPos;
+ }
+ else
+ {
+ ma_uint32 firstFrameIndexOfThisSubBuffer = subBufferSizeInFrames*currentSubBufferIndex;
+ framesRemainingInOutputBuffer = subBufferSizeInFrames - (audioBuffer->frameCursorPos - firstFrameIndexOfThisSubBuffer);
+ }
+
+ ma_uint32 framesToRead = totalFramesRemaining;
+ if (framesToRead > framesRemainingInOutputBuffer) framesToRead = framesRemainingInOutputBuffer;
+
+ memcpy((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), audioBuffer->data + (audioBuffer->frameCursorPos*frameSizeInBytes), framesToRead*frameSizeInBytes);
+ audioBuffer->frameCursorPos = (audioBuffer->frameCursorPos + framesToRead)%audioBuffer->sizeInFrames;
+ framesRead += framesToRead;
+
+ // If we've read to the end of the buffer, mark it as processed
+ if (framesToRead == framesRemainingInOutputBuffer)
+ {
+ audioBuffer->isSubBufferProcessed[currentSubBufferIndex] = true;
+ isSubBufferProcessed[currentSubBufferIndex] = true;
+
+ currentSubBufferIndex = (currentSubBufferIndex + 1)%2;
+
+ // We need to break from this loop if we're not looping
+ if (!audioBuffer->looping)
+ {
+ StopAudioBuffer(audioBuffer);
+ break;
+ }
+ }
+ }
+
+ // Zero-fill excess
+ ma_uint32 totalFramesRemaining = (frameCount - framesRead);
+ if (totalFramesRemaining > 0)
+ {
+ memset((unsigned char *)pFramesOut + (framesRead*frameSizeInBytes), 0, totalFramesRemaining*frameSizeInBytes);
+
+ // For static buffers we can fill the remaining frames with silence for safety, but we don't want
+ // to report those frames as "read". The reason for this is that the caller uses the return value
+ // to know whether or not a non-looping sound has finished playback.
+ if (audioBuffer->usage != AUDIO_BUFFER_USAGE_STATIC) framesRead += totalFramesRemaining;
+ }
+
+ return framesRead;
+}
+
+// This is the main mixing function. Mixing is pretty simple in this project - it's just an accumulation.
+// NOTE: framesOut is both an input and an output. It will be initially filled with zeros outside of this function.
+static void MixAudioFrames(float *framesOut, const float *framesIn, ma_uint32 frameCount, float localVolume)
+{
+ for (ma_uint32 iFrame = 0; iFrame < frameCount; ++iFrame)
+ {
+ for (ma_uint32 iChannel = 0; iChannel < AUDIO.System.device.playback.channels; ++iChannel)
+ {
+ float *frameOut = framesOut + (iFrame*AUDIO.System.device.playback.channels);
+ const float *frameIn = framesIn + (iFrame*AUDIO.System.device.playback.channels);
+
+ frameOut[iChannel] += (frameIn[iChannel]*AUDIO.System.masterVolume*localVolume);
+ }
+ }
+}
+
+// Initialise the multichannel buffer pool
+static void InitAudioBufferPool(void)
+{
+ // Dummy buffers
+ for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
+ {
+ AUDIO.MultiChannel.pool[i] = InitAudioBuffer(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, 0, AUDIO_BUFFER_USAGE_STATIC);
+ }
+}
+
+// Close the audio buffers pool
+static void CloseAudioBufferPool(void)
+{
+ for (int i = 0; i < MAX_AUDIO_BUFFER_POOL_CHANNELS; i++)
+ {
+ RL_FREE(AUDIO.MultiChannel.pool[i]->data);
+ RL_FREE(AUDIO.MultiChannel.pool[i]);
+ }
+}
+
#if defined(SUPPORT_FILEFORMAT_WAV)
// Load WAV file into Wave structure
static Wave LoadWAV(const char *fileName)
diff --git a/src/raylib.dll.rc b/src/raylib.dll.rc
index 0ba8c8a8..4449a59c 100644
--- a/src/raylib.dll.rc
+++ b/src/raylib.dll.rc
@@ -1,8 +1,8 @@
GLFW_ICON ICON "raylib.ico"
1 VERSIONINFO
-FILEVERSION 2,6,0,0
-PRODUCTVERSION 2,6,0,0
+FILEVERSION 3,0,0,0
+PRODUCTVERSION 3,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
@@ -11,12 +11,12 @@ BEGIN
BEGIN
//VALUE "CompanyName", "raylib technologies"
VALUE "FileDescription", "raylib dynamic library (www.raylib.com)"
- VALUE "FileVersion", "2.6.0"
+ VALUE "FileVersion", "3.0.0"
VALUE "InternalName", "raylib_dll"
VALUE "LegalCopyright", "(c) 2020 Ramon Santamaria (@raysan5)"
//VALUE "OriginalFilename", "raylib.dll"
VALUE "ProductName", "raylib"
- VALUE "ProductVersion", "2.6.0"
+ VALUE "ProductVersion", "3.0.0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/raylib.h b/src/raylib.h
index fbfc5006..1ca2ed0a 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -1081,8 +1081,6 @@ RLAPI void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color);
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
RLAPI void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a polygon outline of n sides
-RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Define default texture used to draw shapes
-
// Basic shapes collision detection functions
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
@@ -1329,6 +1327,9 @@ RLAPI void UnloadShader(Shader shader); // Unl
RLAPI Shader GetShaderDefault(void); // Get default shader
RLAPI Texture2D GetTextureDefault(void); // Get default texture
+RLAPI Texture2D GetShapesTexture(void); // Get texture to draw shapes
+RLAPI Rectangle GetShapesTextureRec(void); // Get texture rectangle to draw shapes
+RLAPI void SetShapesTexture(Texture2D texture, Rectangle source); // Define default texture used to draw shapes
// Shader configuration functions
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
diff --git a/src/raylib.rc b/src/raylib.rc
index 87f1ee63..7b36ef6d 100644
--- a/src/raylib.rc
+++ b/src/raylib.rc
@@ -1,8 +1,8 @@
GLFW_ICON ICON "raylib.ico"
1 VERSIONINFO
-FILEVERSION 2,6,0,0
-PRODUCTVERSION 2,6,0,0
+FILEVERSION 3,0,0,0
+PRODUCTVERSION 3,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
@@ -11,12 +11,12 @@ BEGIN
BEGIN
//VALUE "CompanyName", "raylib technologies"
VALUE "FileDescription", "raylib application (www.raylib.com)"
- VALUE "FileVersion", "2.6.0"
+ VALUE "FileVersion", "3.0.0"
VALUE "InternalName", "raylib app"
VALUE "LegalCopyright", "(c) 2020 Ramon Santamaria (@raysan5)"
//VALUE "OriginalFilename", "raylib_app.exe"
VALUE "ProductName", "raylib game"
- VALUE "ProductVersion", "2.6.0"
+ VALUE "ProductVersion", "3.0.0"
END
END
BLOCK "VarFileInfo"
diff --git a/src/rlgl.h b/src/rlgl.h
index ed1d5836..96d51653 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -198,6 +198,14 @@ typedef unsigned char byte;
unsigned char b;
unsigned char a;
} Color;
+
+ // Rectangle type
+ typedef struct Rectangle {
+ float x;
+ float y;
+ float width;
+ float height;
+ } Rectangle;
// Texture2D type
// NOTE: Data stored in GPU memory
@@ -539,6 +547,8 @@ RLAPI void UnloadShader(Shader shader); // Unl
RLAPI Shader GetShaderDefault(void); // Get default shader
RLAPI Texture2D GetTextureDefault(void); // Get default texture
+RLAPI Texture2D GetShapesTexture(void); // Get texture to draw shapes
+RLAPI Rectangle GetShapesTextureRec(void); // Get texture rectangle to draw shapes
// Shader configuration functions
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
@@ -739,6 +749,7 @@ typedef struct DynamicBuffer {
int vCounter; // vertex position counter to process (and draw) from full buffer
int tcCounter; // vertex texcoord counter to process (and draw) from full buffer
int cCounter; // vertex color counter to process (and draw) from full buffer
+
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
@@ -746,7 +757,6 @@ typedef struct DynamicBuffer {
unsigned int *indices; // vertex indices (in case vertex data comes indexed) (6 indices per quad)
#elif defined(GRAPHICS_API_OPENGL_ES2)
unsigned short *indices; // vertex indices (in case vertex data comes indexed) (6 indices per quad)
- // NOTE: 6*2 byte = 12 byte, not alignment problem!
#endif
unsigned int vaoId; // OpenGL Vertex Array Object id
unsigned int vboId[4]; // OpenGL Vertex Buffer Objects id (4 types of vertex data)
@@ -760,7 +770,6 @@ typedef struct DrawCall {
//unsigned int vaoId; // Vertex array id to be used on the draw
//unsigned int shaderId; // Shader id to be used on the draw
unsigned int textureId; // Texture id to be used on the draw
- // TODO: Support additional texture units?
//Matrix projection; // Projection matrix for this draw
//Matrix modelview; // Modelview matrix for this draw
@@ -777,50 +786,71 @@ typedef struct VrStereoConfig {
} VrStereoConfig;
#endif
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+typedef struct rlglData {
+ struct {
+ int currentMatrixMode; // Current matrix mode
+ Matrix *currentMatrix; // Current matrix pointer
+ Matrix modelview; // Default modelview matrix
+ Matrix projection; // Default projection matrix
+ Matrix transform; // Transform matrix to be used with rlTranslate, rlRotate, rlScale
+ bool doTransform; // Use transform matrix against vertex (if required)
+ Matrix stack[MAX_MATRIX_STACK_SIZE];// Matrix stack for push/pop
+ int stackCounter; // Matrix stack counter
+
+ DynamicBuffer vertexData[MAX_BATCH_BUFFERING];// Default dynamic buffer for elements data
+ int currentBuffer; // Current buffer tracking, multi-buffering system is supported
+ DrawCall *draws; // Draw calls array
+ int drawsCounter; // Draw calls counter
+
+ Texture2D shapesTexture; // Texture used on shapes drawing (usually a white)
+ Rectangle shapesTextureRec; // Texture source rectangle used on shapes drawing
+ unsigned int defaultTextureId; // Default texture used on shapes/poly drawing (required by shader)
+ unsigned int defaultVShaderId; // Default vertex shader id (used by default shader program)
+ unsigned int defaultFShaderId; // Default fragment shader Id (used by default shader program)
+ Shader defaultShader; // Basic shader, support vertex color and diffuse texture
+ Shader currentShader; // Shader to be used on rendering (by default, defaultShader)
+ float currentDepth; // Current depth value
+
+ int framebufferWidth; // Default framebuffer width
+ int framebufferHeight; // Default framebuffer height
+
+ } State;
+ struct {
+ bool vao; // VAO support (OpenGL ES2 could not support VAO extension)
+ bool texNPOT; // NPOT textures full support
+ bool texDepth; // Depth textures supported
+ bool texFloat32; // float textures support (32 bit per channel)
+ bool texCompDXT; // DDS texture compression support
+ bool texCompETC1; // ETC1 texture compression support
+ bool texCompETC2; // ETC2/EAC texture compression support
+ bool texCompPVRT; // PVR texture compression support
+ bool texCompASTC; // ASTC texture compression support
+ bool texMirrorClamp; // Clamp mirror wrap mode supported
+ bool texAnisoFilter; // Anisotropic texture filtering support
+ bool debugMarker; // Debug marker support
+
+ float maxAnisotropicLevel; // Maximum anisotropy level supported (minimum is 2.0f)
+ int maxDepthBits; // Maximum bits for depth component
+
+ } ExtSupported; // Extensions supported flags
+#if defined(SUPPORT_VR_SIMULATOR)
+ struct {
+ VrStereoConfig config; // VR stereo configuration for simulator
+ RenderTexture2D stereoFbo; // VR stereo rendering framebuffer
+ bool simulatorReady; // VR simulator ready flag
+ bool stereoRender; // VR stereo rendering enabled/disabled flag
+ } Vr;
+#endif // SUPPORT_VR_SIMULATOR
+} rlglData;
+#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-static Matrix stack[MAX_MATRIX_STACK_SIZE] = { 0 }; // Matrix stack for push/pop
-static int stackCounter = 0; // Matrix stack counter
-static Matrix modelview = { 0 }; // Default modelview matrix
-static Matrix projection = { 0 }; // Default projection matrix
-static Matrix *currentMatrix = NULL; // Current matrix pointer
-static int currentMatrixMode = -1; // Current matrix mode
-static float currentDepth = -1.0f; // Current depth value
-
-// Default dynamic buffer for elements data
-// NOTE: A multi-buffering system is supported
-static DynamicBuffer vertexData[MAX_BATCH_BUFFERING] = { 0 };
-static int currentBuffer = 0; // Current buffer tracking
-
-static Matrix transformMatrix = { 0 }; // Transform matrix to be used with rlTranslate, rlRotate, rlScale
-static bool useTransformMatrix = false; // Use transform matrix against vertex (if required)
-
-static DrawCall *draws = NULL; // Draw calls array
-static int drawsCounter = 0; // Draw calls counter
-
-static unsigned int defaultTextureId = 0; // Default texture used on shapes/poly drawing (required by shader)
-static unsigned int defaultVShaderId = 0; // Default vertex shader id (used by default shader program)
-static unsigned int defaultFShaderId = 0; // Default fragment shader Id (used by default shader program)
-static Shader defaultShader = { 0 }; // Basic shader, support vertex color and diffuse texture
-static Shader currentShader = { 0 }; // Shader to be used on rendering (by default, defaultShader)
-
-// Extensions supported flags
-static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
-static bool texCompDXTSupported = false; // DDS texture compression support
-static bool texCompETC1Supported = false; // ETC1 texture compression support
-static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
-static bool texCompPVRTSupported = false; // PVR texture compression support
-static bool texCompASTCSupported = false; // ASTC texture compression support
-static bool texNPOTSupported = false; // NPOT textures full support
-static bool texFloatSupported = false; // float textures support (32 bit per channel)
-static bool texDepthSupported = false; // Depth textures supported
-static bool texMirrorClampSupported = false;// Clamp mirror wrap mode supported
-static bool texAnisoFilterSupported = false;// Anisotropic texture filtering support
-static bool debugMarkerSupported = false; // Debug marker support
-static int maxDepthBits = 16; // Maximum bits for depth component
-static float maxAnisotropicLevel = 0.0f; // Maximum anisotropy level supported (minimum is 2.0f)
+static rlglData RLGL = { 0 };
+#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: VAO functionality is exposed through extensions (OES)
@@ -829,23 +859,6 @@ static PFNGLBINDVERTEXARRAYOESPROC glBindVertexArray; // Entry point poin
static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; // Entry point pointer to function glDeleteVertexArrays()
#endif
-#if defined(SUPPORT_VR_SIMULATOR)
-// VR global variables
-static VrStereoConfig vrConfig = { 0 }; // VR stereo configuration for simulator
-static RenderTexture2D stereoFbo = { 0 }; // VR stereo rendering framebuffer
-static bool vrSimulatorReady = false; // VR simulator ready flag
-static bool vrStereoRender = false; // VR stereo rendering enabled/disabled flag
- // NOTE: This flag is useful to render data over stereo image (i.e. FPS)
-#endif // SUPPORT_VR_SIMULATOR
-
-#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
-
-static int blendMode = 0; // Track current blending mode
-
-// Default framebuffer size
-static int framebufferWidth = 0; // Default framebuffer width
-static int framebufferHeight = 0; // Default framebuffer height
-
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
@@ -918,49 +931,49 @@ void rlMultMatrixf(float *matf) { glMultMatrixf(matf); }
// Choose the current matrix to be transformed
void rlMatrixMode(int mode)
{
- if (mode == RL_PROJECTION) currentMatrix = &projection;
- else if (mode == RL_MODELVIEW) currentMatrix = &modelview;
+ if (mode == RL_PROJECTION) RLGL.State.currentMatrix = &RLGL.State.projection;
+ else if (mode == RL_MODELVIEW) RLGL.State.currentMatrix = &RLGL.State.modelview;
//else if (mode == RL_TEXTURE) // Not supported
- currentMatrixMode = mode;
+ RLGL.State.currentMatrixMode = mode;
}
-// Push the current matrix into stack
+// Push the current matrix into RLGL.State.stack
void rlPushMatrix(void)
{
- if (stackCounter >= MAX_MATRIX_STACK_SIZE) TraceLog(LOG_ERROR, "Matrix stack overflow");
+ if (RLGL.State.stackCounter >= MAX_MATRIX_STACK_SIZE) TraceLog(LOG_ERROR, "Matrix RLGL.State.stack overflow");
- if (currentMatrixMode == RL_MODELVIEW)
+ if (RLGL.State.currentMatrixMode == RL_MODELVIEW)
{
- useTransformMatrix = true;
- currentMatrix = &transformMatrix;
+ RLGL.State.doTransform = true;
+ RLGL.State.currentMatrix = &RLGL.State.transform;
}
- stack[stackCounter] = *currentMatrix;
- stackCounter++;
+ RLGL.State.stack[RLGL.State.stackCounter] = *RLGL.State.currentMatrix;
+ RLGL.State.stackCounter++;
}
-// Pop lattest inserted matrix from stack
+// Pop lattest inserted matrix from RLGL.State.stack
void rlPopMatrix(void)
{
- if (stackCounter > 0)
+ if (RLGL.State.stackCounter > 0)
{
- Matrix mat = stack[stackCounter - 1];
- *currentMatrix = mat;
- stackCounter--;
+ Matrix mat = RLGL.State.stack[RLGL.State.stackCounter - 1];
+ *RLGL.State.currentMatrix = mat;
+ RLGL.State.stackCounter--;
}
- if ((stackCounter == 0) && (currentMatrixMode == RL_MODELVIEW))
+ if ((RLGL.State.stackCounter == 0) && (RLGL.State.currentMatrixMode == RL_MODELVIEW))
{
- currentMatrix = &modelview;
- useTransformMatrix = false;
+ RLGL.State.currentMatrix = &RLGL.State.modelview;
+ RLGL.State.doTransform = false;
}
}
// Reset current matrix to identity matrix
void rlLoadIdentity(void)
{
- *currentMatrix = MatrixIdentity();
+ *RLGL.State.currentMatrix = MatrixIdentity();
}
// Multiply the current matrix by a translation matrix
@@ -969,7 +982,7 @@ void rlTranslatef(float x, float y, float z)
Matrix matTranslation = MatrixTranslate(x, y, z);
// NOTE: We transpose matrix with multiplication order
- *currentMatrix = MatrixMultiply(matTranslation, *currentMatrix);
+ *RLGL.State.currentMatrix = MatrixMultiply(matTranslation, *RLGL.State.currentMatrix);
}
// Multiply the current matrix by a rotation matrix
@@ -981,7 +994,7 @@ void rlRotatef(float angleDeg, float x, float y, float z)
matRotation = MatrixRotate(Vector3Normalize(axis), angleDeg*DEG2RAD);
// NOTE: We transpose matrix with multiplication order
- *currentMatrix = MatrixMultiply(matRotation, *currentMatrix);
+ *RLGL.State.currentMatrix = MatrixMultiply(matRotation, *RLGL.State.currentMatrix);
}
// Multiply the current matrix by a scaling matrix
@@ -990,7 +1003,7 @@ void rlScalef(float x, float y, float z)
Matrix matScale = MatrixScale(x, y, z);
// NOTE: We transpose matrix with multiplication order
- *currentMatrix = MatrixMultiply(matScale, *currentMatrix);
+ *RLGL.State.currentMatrix = MatrixMultiply(matScale, *RLGL.State.currentMatrix);
}
// Multiply the current matrix by another matrix
@@ -1002,7 +1015,7 @@ void rlMultMatrixf(float *matf)
matf[2], matf[6], matf[10], matf[14],
matf[3], matf[7], matf[11], matf[15] };
- *currentMatrix = MatrixMultiply(*currentMatrix, mat);
+ *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, mat);
}
// Multiply the current matrix by a perspective matrix generated by parameters
@@ -1010,7 +1023,7 @@ void rlFrustum(double left, double right, double bottom, double top, double znea
{
Matrix matPerps = MatrixFrustum(left, right, bottom, top, znear, zfar);
- *currentMatrix = MatrixMultiply(*currentMatrix, matPerps);
+ *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, matPerps);
}
// Multiply the current matrix by an orthographic matrix generated by parameters
@@ -1018,13 +1031,13 @@ void rlOrtho(double left, double right, double bottom, double top, double znear,
{
Matrix matOrtho = MatrixOrtho(left, right, bottom, top, znear, zfar);
- *currentMatrix = MatrixMultiply(*currentMatrix, matOrtho);
+ *RLGL.State.currentMatrix = MatrixMultiply(*RLGL.State.currentMatrix, matOrtho);
}
#endif
// Set the viewport area (transformation from normalized device coordinates to window coordinates)
-// NOTE: Updates global variables: framebufferWidth, framebufferHeight
+// NOTE: Updates global variables: RLGL.State.framebufferWidth, RLGL.State.framebufferHeight
void rlViewport(int x, int y, int width, int height)
{
glViewport(x, y, width, height);
@@ -1065,36 +1078,36 @@ void rlBegin(int mode)
{
// Draw mode can be RL_LINES, RL_TRIANGLES and RL_QUADS
// NOTE: In all three cases, vertex are accumulated over default internal vertex buffer
- if (draws[drawsCounter - 1].mode != mode)
+ if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode != mode)
{
- if (draws[drawsCounter - 1].vertexCount > 0)
+ if (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount > 0)
{
- // Make sure current draws[i].vertexCount is aligned a multiple of 4,
+ // Make sure current RLGL.State.draws[i].vertexCount is aligned a multiple of 4,
// that way, following QUADS drawing will keep aligned with index processing
// It implies adding some extra alignment vertex at the end of the draw,
// those vertex are not processed but they are considered as an additional offset
// for the next set of vertex to be drawn
- if (draws[drawsCounter - 1].mode == RL_LINES) draws[drawsCounter - 1].vertexAlignment = ((draws[drawsCounter - 1].vertexCount < 4)? draws[drawsCounter - 1].vertexCount : draws[drawsCounter - 1].vertexCount%4);
- else if (draws[drawsCounter - 1].mode == RL_TRIANGLES) draws[drawsCounter - 1].vertexAlignment = ((draws[drawsCounter - 1].vertexCount < 4)? 1 : (4 - (draws[drawsCounter - 1].vertexCount%4)));
+ if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_LINES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount : RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4);
+ else if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_TRIANGLES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4)));
- else draws[drawsCounter - 1].vertexAlignment = 0;
+ else RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = 0;
- if (rlCheckBufferLimit(draws[drawsCounter - 1].vertexAlignment)) rlglDraw();
+ if (rlCheckBufferLimit(RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment)) rlglDraw();
else
{
- vertexData[currentBuffer].vCounter += draws[drawsCounter - 1].vertexAlignment;
- vertexData[currentBuffer].cCounter += draws[drawsCounter - 1].vertexAlignment;
- vertexData[currentBuffer].tcCounter += draws[drawsCounter - 1].vertexAlignment;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
- drawsCounter++;
+ RLGL.State.drawsCounter++;
}
}
- if (drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw();
+ if (RLGL.State.drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw();
- draws[drawsCounter - 1].mode = mode;
- draws[drawsCounter - 1].vertexCount = 0;
- draws[drawsCounter - 1].textureId = defaultTextureId;
+ RLGL.State.draws[RLGL.State.drawsCounter - 1].mode = mode;
+ RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount = 0;
+ RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId = RLGL.State.defaultTextureId;
}
}
@@ -1105,30 +1118,30 @@ void rlEnd(void)
// NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls
// Make sure colors count match vertex count
- if (vertexData[currentBuffer].vCounter != vertexData[currentBuffer].cCounter)
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter != RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter)
{
- int addColors = vertexData[currentBuffer].vCounter - vertexData[currentBuffer].cCounter;
+ int addColors = RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter - RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter;
for (int i = 0; i < addColors; i++)
{
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter] = vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter - 4];
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter + 1] = vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter - 3];
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter + 2] = vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter - 2];
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter + 3] = vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter - 1];
- vertexData[currentBuffer].cCounter++;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 4];
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 1] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 3];
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 2] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 2];
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 3] = RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter - 1];
+ RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter++;
}
}
// Make sure texcoords count match vertex count
- if (vertexData[currentBuffer].vCounter != vertexData[currentBuffer].tcCounter)
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter != RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter)
{
- int addTexCoords = vertexData[currentBuffer].vCounter - vertexData[currentBuffer].tcCounter;
+ int addTexCoords = RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter - RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter;
for (int i = 0; i < addTexCoords; i++)
{
- vertexData[currentBuffer].texcoords[2*vertexData[currentBuffer].tcCounter] = 0.0f;
- vertexData[currentBuffer].texcoords[2*vertexData[currentBuffer].tcCounter + 1] = 0.0f;
- vertexData[currentBuffer].tcCounter++;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter] = 0.0f;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter + 1] = 0.0f;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter++;
}
}
@@ -1137,16 +1150,16 @@ void rlEnd(void)
// NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values,
// as well as depth buffer bit-depth (16bit or 24bit or 32bit)
// Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits)
- currentDepth += (1.0f/20000.0f);
+ RLGL.State.currentDepth += (1.0f/20000.0f);
// Verify internal buffers limits
// NOTE: This check is combined with usage of rlCheckBufferLimit()
- if ((vertexData[currentBuffer].vCounter) >= (MAX_BATCH_ELEMENTS*4 - 4))
+ if ((RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter) >= (MAX_BATCH_ELEMENTS*4 - 4))
{
// WARNING: If we are between rlPushMatrix() and rlPopMatrix() and we need to force a rlglDraw(),
- // we need to call rlPopMatrix() before to recover *currentMatrix (modelview) for the next forced draw call!
- // If we have multiple matrix pushed, it will require "stackCounter" pops before launching the draw
- for (int i = stackCounter; i >= 0; i--) rlPopMatrix();
+ // we need to call rlPopMatrix() before to recover *RLGL.State.currentMatrix (RLGL.State.modelview) for the next forced draw call!
+ // If we have multiple matrix pushed, it will require "RLGL.State.stackCounter" pops before launching the draw
+ for (int i = RLGL.State.stackCounter; i >= 0; i--) rlPopMatrix();
rlglDraw();
}
}
@@ -1158,17 +1171,17 @@ void rlVertex3f(float x, float y, float z)
Vector3 vec = { x, y, z };
// Transform provided vector if required
- if (useTransformMatrix) vec = Vector3Transform(vec, transformMatrix);
+ if (RLGL.State.doTransform) vec = Vector3Transform(vec, RLGL.State.transform);
// Verify that MAX_BATCH_ELEMENTS limit not reached
- if (vertexData[currentBuffer].vCounter < (MAX_BATCH_ELEMENTS*4))
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter < (MAX_BATCH_ELEMENTS*4))
{
- vertexData[currentBuffer].vertices[3*vertexData[currentBuffer].vCounter] = vec.x;
- vertexData[currentBuffer].vertices[3*vertexData[currentBuffer].vCounter + 1] = vec.y;
- vertexData[currentBuffer].vertices[3*vertexData[currentBuffer].vCounter + 2] = vec.z;
- vertexData[currentBuffer].vCounter++;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter] = vec.x;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + 1] = vec.y;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vertices[3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + 2] = vec.z;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter++;
- draws[drawsCounter - 1].vertexCount++;
+ RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount++;
}
else TraceLog(LOG_ERROR, "MAX_BATCH_ELEMENTS overflow");
}
@@ -1176,22 +1189,22 @@ void rlVertex3f(float x, float y, float z)
// Define one vertex (position)
void rlVertex2f(float x, float y)
{
- rlVertex3f(x, y, currentDepth);
+ rlVertex3f(x, y, RLGL.State.currentDepth);
}
// Define one vertex (position)
void rlVertex2i(int x, int y)
{
- rlVertex3f((float)x, (float)y, currentDepth);
+ rlVertex3f((float)x, (float)y, RLGL.State.currentDepth);
}
// Define one vertex (texture coordinate)
// NOTE: Texture coordinates are limited to QUADS only
void rlTexCoord2f(float x, float y)
{
- vertexData[currentBuffer].texcoords[2*vertexData[currentBuffer].tcCounter] = x;
- vertexData[currentBuffer].texcoords[2*vertexData[currentBuffer].tcCounter + 1] = y;
- vertexData[currentBuffer].tcCounter++;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter] = x;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords[2*RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter + 1] = y;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter++;
}
// Define one vertex (normal)
@@ -1204,11 +1217,11 @@ void rlNormal3f(float x, float y, float z)
// Define one vertex (color)
void rlColor4ub(byte x, byte y, byte z, byte w)
{
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter] = x;
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter + 1] = y;
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter + 2] = z;
- vertexData[currentBuffer].colors[4*vertexData[currentBuffer].cCounter + 3] = w;
- vertexData[currentBuffer].cCounter++;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter] = x;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 1] = y;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 2] = z;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].colors[4*RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter + 3] = w;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter++;
}
// Define one vertex (color)
@@ -1238,35 +1251,35 @@ void rlEnableTexture(unsigned int id)
#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (draws[drawsCounter - 1].textureId != id)
+ if (RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId != id)
{
- if (draws[drawsCounter - 1].vertexCount > 0)
+ if (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount > 0)
{
- // Make sure current draws[i].vertexCount is aligned a multiple of 4,
+ // Make sure current RLGL.State.draws[i].vertexCount is aligned a multiple of 4,
// that way, following QUADS drawing will keep aligned with index processing
// It implies adding some extra alignment vertex at the end of the draw,
// those vertex are not processed but they are considered as an additional offset
// for the next set of vertex to be drawn
- if (draws[drawsCounter - 1].mode == RL_LINES) draws[drawsCounter - 1].vertexAlignment = ((draws[drawsCounter - 1].vertexCount < 4)? draws[drawsCounter - 1].vertexCount : draws[drawsCounter - 1].vertexCount%4);
- else if (draws[drawsCounter - 1].mode == RL_TRIANGLES) draws[drawsCounter - 1].vertexAlignment = ((draws[drawsCounter - 1].vertexCount < 4)? 1 : (4 - (draws[drawsCounter - 1].vertexCount%4)));
+ if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_LINES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount : RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4);
+ else if (RLGL.State.draws[RLGL.State.drawsCounter - 1].mode == RL_TRIANGLES) RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = ((RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount < 4)? 1 : (4 - (RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount%4)));
- else draws[drawsCounter - 1].vertexAlignment = 0;
+ else RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment = 0;
- if (rlCheckBufferLimit(draws[drawsCounter - 1].vertexAlignment)) rlglDraw();
+ if (rlCheckBufferLimit(RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment)) rlglDraw();
else
{
- vertexData[currentBuffer].vCounter += draws[drawsCounter - 1].vertexAlignment;
- vertexData[currentBuffer].cCounter += draws[drawsCounter - 1].vertexAlignment;
- vertexData[currentBuffer].tcCounter += draws[drawsCounter - 1].vertexAlignment;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter += RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexAlignment;
- drawsCounter++;
+ RLGL.State.drawsCounter++;
}
}
- if (drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw();
+ if (RLGL.State.drawsCounter >= MAX_DRAWCALL_REGISTERED) rlglDraw();
- draws[drawsCounter - 1].textureId = id;
- draws[drawsCounter - 1].vertexCount = 0;
+ RLGL.State.draws[RLGL.State.drawsCounter - 1].textureId = id;
+ RLGL.State.draws[RLGL.State.drawsCounter - 1].vertexCount = 0;
}
#endif
}
@@ -1280,7 +1293,7 @@ void rlDisableTexture(void)
#else
// NOTE: If quads batch limit is reached,
// we force a draw call and next batch starts
- if (vertexData[currentBuffer].vCounter >= (MAX_BATCH_ELEMENTS*4)) rlglDraw();
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter >= (MAX_BATCH_ELEMENTS*4)) rlglDraw();
#endif
}
@@ -1297,7 +1310,7 @@ void rlTextureParameters(unsigned int id, int param, int value)
if (value == RL_WRAP_MIRROR_CLAMP)
{
#if !defined(GRAPHICS_API_OPENGL_11)
- if (texMirrorClampSupported) glTexParameteri(GL_TEXTURE_2D, param, value);
+ if (RLGL.ExtSupported.texMirrorClamp) glTexParameteri(GL_TEXTURE_2D, param, value);
else TraceLog(LOG_WARNING, "Clamp mirror wrap mode not supported");
#endif
}
@@ -1309,10 +1322,10 @@ void rlTextureParameters(unsigned int id, int param, int value)
case RL_TEXTURE_ANISOTROPIC_FILTER:
{
#if !defined(GRAPHICS_API_OPENGL_11)
- if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
- else if (maxAnisotropicLevel > 0.0f)
+ if (value <= RLGL.ExtSupported.maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
+ else if (RLGL.ExtSupported.maxAnisotropicLevel > 0.0f)
{
- TraceLog(LOG_WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel);
+ TraceLog(LOG_WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, RLGL.ExtSupported.maxAnisotropicLevel);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value);
}
else TraceLog(LOG_WARNING, "Anisotropic filtering not supported");
@@ -1420,7 +1433,7 @@ void rlDeleteShader(unsigned int id)
void rlDeleteVertexArrays(unsigned int id)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (vaoSupported)
+ if (RLGL.ExtSupported.vao)
{
if (id != 0) glDeleteVertexArrays(1, &id);
TraceLog(LOG_INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id);
@@ -1435,7 +1448,7 @@ void rlDeleteBuffers(unsigned int id)
if (id != 0)
{
glDeleteBuffers(1, &id);
- if (!vaoSupported) TraceLog(LOG_INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id);
+ if (!RLGL.ExtSupported.vao) TraceLog(LOG_INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id);
}
#endif
}
@@ -1514,12 +1527,12 @@ void rlglInit(int width, int height)
#if defined(GRAPHICS_API_OPENGL_33)
// NOTE: On OpenGL 3.3 VAO and NPOT are supported by default
- vaoSupported = true;
+ RLGL.ExtSupported.vao = true;
// Multiple texture extensions supported by default
- texNPOTSupported = true;
- texFloatSupported = true;
- texDepthSupported = true;
+ RLGL.ExtSupported.texNPOT = true;
+ RLGL.ExtSupported.texFloat32 = true;
+ RLGL.ExtSupported.texDepth = true;
// We get a list of available extensions and we check for some of them (compressed textures)
// NOTE: We don't need to check again supported extensions but we do (GLAD already dealt with that)
@@ -1578,53 +1591,53 @@ void rlglInit(int width, int height)
glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
//glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES"); // NOTE: Fails in WebGL, omitted
- if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) vaoSupported = true;
+ if ((glGenVertexArrays != NULL) && (glBindVertexArray != NULL) && (glDeleteVertexArrays != NULL)) RLGL.ExtSupported.vao = true;
}
// Check NPOT textures support
// NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature
- if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) texNPOTSupported = true;
+ if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) RLGL.ExtSupported.texNPOT = true;
// Check texture float support
- if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) texFloatSupported = true;
+ if (strcmp(extList[i], (const char *)"GL_OES_texture_float") == 0) RLGL.ExtSupported.texFloat32 = true;
// Check depth texture support
if ((strcmp(extList[i], (const char *)"GL_OES_depth_texture") == 0) ||
- (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0)) texDepthSupported = true;
+ (strcmp(extList[i], (const char *)"GL_WEBGL_depth_texture") == 0)) RLGL.ExtSupported.texDepth = true;
- if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) maxDepthBits = 24;
- if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) maxDepthBits = 32;
+ if (strcmp(extList[i], (const char *)"GL_OES_depth24") == 0) RLGL.ExtSupported.maxDepthBits = 24;
+ if (strcmp(extList[i], (const char *)"GL_OES_depth32") == 0) RLGL.ExtSupported.maxDepthBits = 32;
#endif
// DDS texture compression support
if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) ||
(strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) ||
- (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) texCompDXTSupported = true;
+ (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) RLGL.ExtSupported.texCompDXT = true;
// ETC1 texture compression support
if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) ||
- (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) texCompETC1Supported = true;
+ (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) RLGL.ExtSupported.texCompETC1 = true;
// ETC2/EAC texture compression support
- if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) texCompETC2Supported = true;
+ if (strcmp(extList[i], (const char *)"GL_ARB_ES3_compatibility") == 0) RLGL.ExtSupported.texCompETC2 = true;
// PVR texture compression support
- if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) texCompPVRTSupported = true;
+ if (strcmp(extList[i], (const char *)"GL_IMG_texture_compression_pvrtc") == 0) RLGL.ExtSupported.texCompPVRT = true;
// ASTC texture compression support
- if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) texCompASTCSupported = true;
+ if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) RLGL.ExtSupported.texCompASTC = true;
// Anisotropic texture filter support
if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0)
{
- texAnisoFilterSupported = true;
- glGetFloatv(0x84FF, &maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
+ RLGL.ExtSupported.texAnisoFilter = true;
+ glGetFloatv(0x84FF, &RLGL.ExtSupported.maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
}
// Clamp mirror wrap mode supported
- if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texMirrorClampSupported = true;
+ if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) RLGL.ExtSupported.texMirrorClamp = true;
// Debug marker support
- if (strcmp(extList[i], (const char *)"GL_EXT_debug_marker") == 0) debugMarkerSupported = true;
+ if (strcmp(extList[i], (const char *)"GL_EXT_debug_marker") == 0) RLGL.ExtSupported.debugMarker = true;
}
// Free extensions pointers
@@ -1633,67 +1646,67 @@ void rlglInit(int width, int height)
#if defined(GRAPHICS_API_OPENGL_ES2)
RL_FREE(extensionsDup); // Duplicated string must be deallocated
- if (vaoSupported) TraceLog(LOG_INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully");
+ if (RLGL.ExtSupported.vao) TraceLog(LOG_INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully");
else TraceLog(LOG_WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported");
- if (texNPOTSupported) TraceLog(LOG_INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported");
+ if (RLGL.ExtSupported.texNPOT) TraceLog(LOG_INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported");
else TraceLog(LOG_WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)");
#endif
- if (texCompDXTSupported) TraceLog(LOG_INFO, "[EXTENSION] DXT compressed textures supported");
- if (texCompETC1Supported) TraceLog(LOG_INFO, "[EXTENSION] ETC1 compressed textures supported");
- if (texCompETC2Supported) TraceLog(LOG_INFO, "[EXTENSION] ETC2/EAC compressed textures supported");
- if (texCompPVRTSupported) TraceLog(LOG_INFO, "[EXTENSION] PVRT compressed textures supported");
- if (texCompASTCSupported) TraceLog(LOG_INFO, "[EXTENSION] ASTC compressed textures supported");
+ if (RLGL.ExtSupported.texCompDXT) TraceLog(LOG_INFO, "[EXTENSION] DXT compressed textures supported");
+ if (RLGL.ExtSupported.texCompETC1) TraceLog(LOG_INFO, "[EXTENSION] ETC1 compressed textures supported");
+ if (RLGL.ExtSupported.texCompETC2) TraceLog(LOG_INFO, "[EXTENSION] ETC2/EAC compressed textures supported");
+ if (RLGL.ExtSupported.texCompPVRT) TraceLog(LOG_INFO, "[EXTENSION] PVRT compressed textures supported");
+ if (RLGL.ExtSupported.texCompASTC) TraceLog(LOG_INFO, "[EXTENSION] ASTC compressed textures supported");
- if (texAnisoFilterSupported) TraceLog(LOG_INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel);
- if (texMirrorClampSupported) TraceLog(LOG_INFO, "[EXTENSION] Mirror clamp wrap texture mode supported");
+ if (RLGL.ExtSupported.texAnisoFilter) TraceLog(LOG_INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", RLGL.ExtSupported.maxAnisotropicLevel);
+ if (RLGL.ExtSupported.texMirrorClamp) TraceLog(LOG_INFO, "[EXTENSION] Mirror clamp wrap texture mode supported");
- if (debugMarkerSupported) TraceLog(LOG_INFO, "[EXTENSION] Debug Marker supported");
+ if (RLGL.ExtSupported.debugMarker) TraceLog(LOG_INFO, "[EXTENSION] Debug Marker supported");
// Initialize buffers, default shaders and default textures
//----------------------------------------------------------
// Init default white texture
unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes)
- defaultTextureId = rlLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1);
+ RLGL.State.defaultTextureId = rlLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1);
- if (defaultTextureId != 0) TraceLog(LOG_INFO, "[TEX ID %i] Base white texture loaded successfully", defaultTextureId);
+ if (RLGL.State.defaultTextureId != 0) TraceLog(LOG_INFO, "[TEX ID %i] Base white texture loaded successfully", RLGL.State.defaultTextureId);
else TraceLog(LOG_WARNING, "Base white texture could not be loaded");
// Init default Shader (customized for GL 3.3 and ES2)
- defaultShader = LoadShaderDefault();
- currentShader = defaultShader;
+ RLGL.State.defaultShader = LoadShaderDefault();
+ RLGL.State.currentShader = RLGL.State.defaultShader;
// Init default vertex arrays buffers
LoadBuffersDefault();
// Init transformations matrix accumulator
- transformMatrix = MatrixIdentity();
+ RLGL.State.transform = MatrixIdentity();
// Init draw calls tracking system
- draws = (DrawCall *)RL_MALLOC(sizeof(DrawCall)*MAX_DRAWCALL_REGISTERED);
+ RLGL.State.draws = (DrawCall *)RL_MALLOC(sizeof(DrawCall)*MAX_DRAWCALL_REGISTERED);
for (int i = 0; i < MAX_DRAWCALL_REGISTERED; i++)
{
- draws[i].mode = RL_QUADS;
- draws[i].vertexCount = 0;
- draws[i].vertexAlignment = 0;
- //draws[i].vaoId = 0;
- //draws[i].shaderId = 0;
- draws[i].textureId = defaultTextureId;
- //draws[i].projection = MatrixIdentity();
- //draws[i].modelview = MatrixIdentity();
+ RLGL.State.draws[i].mode = RL_QUADS;
+ RLGL.State.draws[i].vertexCount = 0;
+ RLGL.State.draws[i].vertexAlignment = 0;
+ //RLGL.State.draws[i].vaoId = 0;
+ //RLGL.State.draws[i].shaderId = 0;
+ RLGL.State.draws[i].textureId = RLGL.State.defaultTextureId;
+ //RLGL.State.draws[i].RLGL.State.projection = MatrixIdentity();
+ //RLGL.State.draws[i].RLGL.State.modelview = MatrixIdentity();
}
- drawsCounter = 1;
+ RLGL.State.drawsCounter = 1;
- // Init internal matrix stack (emulating OpenGL 1.1)
- for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity();
+ // Init RLGL.State.stack matrices (emulating OpenGL 1.1)
+ for (int i = 0; i < MAX_MATRIX_STACK_SIZE; i++) RLGL.State.stack[i] = MatrixIdentity();
- // Init internal projection and modelview matrices
- projection = MatrixIdentity();
- modelview = MatrixIdentity();
- currentMatrix = &modelview;
+ // Init RLGL.State.projection and RLGL.State.modelview matrices
+ RLGL.State.projection = MatrixIdentity();
+ RLGL.State.modelview = MatrixIdentity();
+ RLGL.State.currentMatrix = &RLGL.State.modelview;
#endif // GRAPHICS_API_OPENGL_33 || GRAPHICS_API_OPENGL_ES2
// Initialize OpenGL default states
@@ -1724,8 +1737,12 @@ void rlglInit(int width, int height)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D)
// Store screen size into global variables
- framebufferWidth = width;
- framebufferHeight = height;
+ RLGL.State.framebufferWidth = width;
+ RLGL.State.framebufferHeight = height;
+
+ // Init texture and rectangle used on basic shapes drawing
+ RLGL.State.shapesTexture = GetTextureDefault();
+ RLGL.State.shapesTextureRec = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f };
TraceLog(LOG_INFO, "OpenGL default states initialized successfully");
}
@@ -1736,11 +1753,11 @@ void rlglClose(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
UnloadShaderDefault(); // Unload default shader
UnloadBuffersDefault(); // Unload default buffers
- glDeleteTextures(1, &defaultTextureId); // Unload default texture
+ glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
- TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", defaultTextureId);
+ TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", RLGL.State.defaultTextureId);
- RL_FREE(draws);
+ RL_FREE(RLGL.State.draws);
#endif
}
@@ -1749,7 +1766,7 @@ void rlglDraw(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Only process data if we have data to process
- if (vertexData[currentBuffer].vCounter > 0)
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0)
{
UpdateBuffersDefault();
DrawBuffersDefault(); // NOTE: Stereo rendering is checked inside
@@ -1780,7 +1797,7 @@ bool rlCheckBufferLimit(int vCount)
{
bool overflow = false;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if ((vertexData[currentBuffer].vCounter + vCount) >= (MAX_BATCH_ELEMENTS*4)) overflow = true;
+ if ((RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter + vCount) >= (MAX_BATCH_ELEMENTS*4)) overflow = true;
#endif
return overflow;
}
@@ -1789,7 +1806,7 @@ bool rlCheckBufferLimit(int vCount)
void rlSetDebugMarker(const char *text)
{
#if defined(GRAPHICS_API_OPENGL_33)
- if (debugMarkerSupported) glInsertEventMarkerEXT(0, text);
+ if (RLGL.ExtSupported.debugMarker) glInsertEventMarkerEXT(0, text);
#endif
}
@@ -1854,32 +1871,32 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
return id;
}
#else
- if ((!texCompDXTSupported) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) ||
+ if ((!RLGL.ExtSupported.texCompDXT) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) ||
(format == COMPRESSED_DXT3_RGBA) || (format == COMPRESSED_DXT5_RGBA)))
{
TraceLog(LOG_WARNING, "DXT compressed texture format not supported");
return id;
}
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if ((!texCompETC1Supported) && (format == COMPRESSED_ETC1_RGB))
+ if ((!RLGL.ExtSupported.texCompETC1) && (format == COMPRESSED_ETC1_RGB))
{
TraceLog(LOG_WARNING, "ETC1 compressed texture format not supported");
return id;
}
- if ((!texCompETC2Supported) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA)))
+ if ((!RLGL.ExtSupported.texCompETC2) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA)))
{
TraceLog(LOG_WARNING, "ETC2 compressed texture format not supported");
return id;
}
- if ((!texCompPVRTSupported) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA)))
+ if ((!RLGL.ExtSupported.texCompPVRT) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA)))
{
TraceLog(LOG_WARNING, "PVRT compressed texture format not supported");
return id;
}
- if ((!texCompASTCSupported) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA)))
+ if ((!RLGL.ExtSupported.texCompASTC) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA)))
{
TraceLog(LOG_WARNING, "ASTC compressed texture format not supported");
return id;
@@ -1951,7 +1968,7 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
- if (texNPOTSupported)
+ if (RLGL.ExtSupported.texNPOT)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
@@ -2009,7 +2026,7 @@ unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderB
#if defined(GRAPHICS_API_OPENGL_33)
glInternalFormat = GL_DEPTH_COMPONENT24;
#elif defined(GRAPHICS_API_OPENGL_ES2)
- if (maxDepthBits >= 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES;
+ if (RLGL.ExtSupported.maxDepthBits >= 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES;
#endif
}
@@ -2018,11 +2035,11 @@ unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderB
#if defined(GRAPHICS_API_OPENGL_33)
glInternalFormat = GL_DEPTH_COMPONENT32;
#elif defined(GRAPHICS_API_OPENGL_ES2)
- if (maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES;
+ if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES;
#endif
}
- if (!useRenderBuffer && texDepthSupported)
+ if (!useRenderBuffer && RLGL.ExtSupported.texDepth)
{
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
@@ -2059,7 +2076,7 @@ unsigned int rlLoadTextureCubemap(void *data, int size, int format)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
unsigned int dataSize = GetPixelDataSize(size, size, format);
-
+
glGenTextures(1, &cubemapId);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapId);
@@ -2143,9 +2160,9 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
case UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
case UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
#if !defined(GRAPHICS_API_OPENGL_11)
- case UNCOMPRESSED_R32: if (texFloatSupported) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
- case UNCOMPRESSED_R32G32B32: if (texFloatSupported) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
- case UNCOMPRESSED_R32G32B32A32: if (texFloatSupported) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
+ case UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_LUMINANCE; *glFormat = GL_LUMINANCE; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
+ case UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB; *glFormat = GL_RGB; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
+ case UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA; *glFormat = GL_RGBA; *glType = GL_FLOAT; break; // NOTE: Requires extension OES_texture_float
#endif
#elif defined(GRAPHICS_API_OPENGL_33)
case UNCOMPRESSED_GRAYSCALE: *glInternalFormat = GL_R8; *glFormat = GL_RED; *glType = GL_UNSIGNED_BYTE; break;
@@ -2155,22 +2172,22 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
case UNCOMPRESSED_R5G5B5A1: *glInternalFormat = GL_RGB5_A1; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_5_5_5_1; break;
case UNCOMPRESSED_R4G4B4A4: *glInternalFormat = GL_RGBA4; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_SHORT_4_4_4_4; break;
case UNCOMPRESSED_R8G8B8A8: *glInternalFormat = GL_RGBA8; *glFormat = GL_RGBA; *glType = GL_UNSIGNED_BYTE; break;
- case UNCOMPRESSED_R32: if (texFloatSupported) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
- case UNCOMPRESSED_R32G32B32: if (texFloatSupported) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
- case UNCOMPRESSED_R32G32B32A32: if (texFloatSupported) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
+ case UNCOMPRESSED_R32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_R32F; *glFormat = GL_RED; *glType = GL_FLOAT; break;
+ case UNCOMPRESSED_R32G32B32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGB32F; *glFormat = GL_RGB; *glType = GL_FLOAT; break;
+ case UNCOMPRESSED_R32G32B32A32: if (RLGL.ExtSupported.texFloat32) *glInternalFormat = GL_RGBA32F; *glFormat = GL_RGBA; *glType = GL_FLOAT; break;
#endif
#if !defined(GRAPHICS_API_OPENGL_11)
- case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
- case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
- case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
- case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
- case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
- case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
- case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
- case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
- case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
- case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
- case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
+ case COMPRESSED_DXT1_RGB: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; break;
+ case COMPRESSED_DXT1_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
+ case COMPRESSED_DXT3_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
+ case COMPRESSED_DXT5_RGBA: if (RLGL.ExtSupported.texCompDXT) *glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
+ case COMPRESSED_ETC1_RGB: if (RLGL.ExtSupported.texCompETC1) *glInternalFormat = GL_ETC1_RGB8_OES; break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3
+ case COMPRESSED_ETC2_RGB: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGB8_ETC2; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
+ case COMPRESSED_ETC2_EAC_RGBA: if (RLGL.ExtSupported.texCompETC2) *glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
+ case COMPRESSED_PVRT_RGB: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
+ case COMPRESSED_PVRT_RGBA: if (RLGL.ExtSupported.texCompPVRT) *glInternalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; break; // NOTE: Requires PowerVR GPU
+ case COMPRESSED_ASTC_4x4_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
+ case COMPRESSED_ASTC_8x8_RGBA: if (RLGL.ExtSupported.texCompASTC) *glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR; break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
#endif
default: TraceLog(LOG_WARNING, "Texture format not supported"); break;
}
@@ -2189,7 +2206,7 @@ RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depth
RenderTexture2D target = { 0 };
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (useDepthTexture && texDepthSupported) target.depthTexture = true;
+ if (useDepthTexture && RLGL.ExtSupported.texDepth) target.depthTexture = true;
// Create the framebuffer object
glGenFramebuffers(1, &target.id);
@@ -2337,7 +2354,7 @@ void rlGenerateMipmaps(Texture2D *texture)
else TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps could not be generated for texture format", texture->id);
}
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if ((texIsPOT) || (texNPOTSupported))
+ if ((texIsPOT) || (RLGL.ExtSupported.texNPOT))
{
//glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
@@ -2380,7 +2397,7 @@ void rlLoadMesh(Mesh *mesh, bool dynamic)
int drawHint = GL_STATIC_DRAW;
if (dynamic) drawHint = GL_DYNAMIC_DRAW;
- if (vaoSupported)
+ if (RLGL.ExtSupported.vao)
{
// Initialize Quads VAO (Buffer A)
glGenVertexArrays(1, &mesh->vaoId);
@@ -2474,7 +2491,7 @@ void rlLoadMesh(Mesh *mesh, bool dynamic)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->triangleCount*3, mesh->indices, drawHint);
}
- if (vaoSupported)
+ if (RLGL.ExtSupported.vao)
{
if (mesh->vaoId > 0) TraceLog(LOG_INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId);
else TraceLog(LOG_WARNING, "Mesh could not be uploaded to VRAM (GPU)");
@@ -2495,7 +2512,7 @@ unsigned int rlLoadAttribBuffer(unsigned int vaoId, int shaderLoc, void *buffer,
int drawHint = GL_STATIC_DRAW;
if (dynamic) drawHint = GL_DYNAMIC_DRAW;
- if (vaoSupported) glBindVertexArray(vaoId);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(vaoId);
glGenBuffers(1, &id);
glBindBuffer(GL_ARRAY_BUFFER, id);
@@ -2503,7 +2520,7 @@ unsigned int rlLoadAttribBuffer(unsigned int vaoId, int shaderLoc, void *buffer,
glVertexAttribPointer(shaderLoc, 2, GL_FLOAT, 0, 0, 0);
glEnableVertexAttribArray(shaderLoc);
- if (vaoSupported) glBindVertexArray(0);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
#endif
return id;
@@ -2522,7 +2539,7 @@ void rlUpdateMeshAt(Mesh mesh, int buffer, int num, int index)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Activate mesh VAO
- if (vaoSupported) glBindVertexArray(mesh.vaoId);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(mesh.vaoId);
switch (buffer)
{
@@ -2588,7 +2605,7 @@ void rlUpdateMeshAt(Mesh mesh, int buffer, int num, int index)
}
// Unbind the current VAO
- if (vaoSupported) glBindVertexArray(0);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
// Another option would be using buffer mapping...
//mesh.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
@@ -2655,21 +2672,21 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
(float)material.maps[MAP_SPECULAR].color.b/255.0f,
(float)material.maps[MAP_SPECULAR].color.a/255.0f);
- if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview);
- if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection);
+ if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], RLGL.State.modelview);
+ if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], RLGL.State.projection);
// At this point the modelview matrix just contains the view matrix (camera)
// That's because BeginMode3D() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix()
- Matrix matView = modelview; // View matrix (camera)
- Matrix matProjection = projection; // Projection matrix (perspective)
+ Matrix matView = RLGL.State.modelview; // View matrix (camera)
+ Matrix matProjection = RLGL.State.projection; // Projection matrix (perspective)
- // TODO: Consider possible transform matrices in the stack
+ // TODO: Consider possible transform matrices in the RLGL.State.stack
// Is this the right order? or should we start with the first stored matrix instead of the last one?
//Matrix matStackTransform = MatrixIdentity();
- //for (int i = stackCounter; i > 0; i--) matStackTransform = MatrixMultiply(stack[i], matStackTransform);
+ //for (int i = RLGL.State.stackCounter; i > 0; i--) matStackTransform = MatrixMultiply(RLGL.State.stack[i], matStackTransform);
// Transform to camera-space coordinates
- Matrix matModelView = MatrixMultiply(transform, MatrixMultiply(transformMatrix, matView));
+ Matrix matModelView = MatrixMultiply(transform, MatrixMultiply(RLGL.State.transform, matView));
//-----------------------------------------------------
// Bind active texture maps (if available)
@@ -2686,7 +2703,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
}
// Bind vertex array objects (or VBOs)
- if (vaoSupported) glBindVertexArray(mesh.vaoId);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(mesh.vaoId);
else
{
// Bind mesh VBO data: vertex position (shader-location = 0)
@@ -2746,18 +2763,18 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
int eyesCount = 1;
#if defined(SUPPORT_VR_SIMULATOR)
- if (vrStereoRender) eyesCount = 2;
+ if (RLGL.Vr.stereoRender) eyesCount = 2;
#endif
for (int eye = 0; eye < eyesCount; eye++)
{
- if (eyesCount == 1) modelview = matModelView;
+ if (eyesCount == 1) RLGL.State.modelview = matModelView;
#if defined(SUPPORT_VR_SIMULATOR)
else SetStereoView(eye, matProjection, matModelView);
#endif
// Calculate model-view-projection matrix (MVP)
- Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates
+ Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection); // Transform to screen-space coordinates
// Send combined model-view-projection matrix to shader
glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP));
@@ -2776,7 +2793,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
}
// Unind vertex array objects (or VBOs)
- if (vaoSupported) glBindVertexArray(0);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
else
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
@@ -2786,10 +2803,10 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform)
// Unbind shader program
glUseProgram(0);
- // Restore projection/modelview matrices
+ // Restore RLGL.State.projection/RLGL.State.modelview matrices
// NOTE: In stereo rendering matrices are being modified to fit every eye
- projection = matProjection;
- modelview = matView;
+ RLGL.State.projection = matProjection;
+ RLGL.State.modelview = matView;
#endif
}
@@ -2927,7 +2944,7 @@ Texture2D GetTextureDefault(void)
{
Texture2D texture = { 0 };
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- texture.id = defaultTextureId;
+ texture.id = RLGL.State.defaultTextureId;
texture.width = 1;
texture.height = 1;
texture.mipmaps = 1;
@@ -2936,11 +2953,30 @@ Texture2D GetTextureDefault(void)
return texture;
}
+// Get texture to draw shapes (RAII)
+Texture2D GetShapesTexture(void)
+{
+ return RLGL.State.shapesTexture;
+}
+
+// Get texture rectangle to draw shapes
+Rectangle GetShapesTextureRec(void)
+{
+ return RLGL.State.shapesTextureRec;
+}
+
+// Define default texture used to draw shapes
+void SetShapesTexture(Texture2D texture, Rectangle source)
+{
+ RLGL.State.shapesTexture = texture;
+ RLGL.State.shapesTextureRec = source;
+}
+
// Get default shader
Shader GetShaderDefault(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- return defaultShader;
+ return RLGL.State.defaultShader;
#else
Shader shader = { 0 };
return shader;
@@ -3012,24 +3048,24 @@ Shader LoadShaderCode(const char *vsCode, const char *fsCode)
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- unsigned int vertexShaderId = defaultVShaderId;
- unsigned int fragmentShaderId = defaultFShaderId;
+ unsigned int vertexShaderId = RLGL.State.defaultVShaderId;
+ unsigned int fragmentShaderId = RLGL.State.defaultFShaderId;
if (vsCode != NULL) vertexShaderId = CompileShader(vsCode, GL_VERTEX_SHADER);
if (fsCode != NULL) fragmentShaderId = CompileShader(fsCode, GL_FRAGMENT_SHADER);
- if ((vertexShaderId == defaultVShaderId) && (fragmentShaderId == defaultFShaderId)) shader = defaultShader;
+ if ((vertexShaderId == RLGL.State.defaultVShaderId) && (fragmentShaderId == RLGL.State.defaultFShaderId)) shader = RLGL.State.defaultShader;
else
{
shader.id = LoadShaderProgram(vertexShaderId, fragmentShaderId);
- if (vertexShaderId != defaultVShaderId) glDeleteShader(vertexShaderId);
- if (fragmentShaderId != defaultFShaderId) glDeleteShader(fragmentShaderId);
+ if (vertexShaderId != RLGL.State.defaultVShaderId) glDeleteShader(vertexShaderId);
+ if (fragmentShaderId != RLGL.State.defaultFShaderId) glDeleteShader(fragmentShaderId);
if (shader.id == 0)
{
TraceLog(LOG_WARNING, "Custom shader could not be loaded");
- shader = defaultShader;
+ shader = RLGL.State.defaultShader;
}
// After shader loading, we TRY to set default location names
@@ -3080,10 +3116,10 @@ void UnloadShader(Shader shader)
void BeginShaderMode(Shader shader)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (currentShader.id != shader.id)
+ if (RLGL.State.currentShader.id != shader.id)
{
rlglDraw();
- currentShader = shader;
+ RLGL.State.currentShader = shader;
}
#endif
}
@@ -3092,7 +3128,7 @@ void BeginShaderMode(Shader shader)
void EndShaderMode(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- BeginShaderMode(defaultShader);
+ BeginShaderMode(RLGL.State.defaultShader);
#endif
}
@@ -3165,10 +3201,10 @@ void SetShaderValueTexture(Shader shader, int uniformLoc, Texture2D texture)
}
// Set a custom projection matrix (replaces internal projection matrix)
-void SetMatrixProjection(Matrix proj)
+void SetMatrixProjection(Matrix projection)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- projection = proj;
+ RLGL.State.projection = projection;
#endif
}
@@ -3184,7 +3220,7 @@ Matrix GetMatrixProjection(void) {
m.m12 = mat[12]; m.m13 = mat[13]; m.m14 = mat[14]; m.m15 = mat[15];
return m;
#else
- return projection;
+ return RLGL.State.projection;
#endif
#
}
@@ -3193,7 +3229,7 @@ Matrix GetMatrixProjection(void) {
void SetMatrixModelview(Matrix view)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- modelview = view;
+ RLGL.State.modelview = view;
#endif
}
@@ -3209,7 +3245,7 @@ Matrix GetMatrixModelview(void)
matrix.m8 = mat[8]; matrix.m9 = mat[9]; matrix.m10 = mat[10]; matrix.m11 = mat[11];
matrix.m12 = mat[12]; matrix.m13 = mat[13]; matrix.m14 = mat[14]; matrix.m15 = mat[15];
#else
- matrix = modelview;
+ matrix = RLGL.State.modelview;
#endif
return matrix;
}
@@ -3251,7 +3287,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D map, int size)
#if defined(GRAPHICS_API_OPENGL_33)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB32F, size, size, 0, GL_RGB, GL_FLOAT, NULL);
#elif defined(GRAPHICS_API_OPENGL_ES2)
- if (texFloatSupported) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
+ if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
#endif
}
@@ -3296,7 +3332,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D map, int size)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Reset viewport dimensions to default
- glViewport(0, 0, framebufferWidth, framebufferHeight);
+ glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
//glEnable(GL_CULL_FACE);
// NOTE: Texture2D is a GL_TEXTURE_CUBE_MAP, not a GL_TEXTURE_2D!
@@ -3374,7 +3410,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Reset viewport dimensions to default
- glViewport(0, 0, framebufferWidth, framebufferHeight);
+ glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
irradiance.width = size;
irradiance.height = size;
@@ -3469,7 +3505,7 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Reset viewport dimensions to default
- glViewport(0, 0, framebufferWidth, framebufferHeight);
+ glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
prefilter.width = size;
prefilter.height = size;
@@ -3492,7 +3528,7 @@ Texture2D GenTextureBRDF(Shader shader, int size)
#if defined(GRAPHICS_API_OPENGL_33)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, size, size, 0, GL_RGB, GL_FLOAT, NULL);
#elif defined(GRAPHICS_API_OPENGL_ES2)
- if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
+ if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
#endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -3526,7 +3562,7 @@ Texture2D GenTextureBRDF(Shader shader, int size)
glDeleteFramebuffers(1, &fbo);
// Reset viewport dimensions to default
- glViewport(0, 0, framebufferWidth, framebufferHeight);
+ glViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
brdf.width = size;
brdf.height = size;
@@ -3540,6 +3576,8 @@ Texture2D GenTextureBRDF(Shader shader, int size)
// NOTE: Only 3 blending modes supported, default blend mode is alpha
void BeginBlendMode(int mode)
{
+ static int blendMode = 0; // Track current blending mode
+
if ((blendMode != mode) && (mode < 3))
{
rlglDraw();
@@ -3564,15 +3602,15 @@ void EndBlendMode(void)
#if defined(SUPPORT_VR_SIMULATOR)
// Init VR simulator for selected device parameters
-// NOTE: It modifies the global variable: stereoFbo
+// NOTE: It modifies the global variable: RLGL.Vr.stereoFbo
void InitVrSimulator(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Initialize framebuffer and textures for stereo rendering
// NOTE: Screen size should match HMD aspect ratio
- stereoFbo = rlLoadRenderTexture(framebufferWidth, framebufferHeight, UNCOMPRESSED_R8G8B8A8, 24, false);
+ RLGL.Vr.stereoFbo = rlLoadRenderTexture(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, UNCOMPRESSED_R8G8B8A8, 24, false);
- vrSimulatorReady = true;
+ RLGL.Vr.simulatorReady = true;
#else
TraceLog(LOG_WARNING, "VR Simulator not supported on OpenGL 1.1");
#endif
@@ -3589,7 +3627,7 @@ void UpdateVrTracking(Camera *camera)
void CloseVrSimulator(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (vrSimulatorReady) rlDeleteRenderTextures(stereoFbo); // Unload stereo framebuffer and texture
+ if (RLGL.Vr.simulatorReady) rlDeleteRenderTextures(RLGL.Vr.stereoFbo); // Unload stereo framebuffer and texture
#endif
}
@@ -3597,11 +3635,11 @@ void CloseVrSimulator(void)
void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- // Reset vrConfig for a new values assignment
- memset(&vrConfig, 0, sizeof(vrConfig));
+ // Reset RLGL.Vr.config for a new values assignment
+ memset(&RLGL.Vr.config, 0, sizeof(RLGL.Vr.config));
// Assign distortion shader
- vrConfig.distortionShader = distortion;
+ RLGL.Vr.config.distortionShader = distortion;
// Compute aspect ratio
float aspect = ((float)hmd.hResolution*0.5f)/(float)hmd.vResolution;
@@ -3642,37 +3680,37 @@ void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion)
// Compute camera projection matrices
float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1]
Matrix proj = MatrixPerspective(fovy, aspect, DEFAULT_NEAR_CULL_DISTANCE, DEFAULT_FAR_CULL_DISTANCE);
- vrConfig.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f));
- vrConfig.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f));
+ RLGL.Vr.config.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f));
+ RLGL.Vr.config.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f));
// Compute camera transformation matrices
// NOTE: Camera movement might seem more natural if we model the head.
// Our axis of rotation is the base of our head, so we might want to add
// some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions.
- vrConfig.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
- vrConfig.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
+ RLGL.Vr.config.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
+ RLGL.Vr.config.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f);
// Compute eyes Viewports
- vrConfig.eyeViewportRight[2] = hmd.hResolution/2;
- vrConfig.eyeViewportRight[3] = hmd.vResolution;
+ RLGL.Vr.config.eyeViewportRight[2] = hmd.hResolution/2;
+ RLGL.Vr.config.eyeViewportRight[3] = hmd.vResolution;
- vrConfig.eyeViewportLeft[0] = hmd.hResolution/2;
- vrConfig.eyeViewportLeft[1] = 0;
- vrConfig.eyeViewportLeft[2] = hmd.hResolution/2;
- vrConfig.eyeViewportLeft[3] = hmd.vResolution;
+ RLGL.Vr.config.eyeViewportLeft[0] = hmd.hResolution/2;
+ RLGL.Vr.config.eyeViewportLeft[1] = 0;
+ RLGL.Vr.config.eyeViewportLeft[2] = hmd.hResolution/2;
+ RLGL.Vr.config.eyeViewportLeft[3] = hmd.vResolution;
- if (vrConfig.distortionShader.id > 0)
+ if (RLGL.Vr.config.distortionShader.id > 0)
{
// Update distortion shader with lens and distortion-scale parameters
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, UNIFORM_VEC2);
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, UNIFORM_VEC2);
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftScreenCenter"), leftScreenCenter, UNIFORM_VEC2);
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightScreenCenter"), rightScreenCenter, UNIFORM_VEC2);
-
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scale"), scale, UNIFORM_VEC2);
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, UNIFORM_VEC2);
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, UNIFORM_VEC4);
- SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, UNIFORM_VEC4);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "leftLensCenter"), leftLensCenter, UNIFORM_VEC2);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "rightLensCenter"), rightLensCenter, UNIFORM_VEC2);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "leftScreenCenter"), leftScreenCenter, UNIFORM_VEC2);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "rightScreenCenter"), rightScreenCenter, UNIFORM_VEC2);
+
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "scale"), scale, UNIFORM_VEC2);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "scaleIn"), scaleIn, UNIFORM_VEC2);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "hmdWarpParam"), hmd.lensDistortionValues, UNIFORM_VEC4);
+ SetShaderValue(RLGL.Vr.config.distortionShader, GetShaderLocation(RLGL.Vr.config.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, UNIFORM_VEC4);
}
#endif
}
@@ -3681,7 +3719,7 @@ void SetVrConfiguration(VrDeviceInfo hmd, Shader distortion)
bool IsVrSimulatorReady(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- return vrSimulatorReady;
+ return RLGL.Vr.simulatorReady;
#else
return false;
#endif
@@ -3691,18 +3729,18 @@ bool IsVrSimulatorReady(void)
void ToggleVrMode(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- vrSimulatorReady = !vrSimulatorReady;
+ RLGL.Vr.simulatorReady = !RLGL.Vr.simulatorReady;
- if (!vrSimulatorReady)
+ if (!RLGL.Vr.simulatorReady)
{
- vrStereoRender = false;
+ RLGL.Vr.stereoRender = false;
// Reset viewport and default projection-modelview matrices
- rlViewport(0, 0, framebufferWidth, framebufferHeight);
- projection = MatrixOrtho(0.0, framebufferWidth, framebufferHeight, 0.0, 0.0, 1.0);
- modelview = MatrixIdentity();
+ rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
+ RLGL.State.projection = MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0);
+ RLGL.State.modelview = MatrixIdentity();
}
- else vrStereoRender = true;
+ else RLGL.Vr.stereoRender = true;
#endif
}
@@ -3710,16 +3748,15 @@ void ToggleVrMode(void)
void BeginVrDrawing(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (vrSimulatorReady)
+ if (RLGL.Vr.simulatorReady)
{
-
- rlEnableRenderTexture(stereoFbo.id); // Setup framebuffer for stereo rendering
+ rlEnableRenderTexture(RLGL.Vr.stereoFbo.id); // Setup framebuffer for stereo rendering
//glEnable(GL_FRAMEBUFFER_SRGB); // Enable SRGB framebuffer (only if required)
//glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
rlClearScreenBuffers(); // Clear current framebuffer
- vrStereoRender = true;
+ RLGL.Vr.stereoRender = true;
}
#endif
}
@@ -3728,29 +3765,29 @@ void BeginVrDrawing(void)
void EndVrDrawing(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (vrSimulatorReady)
+ if (RLGL.Vr.simulatorReady)
{
- vrStereoRender = false; // Disable stereo render
+ RLGL.Vr.stereoRender = false; // Disable stereo render
rlDisableRenderTexture(); // Unbind current framebuffer
rlClearScreenBuffers(); // Clear current framebuffer
// Set viewport to default framebuffer size (screen size)
- rlViewport(0, 0, framebufferWidth, framebufferHeight);
+ rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
// Let rlgl reconfigure internal matrices
rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix
rlLoadIdentity(); // Reset internal projection matrix
- rlOrtho(0.0, framebufferWidth, framebufferHeight, 0.0, 0.0, 1.0); // Recalculate internal projection matrix
+ rlOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0); // Recalculate internal RLGL.State.projection matrix
rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
rlLoadIdentity(); // Reset internal modelview matrix
- // Draw RenderTexture (stereoFbo) using distortion shader if available
- if (vrConfig.distortionShader.id > 0) currentShader = vrConfig.distortionShader;
- else currentShader = GetShaderDefault();
+ // Draw RenderTexture (RLGL.Vr.stereoFbo) using distortion shader if available
+ if (RLGL.Vr.config.distortionShader.id > 0) RLGL.State.currentShader = RLGL.Vr.config.distortionShader;
+ else RLGL.State.currentShader = GetShaderDefault();
- rlEnableTexture(stereoFbo.texture.id);
+ rlEnableTexture(RLGL.Vr.stereoFbo.texture.id);
rlPushMatrix();
rlBegin(RL_QUADS);
@@ -3763,15 +3800,15 @@ void EndVrDrawing(void)
// Bottom-right corner for texture and quad
rlTexCoord2f(0.0f, 0.0f);
- rlVertex2f(0.0f, (float)stereoFbo.texture.height);
+ rlVertex2f(0.0f, (float)RLGL.Vr.stereoFbo.texture.height);
// Top-right corner for texture and quad
rlTexCoord2f(1.0f, 0.0f);
- rlVertex2f( (float)stereoFbo.texture.width, (float)stereoFbo.texture.height);
+ rlVertex2f((float)RLGL.Vr.stereoFbo.texture.width, (float)RLGL.Vr.stereoFbo.texture.height);
// Top-left corner for texture and quad
rlTexCoord2f(1.0f, 1.0f);
- rlVertex2f( (float)stereoFbo.texture.width, 0.0f);
+ rlVertex2f((float)RLGL.Vr.stereoFbo.texture.width, 0.0f);
rlEnd();
rlPopMatrix();
@@ -3781,13 +3818,13 @@ void EndVrDrawing(void)
UpdateBuffersDefault();
DrawBuffersDefault();
- // Restore defaultShader
- currentShader = defaultShader;
+ // Restore RLGL.State.defaultShader
+ RLGL.State.currentShader = RLGL.State.defaultShader;
// Reset viewport and default projection-modelview matrices
- rlViewport(0, 0, framebufferWidth, framebufferHeight);
- projection = MatrixOrtho(0.0, framebufferWidth, framebufferHeight, 0.0, 0.0, 1.0);
- modelview = MatrixIdentity();
+ rlViewport(0, 0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
+ RLGL.State.projection = MatrixOrtho(0.0, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, 0.0, 0.0, 1.0);
+ RLGL.State.modelview = MatrixIdentity();
rlDisableDepthTest();
}
@@ -3965,10 +4002,10 @@ static Shader LoadShaderDefault(void)
"} \n";
// NOTE: Compiled vertex/fragment shaders are kept for re-use
- defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader
- defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader
+ RLGL.State.defaultVShaderId = CompileShader(defaultVShaderStr, GL_VERTEX_SHADER); // Compile default vertex shader
+ RLGL.State.defaultFShaderId = CompileShader(defaultFShaderStr, GL_FRAGMENT_SHADER); // Compile default fragment shader
- shader.id = LoadShaderProgram(defaultVShaderId, defaultFShaderId);
+ shader.id = LoadShaderProgram(RLGL.State.defaultVShaderId, RLGL.State.defaultFShaderId);
if (shader.id > 0)
{
@@ -4030,12 +4067,12 @@ static void UnloadShaderDefault(void)
{
glUseProgram(0);
- glDetachShader(defaultShader.id, defaultVShaderId);
- glDetachShader(defaultShader.id, defaultFShaderId);
- glDeleteShader(defaultVShaderId);
- glDeleteShader(defaultFShaderId);
+ glDetachShader(RLGL.State.defaultShader.id, RLGL.State.defaultVShaderId);
+ glDetachShader(RLGL.State.defaultShader.id, RLGL.State.defaultFShaderId);
+ glDeleteShader(RLGL.State.defaultVShaderId);
+ glDeleteShader(RLGL.State.defaultFShaderId);
- glDeleteProgram(defaultShader.id);
+ glDeleteProgram(RLGL.State.defaultShader.id);
}
// Load default internal buffers
@@ -4045,37 +4082,37 @@ static void LoadBuffersDefault(void)
//--------------------------------------------------------------------------------------------
for (int i = 0; i < MAX_BATCH_BUFFERING; i++)
{
- vertexData[i].vertices = (float *)RL_MALLOC(sizeof(float)*3*4*MAX_BATCH_ELEMENTS); // 3 float by vertex, 4 vertex by quad
- vertexData[i].texcoords = (float *)RL_MALLOC(sizeof(float)*2*4*MAX_BATCH_ELEMENTS); // 2 float by texcoord, 4 texcoord by quad
- vertexData[i].colors = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS); // 4 float by color, 4 colors by quad
+ RLGL.State.vertexData[i].vertices = (float *)RL_MALLOC(sizeof(float)*3*4*MAX_BATCH_ELEMENTS); // 3 float by vertex, 4 vertex by quad
+ RLGL.State.vertexData[i].texcoords = (float *)RL_MALLOC(sizeof(float)*2*4*MAX_BATCH_ELEMENTS); // 2 float by texcoord, 4 texcoord by quad
+ RLGL.State.vertexData[i].colors = (unsigned char *)RL_MALLOC(sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS); // 4 float by color, 4 colors by quad
#if defined(GRAPHICS_API_OPENGL_33)
- vertexData[i].indices = (unsigned int *)RL_MALLOC(sizeof(unsigned int)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices)
+ RLGL.State.vertexData[i].indices = (unsigned int *)RL_MALLOC(sizeof(unsigned int)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices)
#elif defined(GRAPHICS_API_OPENGL_ES2)
- vertexData[i].indices = (unsigned short *)RL_MALLOC(sizeof(unsigned short)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices)
+ RLGL.State.vertexData[i].indices = (unsigned short *)RL_MALLOC(sizeof(unsigned short)*6*MAX_BATCH_ELEMENTS); // 6 int by quad (indices)
#endif
- for (int j = 0; j < (3*4*MAX_BATCH_ELEMENTS); j++) vertexData[i].vertices[j] = 0.0f;
- for (int j = 0; j < (2*4*MAX_BATCH_ELEMENTS); j++) vertexData[i].texcoords[j] = 0.0f;
- for (int j = 0; j < (4*4*MAX_BATCH_ELEMENTS); j++) vertexData[i].colors[j] = 0;
+ for (int j = 0; j < (3*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].vertices[j] = 0.0f;
+ for (int j = 0; j < (2*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].texcoords[j] = 0.0f;
+ for (int j = 0; j < (4*4*MAX_BATCH_ELEMENTS); j++) RLGL.State.vertexData[i].colors[j] = 0;
int k = 0;
// Indices can be initialized right now
for (int j = 0; j < (6*MAX_BATCH_ELEMENTS); j += 6)
{
- vertexData[i].indices[j] = 4*k;
- vertexData[i].indices[j + 1] = 4*k + 1;
- vertexData[i].indices[j + 2] = 4*k + 2;
- vertexData[i].indices[j + 3] = 4*k;
- vertexData[i].indices[j + 4] = 4*k + 2;
- vertexData[i].indices[j + 5] = 4*k + 3;
+ RLGL.State.vertexData[i].indices[j] = 4*k;
+ RLGL.State.vertexData[i].indices[j + 1] = 4*k + 1;
+ RLGL.State.vertexData[i].indices[j + 2] = 4*k + 2;
+ RLGL.State.vertexData[i].indices[j + 3] = 4*k;
+ RLGL.State.vertexData[i].indices[j + 4] = 4*k + 2;
+ RLGL.State.vertexData[i].indices[j + 5] = 4*k + 3;
k++;
}
- vertexData[i].vCounter = 0;
- vertexData[i].tcCounter = 0;
- vertexData[i].cCounter = 0;
+ RLGL.State.vertexData[i].vCounter = 0;
+ RLGL.State.vertexData[i].tcCounter = 0;
+ RLGL.State.vertexData[i].cCounter = 0;
}
TraceLog(LOG_INFO, "Internal buffers initialized successfully (CPU)");
@@ -4085,49 +4122,49 @@ static void LoadBuffersDefault(void)
//--------------------------------------------------------------------------------------------
for (int i = 0; i < MAX_BATCH_BUFFERING; i++)
{
- if (vaoSupported)
+ if (RLGL.ExtSupported.vao)
{
// Initialize Quads VAO
- glGenVertexArrays(1, &vertexData[i].vaoId);
- glBindVertexArray(vertexData[i].vaoId);
+ glGenVertexArrays(1, &RLGL.State.vertexData[i].vaoId);
+ glBindVertexArray(RLGL.State.vertexData[i].vaoId);
}
// Quads - Vertex buffers binding and attributes enable
// Vertex position buffer (shader-location = 0)
- glGenBuffers(1, &vertexData[i].vboId[0]);
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[i].vboId[0]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, vertexData[i].vertices, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]);
- glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
+ glGenBuffers(1, &RLGL.State.vertexData[i].vboId[0]);
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[0]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].vertices, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
// Vertex texcoord buffer (shader-location = 1)
- glGenBuffers(1, &vertexData[i].vboId[1]);
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[i].vboId[1]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, vertexData[i].texcoords, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_TEXCOORD01]);
- glVertexAttribPointer(currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
+ glGenBuffers(1, &RLGL.State.vertexData[i].vboId[1]);
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[1]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].texcoords, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
// Vertex color buffer (shader-location = 3)
- glGenBuffers(1, &vertexData[i].vboId[2]);
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[i].vboId[2]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS, vertexData[i].colors, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]);
- glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glGenBuffers(1, &RLGL.State.vertexData[i].vboId[2]);
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[2]);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].colors, GL_DYNAMIC_DRAW);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
// Fill index buffer
- glGenBuffers(1, &vertexData[i].vboId[3]);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexData[i].vboId[3]);
+ glGenBuffers(1, &RLGL.State.vertexData[i].vboId[3]);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RLGL.State.vertexData[i].vboId[3]);
#if defined(GRAPHICS_API_OPENGL_33)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_BATCH_ELEMENTS, vertexData[i].indices, GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].indices, GL_STATIC_DRAW);
#elif defined(GRAPHICS_API_OPENGL_ES2)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_BATCH_ELEMENTS, vertexData[i].indices, GL_STATIC_DRAW);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[i].indices, GL_STATIC_DRAW);
#endif
}
TraceLog(LOG_INFO, "Internal buffers uploaded successfully (GPU)");
// Unbind the current VAO
- if (vaoSupported) glBindVertexArray(0);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
//--------------------------------------------------------------------------------------------
}
@@ -4137,25 +4174,25 @@ static void LoadBuffersDefault(void)
static void UpdateBuffersDefault(void)
{
// Update vertex buffers data
- if (vertexData[currentBuffer].vCounter > 0)
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0)
{
// Activate elements VAO
- if (vaoSupported) glBindVertexArray(vertexData[currentBuffer].vaoId);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(RLGL.State.vertexData[RLGL.State.currentBuffer].vaoId);
// Vertex positions buffer
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[currentBuffer].vboId[0]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*vertexData[currentBuffer].vCounter, vertexData[currentBuffer].vertices);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, vertexData[currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].vertices);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].vertices, GL_DYNAMIC_DRAW); // Update all buffer
// Texture coordinates buffer
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[currentBuffer].vboId[1]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*vertexData[currentBuffer].vCounter, vertexData[currentBuffer].texcoords);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, vertexData[currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].texcoords, GL_DYNAMIC_DRAW); // Update all buffer
// Colors buffer
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[currentBuffer].vboId[2]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*vertexData[currentBuffer].vCounter, vertexData[currentBuffer].colors);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_BATCH_ELEMENTS, vertexData[currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[2]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter, RLGL.State.vertexData[RLGL.State.currentBuffer].colors);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_BATCH_ELEMENTS, RLGL.State.vertexData[RLGL.State.currentBuffer].colors, GL_DYNAMIC_DRAW); // Update all buffer
// NOTE: glMapBuffer() causes sync issue.
// If GPU is working with this buffer, glMapBuffer() will wait(stall) until GPU to finish its job.
@@ -4165,27 +4202,27 @@ static void UpdateBuffersDefault(void)
// Another option: map the buffer object into client's memory
// Probably this code could be moved somewhere else...
- // vertexData[currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
- // if (vertexData[currentBuffer].vertices)
+ // RLGL.State.vertexData[RLGL.State.currentBuffer].vertices = (float *)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
+ // if (RLGL.State.vertexData[RLGL.State.currentBuffer].vertices)
// {
// Update vertex data
// }
// glUnmapBuffer(GL_ARRAY_BUFFER);
// Unbind the current VAO
- if (vaoSupported) glBindVertexArray(0);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
}
}
// Draw default internal buffers vertex data
static void DrawBuffersDefault(void)
{
- Matrix matProjection = projection;
- Matrix matModelView = modelview;
+ Matrix matProjection = RLGL.State.projection;
+ Matrix matModelView = RLGL.State.modelview;
int eyesCount = 1;
#if defined(SUPPORT_VR_SIMULATOR)
- if (vrStereoRender) eyesCount = 2;
+ if (RLGL.Vr.stereoRender) eyesCount = 2;
#endif
for (int eye = 0; eye < eyesCount; eye++)
@@ -4195,74 +4232,74 @@ static void DrawBuffersDefault(void)
#endif
// Draw buffers
- if (vertexData[currentBuffer].vCounter > 0)
+ if (RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter > 0)
{
// Set current shader and upload current MVP matrix
- glUseProgram(currentShader.id);
+ glUseProgram(RLGL.State.currentShader.id);
// Create modelview-projection matrix
- Matrix matMVP = MatrixMultiply(modelview, projection);
+ Matrix matMVP = MatrixMultiply(RLGL.State.modelview, RLGL.State.projection);
- glUniformMatrix4fv(currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP));
- glUniform4f(currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f);
- glUniform1i(currentShader.locs[LOC_MAP_DIFFUSE], 0); // Provided value refers to the texture unit (active)
+ glUniformMatrix4fv(RLGL.State.currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP));
+ glUniform4f(RLGL.State.currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f);
+ glUniform1i(RLGL.State.currentShader.locs[LOC_MAP_DIFFUSE], 0); // Provided value refers to the texture unit (active)
// TODO: Support additional texture units on custom shader
- //if (currentShader->locs[LOC_MAP_SPECULAR] > 0) glUniform1i(currentShader.locs[LOC_MAP_SPECULAR], 1);
- //if (currentShader->locs[LOC_MAP_NORMAL] > 0) glUniform1i(currentShader.locs[LOC_MAP_NORMAL], 2);
+ //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) glUniform1i(RLGL.State.currentShader.locs[LOC_MAP_SPECULAR], 1);
+ //if (RLGL.State.currentShader->locs[LOC_MAP_NORMAL] > 0) glUniform1i(RLGL.State.currentShader.locs[LOC_MAP_NORMAL], 2);
// NOTE: Right now additional map textures not considered for default buffers drawing
int vertexOffset = 0;
- if (vaoSupported) glBindVertexArray(vertexData[currentBuffer].vaoId);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(RLGL.State.vertexData[RLGL.State.currentBuffer].vaoId);
else
{
// Bind vertex attrib: position (shader-location = 0)
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[currentBuffer].vboId[0]);
- glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]);
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[0]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_POSITION]);
// Bind vertex attrib: texcoord (shader-location = 1)
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[currentBuffer].vboId[1]);
- glVertexAttribPointer(currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_TEXCOORD01]);
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[1]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_TEXCOORD01]);
// Bind vertex attrib: color (shader-location = 3)
- glBindBuffer(GL_ARRAY_BUFFER, vertexData[currentBuffer].vboId[2]);
- glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
- glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]);
+ glBindBuffer(GL_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[2]);
+ glVertexAttribPointer(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
+ glEnableVertexAttribArray(RLGL.State.currentShader.locs[LOC_VERTEX_COLOR]);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexData[currentBuffer].vboId[3]);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, RLGL.State.vertexData[RLGL.State.currentBuffer].vboId[3]);
}
glActiveTexture(GL_TEXTURE0);
- for (int i = 0; i < drawsCounter; i++)
+ for (int i = 0; i < RLGL.State.drawsCounter; i++)
{
- glBindTexture(GL_TEXTURE_2D, draws[i].textureId);
+ glBindTexture(GL_TEXTURE_2D, RLGL.State.draws[i].textureId);
// TODO: Find some way to bind additional textures --> Use global texture IDs? Register them on draw[i]?
- //if (currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureUnit1_id); }
- //if (currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureUnit2_id); }
+ //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textureUnit1_id); }
+ //if (RLGL.State.currentShader->locs[LOC_MAP_SPECULAR] > 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textureUnit2_id); }
- if ((draws[i].mode == RL_LINES) || (draws[i].mode == RL_TRIANGLES)) glDrawArrays(draws[i].mode, vertexOffset, draws[i].vertexCount);
+ if ((RLGL.State.draws[i].mode == RL_LINES) || (RLGL.State.draws[i].mode == RL_TRIANGLES)) glDrawArrays(RLGL.State.draws[i].mode, vertexOffset, RLGL.State.draws[i].vertexCount);
else
{
#if defined(GRAPHICS_API_OPENGL_33)
// We need to define the number of indices to be processed: quadsCount*6
// NOTE: The final parameter tells the GPU the offset in bytes from the
// start of the index buffer to the location of the first index to process
- glDrawElements(GL_TRIANGLES, draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*vertexOffset/4*6));
+ glDrawElements(GL_TRIANGLES, RLGL.State.draws[i].vertexCount/4*6, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*vertexOffset/4*6));
#elif defined(GRAPHICS_API_OPENGL_ES2)
- glDrawElements(GL_TRIANGLES, draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*vertexOffset/4*6));
+ glDrawElements(GL_TRIANGLES, RLGL.State.draws[i].vertexCount/4*6, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*vertexOffset/4*6));
#endif
}
- vertexOffset += (draws[i].vertexCount + draws[i].vertexAlignment);
+ vertexOffset += (RLGL.State.draws[i].vertexCount + RLGL.State.draws[i].vertexAlignment);
}
- if (!vaoSupported)
+ if (!RLGL.ExtSupported.vao)
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -4271,43 +4308,43 @@ static void DrawBuffersDefault(void)
glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
}
- if (vaoSupported) glBindVertexArray(0); // Unbind VAO
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0); // Unbind VAO
glUseProgram(0); // Unbind shader program
}
// Reset vertex counters for next frame
- vertexData[currentBuffer].vCounter = 0;
- vertexData[currentBuffer].tcCounter = 0;
- vertexData[currentBuffer].cCounter = 0;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].vCounter = 0;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].tcCounter = 0;
+ RLGL.State.vertexData[RLGL.State.currentBuffer].cCounter = 0;
// Reset depth for next draw
- currentDepth = -1.0f;
+ RLGL.State.currentDepth = -1.0f;
// Restore projection/modelview matrices
- projection = matProjection;
- modelview = matModelView;
+ RLGL.State.projection = matProjection;
+ RLGL.State.modelview = matModelView;
- // Reset draws array
+ // Reset RLGL.State.draws array
for (int i = 0; i < MAX_DRAWCALL_REGISTERED; i++)
{
- draws[i].mode = RL_QUADS;
- draws[i].vertexCount = 0;
- draws[i].textureId = defaultTextureId;
+ RLGL.State.draws[i].mode = RL_QUADS;
+ RLGL.State.draws[i].vertexCount = 0;
+ RLGL.State.draws[i].textureId = RLGL.State.defaultTextureId;
}
- drawsCounter = 1;
+ RLGL.State.drawsCounter = 1;
// Change to next buffer in the list
- currentBuffer++;
- if (currentBuffer >= MAX_BATCH_BUFFERING) currentBuffer = 0;
+ RLGL.State.currentBuffer++;
+ if (RLGL.State.currentBuffer >= MAX_BATCH_BUFFERING) RLGL.State.currentBuffer = 0;
}
// Unload default internal buffers vertex data from CPU and GPU
static void UnloadBuffersDefault(void)
{
// Unbind everything
- if (vaoSupported) glBindVertexArray(0);
+ if (RLGL.ExtSupported.vao) glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
@@ -4318,19 +4355,19 @@ static void UnloadBuffersDefault(void)
for (int i = 0; i < MAX_BATCH_BUFFERING; i++)
{
// Delete VBOs from GPU (VRAM)
- glDeleteBuffers(1, &vertexData[i].vboId[0]);
- glDeleteBuffers(1, &vertexData[i].vboId[1]);
- glDeleteBuffers(1, &vertexData[i].vboId[2]);
- glDeleteBuffers(1, &vertexData[i].vboId[3]);
+ glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[0]);
+ glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[1]);
+ glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[2]);
+ glDeleteBuffers(1, &RLGL.State.vertexData[i].vboId[3]);
// Delete VAOs from GPU (VRAM)
- if (vaoSupported) glDeleteVertexArrays(1, &vertexData[i].vaoId);
+ if (RLGL.ExtSupported.vao) glDeleteVertexArrays(1, &RLGL.State.vertexData[i].vaoId);
// Free vertex arrays memory from CPU (RAM)
- RL_FREE(vertexData[i].vertices);
- RL_FREE(vertexData[i].texcoords);
- RL_FREE(vertexData[i].colors);
- RL_FREE(vertexData[i].indices);
+ RL_FREE(RLGL.State.vertexData[i].vertices);
+ RL_FREE(RLGL.State.vertexData[i].texcoords);
+ RL_FREE(RLGL.State.vertexData[i].colors);
+ RL_FREE(RLGL.State.vertexData[i].indices);
}
}
@@ -4453,13 +4490,13 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView)
Matrix eyeModelView = matModelView;
// Setup viewport and projection/modelview matrices using tracking data
- rlViewport(eye*framebufferWidth/2, 0, framebufferWidth/2, framebufferHeight);
+ rlViewport(eye*RLGL.State.framebufferWidth/2, 0, RLGL.State.framebufferWidth/2, RLGL.State.framebufferHeight);
// Apply view offset to modelview matrix
- eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]);
+ eyeModelView = MatrixMultiply(matModelView, RLGL.Vr.config.eyesViewOffset[eye]);
// Set current eye projection matrix
- eyeProjection = vrConfig.eyesProjection[eye];
+ eyeProjection = RLGL.Vr.config.eyesProjection[eye];
SetMatrixModelview(eyeModelView);
SetMatrixProjection(eyeProjection);
diff --git a/src/shapes.c b/src/shapes.c
index ff9e6c1a..ca68d951 100644
--- a/src/shapes.c
+++ b/src/shapes.c
@@ -58,14 +58,12 @@
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-static Texture2D texShapes = { 0 }; // Texture used on shapes drawing (usually a white)
-static Rectangle recTexShapes = { 0 }; // Texture source rectangle used on shapes drawing
+// ...
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static float EaseCubicInOut(float t, float b, float c, float d); // Cubic easing
-static Texture2D GetShapesTexture(void); // Get texture to draw shapes
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -138,16 +136,16 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
rlColor4ub(color.r, color.g, color.b, color.a);
rlNormal3f(0.0f, 0.0f, 1.0f);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(0.0f, 0.0f);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(0.0f, thick);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(d, thick);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(d, 0.0f);
rlEnd();
rlPopMatrix();
@@ -241,16 +239,16 @@ void DrawCircleSector(Vector2 center, float radius, int startAngle, int endAngle
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x, center.y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
angle += (stepLength*2);
@@ -261,16 +259,16 @@ void DrawCircleSector(Vector2 center, float radius, int startAngle, int endAngle
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x, center.y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x, center.y);
}
rlEnd();
@@ -489,16 +487,16 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, int startAng
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
angle += stepLength;
@@ -643,16 +641,16 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
rlNormal3f(0.0f, 0.0f, 1.0f);
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(0.0f, 0.0f);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(0.0f, rec.height);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(rec.width, rec.height);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(rec.width, 0.0f);
rlEnd();
rlPopMatrix();
@@ -686,19 +684,19 @@ void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3,
// NOTE: Default raylib font character 95 is a white square
rlColor4ub(col1.r, col1.g, col1.b, col1.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(rec.x, rec.y);
rlColor4ub(col2.r, col2.g, col2.b, col2.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(rec.x, rec.y + rec.height);
rlColor4ub(col3.r, col3.g, col3.b, col3.a);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
rlColor4ub(col4.r, col4.g, col4.b, col4.a);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(rec.x + rec.width, rec.y);
rlEnd();
rlPopMatrix();
@@ -821,13 +819,13 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
for (int i = 0; i < segments/2; i++)
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x, center.y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
angle += (stepLength*2);
}
@@ -835,70 +833,70 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
if (segments%2)
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x, center.y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x, center.y);
}
}
// [2] Upper Rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[0].x, point[0].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[8].x, point[8].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[9].x, point[9].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[1].x, point[1].y);
// [4] Right Rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[2].x, point[2].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[9].x, point[9].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[10].x, point[10].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[3].x, point[3].y);
// [6] Bottom Rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[11].x, point[11].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[5].x, point[5].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[4].x, point[4].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[10].x, point[10].y);
// [8] Left Rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[7].x, point[7].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[6].x, point[6].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[11].x, point[11].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[8].x, point[8].y);
// [9] Middle Rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[8].x, point[8].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[11].x, point[11].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[10].x, point[10].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[9].x, point[9].y);
rlEnd();
@@ -1053,13 +1051,13 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int
for (int i = 0; i < segments; i++)
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
angle += stepLength;
@@ -1068,46 +1066,46 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int
// Upper rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[0].x, point[0].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[8].x, point[8].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[9].x, point[9].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[1].x, point[1].y);
// Right rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[2].x, point[2].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[10].x, point[10].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[11].x, point[11].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[3].x, point[3].y);
// Lower rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[13].x, point[13].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[5].x, point[5].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[4].x, point[4].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[12].x, point[12].y);
// Left rectangle
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[15].x, point[15].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[7].x, point[7].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(point[6].x, point[6].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(point[14].x, point[14].y);
rlEnd();
@@ -1221,16 +1219,16 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(v1.x, v1.y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(v2.x, v2.y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(v2.x, v2.y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(v3.x, v3.y);
rlEnd();
@@ -1278,16 +1276,16 @@ void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
for (int i = 1; i < pointsCount - 1; i++)
{
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(points[0].x, points[0].y);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(points[i].x, points[i].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(points[i + 1].x, points[i + 1].y);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(points[i + 1].x, points[i + 1].y);
}
rlEnd();
@@ -1345,17 +1343,17 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
{
rlColor4ub(color.r, color.g, color.b, color.a);
- rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(0, 0);
- rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
centralAngle += 360.0f/(float)sides;
- rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
+ rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
}
rlEnd();
@@ -1402,13 +1400,6 @@ void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Colo
rlPopMatrix();
}
-// Define default texture used to draw shapes
-void SetShapesTexture(Texture2D texture, Rectangle source)
-{
- texShapes = texture;
- recTexShapes = source;
-}
-
//----------------------------------------------------------------------------------
// Module Functions Definition - Collision Detection functions
//----------------------------------------------------------------------------------
@@ -1576,22 +1567,3 @@ static float EaseCubicInOut(float t, float b, float c, float d)
return 0.5f*c*(t*t*t + 2.0f) + b;
}
-
-// Get texture to draw shapes (RAII)
-static Texture2D GetShapesTexture(void)
-{
- if (texShapes.id == 0)
- {
-#if defined(SUPPORT_FONT_TEXTURE)
- texShapes = GetFontDefault().texture; // Use font texture white character
- Rectangle rec = GetFontDefault().recs[95];
- // NOTE: We setup a 1px padding on char rectangle to avoid texture bleeding on MSAA filtering
- recTexShapes = (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 };
-#else
- texShapes = GetTextureDefault(); // Use default white texture
- recTexShapes = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f };
-#endif
- }
-
- return texShapes;
-}
diff --git a/src/utils.h b/src/utils.h
index 31c54aa5..94414c05 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -32,6 +32,18 @@
#include <android/asset_manager.h> // Required for: AAssetManager
#endif
+#if defined(SUPPORT_TRACELOG)
+ #define TRACELOG(level, ...) TraceLog(level, __VA_ARGS__)
+
+ #if defined(SUPPORT_TRACELOG_DEBUG)
+ #define TRACELOGD(...) TraceLog(LOG_DEBUG, __VA_ARGS__)
+ #else
+ #define TRACELOGD(...) void(0)
+ #endif
+#else
+ #define TRACELOG(level, ...) void(0)
+#endif
+
//----------------------------------------------------------------------------------
// Some basic Defines
//----------------------------------------------------------------------------------