Merge branch 'master' of https://github.com/raysan5/raylib
This commit is contained in:
commit
73d62aab54
1
.github/ISSUE_TEMPLATE/new-issue-template.md
vendored
1
.github/ISSUE_TEMPLATE/new-issue-template.md
vendored
|
|
@ -21,6 +21,7 @@ Please, before submitting a new issue verify and check:
|
||||||
|
|
||||||
- [ ] I tested it on latest raylib version from master branch
|
- [ ] I tested it on latest raylib version from master branch
|
||||||
- [ ] I checked there is no similar issue already reported
|
- [ ] I checked there is no similar issue already reported
|
||||||
|
- [ ] I checked the documentation on the [wiki](https://github.com/raysan5/raylib/wiki)
|
||||||
- [ ] My code has no errors or misuse of raylib
|
- [ ] My code has no errors or misuse of raylib
|
||||||
|
|
||||||
### Issue description
|
### Issue description
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| chez-raylib | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme/) | GPLv3 | https://github.com/Yunoinsky/chez-raylib |
|
| chez-raylib | **auto** | [Chez Scheme](https://cisco.github.io/ChezScheme/) | GPLv3 | https://github.com/Yunoinsky/chez-raylib |
|
||||||
| raylib-cr | **4.6-dev (5e1a81)** | [Crystal](https://crystal-lang.org/) | Apache-2.0 | https://github.com/sol-vin/raylib-cr |
|
| raylib-cr | **4.6-dev (5e1a81)** | [Crystal](https://crystal-lang.org/) | Apache-2.0 | https://github.com/sol-vin/raylib-cr |
|
||||||
| ray-cyber | 4.5 | [Cyber](https://cyberscript.dev) | MIT | https://github.com/fubark/ray-cyber |
|
| ray-cyber | 4.5 | [Cyber](https://cyberscript.dev) | MIT | https://github.com/fubark/ray-cyber |
|
||||||
| raylib-c3 | **4.5** | [C3](https://c3-lang.org/) | MIT | https://github.com/Its-Kenta/Raylib-C3 |
|
| raylib-c3 | **4.5** | [C3](https://c3-lang.org/) | Zlib | https://github.com/Its-Kenta/Raylib-C3 |
|
||||||
| dart-raylib | 4.0 | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib |
|
| dart-raylib | 4.0 | [Dart](https://dart.dev/) | MIT | https://gitlab.com/wolfenrain/dart-raylib |
|
||||||
| bindbc-raylib3 | 4.0 | [D](https://dlang.org/) | BSL-1.0 | https://github.com/o3o/bindbc-raylib3 |
|
| bindbc-raylib3 | **4.5** | [D](https://dlang.org/) | BSL-1.0 | https://github.com/o3o/bindbc-raylib3 |
|
||||||
| dray | 4.2 | [D](https://dlang.org/) | Apache-2.0 | https://github.com/redthing1/dray |
|
| dray | 4.2 | [D](https://dlang.org/) | Apache-2.0 | https://github.com/redthing1/dray |
|
||||||
| raylib-d | **4.5** | [D](https://dlang.org/) | Zlib | https://github.com/schveiguy/raylib-d |
|
| raylib-d | **4.5** | [D](https://dlang.org/) | Zlib | https://github.com/schveiguy/raylib-d |
|
||||||
| dlang_raylib | 4.0 | [D](https://dlang.org) | MPL-2.0 |https://github.com/rc-05/dlang_raylib |
|
| dlang_raylib | 4.0 | [D](https://dlang.org) | MPL-2.0 |https://github.com/rc-05/dlang_raylib |
|
||||||
|
|
@ -28,7 +28,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| raylib-go | 4.5 | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go |
|
| raylib-go | 4.5 | [Go](https://golang.org/) | Zlib | https://github.com/gen2brain/raylib-go |
|
||||||
| raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile |
|
| raylib-guile | **auto** | [Guile](https://www.gnu.org/software/guile/) | Zlib | https://github.com/petelliott/raylib-guile |
|
||||||
| gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | MIT | https://github.com/ArnautDaniel/gforth-raylib |
|
| gforth-raylib | 3.5 | [Gforth](https://gforth.org/) | MIT | https://github.com/ArnautDaniel/gforth-raylib |
|
||||||
| h-raylib | **4.5** | [Haskell](https://haskell.org/) | Apache-2.0 | https://github.com/Anut-py/h-raylib |
|
| h-raylib | **4.6-dev** | [Haskell](https://haskell.org/) | Apache-2.0 | https://github.com/Anut-py/h-raylib |
|
||||||
| raylib-hx | 4.2 | [Haxe](https://haxe.org/) | Zlib | https://github.com/foreignsasquatch/raylib-hx |
|
| raylib-hx | 4.2 | [Haxe](https://haxe.org/) | Zlib | https://github.com/foreignsasquatch/raylib-hx |
|
||||||
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | MIT | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
|
| hb-raylib | 3.5 | [Harbour](https://harbour.github.io) | MIT | https://github.com/MarcosLeonardoMendezGerencir/hb-raylib |
|
||||||
| jaylib | 4.5 | [Janet](https://janet-lang.org/) | MIT | https://github.com/janet-lang/jaylib |
|
| jaylib | 4.5 | [Janet](https://janet-lang.org/) | MIT | https://github.com/janet-lang/jaylib |
|
||||||
|
|
@ -40,7 +40,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| raylib-lua | **4.5** | [Lua](http://www.lua.org/) | ISC | https://github.com/TSnake41/raylib-lua |
|
| raylib-lua | **4.5** | [Lua](http://www.lua.org/) | ISC | https://github.com/TSnake41/raylib-lua |
|
||||||
| raylua | 4.0 | [Lua](http://www.lua.org/) | MIT | https://github.com/Rabios/raylua |
|
| raylua | 4.0 | [Lua](http://www.lua.org/) | MIT | https://github.com/Rabios/raylua |
|
||||||
| nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib |
|
| nelua-raylib | 4.0 | [nelua](https://nelua.io/) | MIT | https://github.com/AKDev21/nelua-raylib |
|
||||||
| Raylib-Nelua | **4.5-dev** | [nelua](https://nelua.io/) | MIT | https://github.com/Its-Kenta/Raylib-Nelua |
|
| Raylib.nelua | **4.5** | [nelua](https://nelua.io/) | Zlib | https://github.com/Its-Kenta/Raylib-Nelua |
|
||||||
| NimraylibNow! | 4.2 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now |
|
| NimraylibNow! | 4.2 | [Nim](https://nim-lang.org/) | MIT | https://github.com/greenfork/nimraylib_now |
|
||||||
| raylib-Forever | auto | [Nim](https://nim-lang.org/) | ? | https://github.com/Guevara-chan/Raylib-Forever |
|
| raylib-Forever | auto | [Nim](https://nim-lang.org/) | ? | https://github.com/Guevara-chan/Raylib-Forever |
|
||||||
| naylib | auto | [Nim](https://nim-lang.org/) | MIT | https://github.com/planetis-m/naylib |
|
| naylib | auto | [Nim](https://nim-lang.org/) | MIT | https://github.com/planetis-m/naylib |
|
||||||
|
|
@ -59,6 +59,7 @@ Some people ported raylib to other languages in form of bindings or wrappers to
|
||||||
| raylib-php | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/joseph-montanez/raylib-php |
|
| raylib-php | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/joseph-montanez/raylib-php |
|
||||||
| raylib-phpcpp | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/oraoto/raylib-phpcpp |
|
| raylib-phpcpp | 3.5 | [PHP](https://en.wikipedia.org/wiki/PHP) | Zlib | https://github.com/oraoto/raylib-phpcpp |
|
||||||
| raylibr | 4.0 | [R](https://www.r-project.org) | MIT | https://github.com/jeroenjanssens/raylibr |
|
| raylibr | 4.0 | [R](https://www.r-project.org) | MIT | https://github.com/jeroenjanssens/raylibr |
|
||||||
|
| raylib-ffi | 4.5 | [Rust](https://www.rust-lang.org/) | GPLv3 | https://github.com/ewpratten/raylib-ffi |
|
||||||
| raylib-rs | 3.5 | [Rust](https://www.rust-lang.org/) | Zlib | https://github.com/deltaphc/raylib-rs |
|
| raylib-rs | 3.5 | [Rust](https://www.rust-lang.org/) | Zlib | https://github.com/deltaphc/raylib-rs |
|
||||||
| Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | ? | https://github.com/RedCubeDev-ByteSpace/Relib |
|
| Relib | 3.5 | [ReCT](https://github.com/RedCubeDev-ByteSpace/ReCT) | ? | https://github.com/RedCubeDev-ByteSpace/Relib |
|
||||||
| racket-raylib | 4.0 | [Racket](https://racket-lang.org/) | MIT/Apache-2.0 | https://github.com/eutro/racket-raylib |
|
| racket-raylib | 4.0 | [Racket](https://racket-lang.org/) | MIT/Apache-2.0 | https://github.com/eutro/racket-raylib |
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ cmake_dependent_option(SUPPORT_FILEFORMAT_PVR "Support loading PVR as textures"
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_FNT "Support loading fonts in FNT format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_FNT "Support loading fonts in FNT format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_FILEFORMAT_TTF "Support loading font in TTF/OTF format" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_FILEFORMAT_TTF "Support loading font in TTF/OTF format" ON CUSTOMIZE_BUILD ON)
|
||||||
cmake_dependent_option(SUPPORT_TEXT_MANIPULATION "Support text manipulation functions" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_TEXT_MANIPULATION "Support text manipulation functions" ON CUSTOMIZE_BUILD ON)
|
||||||
|
cmake_dependent_option(SUPPORT_FONT_ATLAS_WHITE_REC "Support white rec on font atlas bottom-right corner" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
||||||
# rmodels.c
|
# rmodels.c
|
||||||
cmake_dependent_option(SUPPORT_MESH_GENERATION "Support procedural mesh generation functions, uses external par_shapes.h library. NOTE: Some generated meshes DO NOT include generated texture coordinates" ON CUSTOMIZE_BUILD ON)
|
cmake_dependent_option(SUPPORT_MESH_GENERATION "Support procedural mesh generation functions, uses external par_shapes.h library. NOTE: Some generated meshes DO NOT include generated texture coordinates" ON CUSTOMIZE_BUILD ON)
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ elseif ("${PLATFORM}" MATCHES "DRM")
|
||||||
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT ${OPENGL_VERSION})
|
if (NOT ${OPENGL_VERSION} MATCHES "OFF")
|
||||||
set(${SUGGESTED_GRAPHICS} "${GRAPHICS}")
|
set(${SUGGESTED_GRAPHICS} "${GRAPHICS}")
|
||||||
if (${OPENGL_VERSION} MATCHES "4.3")
|
if (${OPENGL_VERSION} MATCHES "4.3")
|
||||||
set(GRAPHICS "GRAPHICS_API_OPENGL_43")
|
set(GRAPHICS "GRAPHICS_API_OPENGL_43")
|
||||||
|
|
|
||||||
|
|
@ -405,6 +405,7 @@ CORE = \
|
||||||
core/core_input_gamepad \
|
core/core_input_gamepad \
|
||||||
core/core_input_multitouch \
|
core/core_input_multitouch \
|
||||||
core/core_input_gestures \
|
core/core_input_gestures \
|
||||||
|
core/core_input_gestures_web \
|
||||||
core/core_2d_camera \
|
core/core_2d_camera \
|
||||||
core/core_2d_camera_platformer \
|
core/core_2d_camera_platformer \
|
||||||
core/core_2d_camera_mouse_zoom \
|
core/core_2d_camera_mouse_zoom \
|
||||||
|
|
@ -536,12 +537,20 @@ AUDIO = \
|
||||||
audio/audio_stream_effects \
|
audio/audio_stream_effects \
|
||||||
audio/audio_mixed_processor
|
audio/audio_mixed_processor
|
||||||
|
|
||||||
|
OTHERS = \
|
||||||
|
others/easings_testbed \
|
||||||
|
others/embedded_files_loading \
|
||||||
|
others/raylib_opengl_interop \
|
||||||
|
others/raymath_vector_angle \
|
||||||
|
others/rlgl_compute_shader \
|
||||||
|
others/rlgl_standalone
|
||||||
|
|
||||||
CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST))
|
CURRENT_MAKEFILE = $(lastword $(MAKEFILE_LIST))
|
||||||
|
|
||||||
# Define processes to execute
|
# Define processes to execute
|
||||||
#------------------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------------------
|
||||||
# Default target entry
|
# Default target entry
|
||||||
all: $(CORE) $(SHAPES) $(TEXT) $(TEXTURES) $(MODELS) $(SHADERS) $(AUDIO)
|
all: $(CORE) $(SHAPES) $(TEXT) $(TEXTURES) $(MODELS) $(SHADERS) $(AUDIO) $(OTHERS)
|
||||||
|
|
||||||
core: $(CORE)
|
core: $(CORE)
|
||||||
shapes: $(SHAPES)
|
shapes: $(SHAPES)
|
||||||
|
|
@ -550,6 +559,7 @@ text: $(TEXT)
|
||||||
models: $(MODELS)
|
models: $(MODELS)
|
||||||
shaders: $(SHADERS)
|
shaders: $(SHADERS)
|
||||||
audio: $(AUDIO)
|
audio: $(AUDIO)
|
||||||
|
others: $(OTHERS)
|
||||||
|
|
||||||
# Generic compilation pattern
|
# Generic compilation pattern
|
||||||
# NOTE: Examples must be ready for Android compilation!
|
# NOTE: Examples must be ready for Android compilation!
|
||||||
|
|
|
||||||
|
|
@ -386,6 +386,7 @@ CORE = \
|
||||||
core/core_input_gamepad \
|
core/core_input_gamepad \
|
||||||
core/core_input_multitouch \
|
core/core_input_multitouch \
|
||||||
core/core_input_gestures \
|
core/core_input_gestures \
|
||||||
|
core/core_input_gestures_web \
|
||||||
core/core_2d_camera \
|
core/core_2d_camera \
|
||||||
core/core_2d_camera_platformer \
|
core/core_2d_camera_platformer \
|
||||||
core/core_2d_camera_mouse_zoom \
|
core/core_2d_camera_mouse_zoom \
|
||||||
|
|
@ -558,6 +559,9 @@ core/core_input_multitouch: core/core_input_multitouch.c
|
||||||
core/core_input_gestures: core/core_input_gestures.c
|
core/core_input_gestures: core/core_input_gestures.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||||
|
|
||||||
|
core/core_input_gestures_web: core/core_input_gestures_web.c
|
||||||
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||||
|
|
||||||
core/core_2d_camera: core/core_2d_camera.c
|
core/core_2d_camera: core/core_2d_camera.c
|
||||||
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
|
||||||
|
|
||||||
|
|
|
||||||
338
examples/core/core_input_gestures_web.c
Normal file
338
examples/core/core_input_gestures_web.c
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [core] example - Input Gestures for Web
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 4.6-dev, last time updated with raylib 4.6-dev
|
||||||
|
*
|
||||||
|
* Example contributed by ubkp (@ubkp) and reviewed by Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
|
* BSD-like license that allows static linking with closed source software
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 ubkp (@ubkp)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include "math.h" // Required for the protractor angle graphic drawing
|
||||||
|
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
#include <emscripten/emscripten.h> // Required for the Web/HTML5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
// Global definitions and declarations
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Common variables definitions
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
int screenWidth = 800; // Update depending on web canvas
|
||||||
|
const int screenHeight = 450;
|
||||||
|
Vector2 messagePosition = { 160, 7 };
|
||||||
|
|
||||||
|
// Last gesture variables definitions
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
int lastGesture = 0;
|
||||||
|
Vector2 lastGesturePosition = { 165, 130 };
|
||||||
|
|
||||||
|
// Gesture log variables definitions and functions declarations
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
#define GESTURE_LOG_SIZE 20
|
||||||
|
char gestureLog[GESTURE_LOG_SIZE][12] = { "" }; // The gesture log uses an array (as an inverted circular queue) to store the performed gestures
|
||||||
|
int gestureLogIndex = GESTURE_LOG_SIZE; // The index for the inverted circular queue (moving from last to first direction, then looping around)
|
||||||
|
int previousGesture = 0;
|
||||||
|
|
||||||
|
char const *GetGestureName(int i)
|
||||||
|
{
|
||||||
|
switch (i) {
|
||||||
|
case 0: return "None"; break;
|
||||||
|
case 1: return "Tap"; break;
|
||||||
|
case 2: return "Double Tap"; break;
|
||||||
|
case 4: return "Hold"; break;
|
||||||
|
case 8: return "Drag"; break;
|
||||||
|
case 16: return "Swipe Right"; break;
|
||||||
|
case 32: return "Swipe Left"; break;
|
||||||
|
case 64: return "Swipe Up"; break;
|
||||||
|
case 128: return "Swipe Down"; break;
|
||||||
|
case 256: return "Pinch In"; break;
|
||||||
|
case 512: return "Pinch Out"; break;
|
||||||
|
default: return "Unknown"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color GetGestureColor(int i)
|
||||||
|
{
|
||||||
|
switch (i) {
|
||||||
|
case 0: return BLACK; break;
|
||||||
|
case 1: return BLUE; break;
|
||||||
|
case 2: return SKYBLUE; break;
|
||||||
|
case 4: return BLACK; break;
|
||||||
|
case 8: return LIME; break;
|
||||||
|
case 16: return RED; break;
|
||||||
|
case 32: return RED; break;
|
||||||
|
case 64: return RED; break;
|
||||||
|
case 128: return RED; break;
|
||||||
|
case 256: return VIOLET; break;
|
||||||
|
case 512: return ORANGE; break;
|
||||||
|
default: return BLACK; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int logMode = 1; // Log mode values: 0 shows repeated events; 1 hides repeated events; 2 shows repeated events but hide hold events; 3 hides repeated events and hide hold events
|
||||||
|
|
||||||
|
Color gestureColor = { 0, 0, 0, 255 };
|
||||||
|
Rectangle logButton1 = { 53, 7, 48, 26 };
|
||||||
|
Rectangle logButton2 = { 108, 7, 36, 26 };
|
||||||
|
Vector2 gestureLogPosition = { 10, 10 };
|
||||||
|
|
||||||
|
// Protractor variables definitions
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
float angleLength = 90.0f;
|
||||||
|
float currentAngleDegrees = 0.0f;
|
||||||
|
Vector2 finalVector = { 0.0f, 0.0f };
|
||||||
|
char currentAngleStr[7] = "";
|
||||||
|
Vector2 protractorPosition = { 266.0f, 315.0f };
|
||||||
|
|
||||||
|
// Update
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
void Update(void)
|
||||||
|
{
|
||||||
|
// Handle common
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
int i, ii; // Iterators that will be reused by all for loops
|
||||||
|
const int currentGesture = GetGestureDetected();
|
||||||
|
const float currentDragDegrees = GetGestureDragAngle();
|
||||||
|
const float currentPitchDegrees = GetGesturePinchAngle();
|
||||||
|
const int touchCount = GetTouchPointCount();
|
||||||
|
|
||||||
|
// Handle last gesture
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
if ((currentGesture != 0) && (currentGesture != 4) && (currentGesture != previousGesture)) lastGesture = currentGesture; // Filter the meaningful gestures (1, 2, 8 to 512) for the display
|
||||||
|
|
||||||
|
// Handle gesture log
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
|
||||||
|
{
|
||||||
|
if (CheckCollisionPointRec(GetMousePosition(), logButton1))
|
||||||
|
{
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case 3: logMode=2; break;
|
||||||
|
case 2: logMode=3; break;
|
||||||
|
case 1: logMode=0; break;
|
||||||
|
default: logMode=1; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (CheckCollisionPointRec(GetMousePosition(), logButton2))
|
||||||
|
{
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case 3: logMode=1; break;
|
||||||
|
case 2: logMode=0; break;
|
||||||
|
case 1: logMode=3; break;
|
||||||
|
default: logMode=2; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fillLog = 0; // Gate variable to be used to allow or not the gesture log to be filled
|
||||||
|
if (currentGesture !=0)
|
||||||
|
{
|
||||||
|
if (logMode == 3) // 3 hides repeated events and hide hold events
|
||||||
|
{
|
||||||
|
if (((currentGesture != 4) && (currentGesture != previousGesture)) || (currentGesture < 3)) fillLog = 1;
|
||||||
|
}
|
||||||
|
else if (logMode == 2) // 2 shows repeated events but hide hold events
|
||||||
|
{
|
||||||
|
if (currentGesture != 4) fillLog = 1;
|
||||||
|
}
|
||||||
|
else if (logMode == 1) // 1 hides repeated events
|
||||||
|
{
|
||||||
|
if (currentGesture != previousGesture) fillLog = 1;
|
||||||
|
}
|
||||||
|
else // 0 shows repeated events
|
||||||
|
{
|
||||||
|
fillLog = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fillLog) // If one of the conditions from logMode was met, fill the gesture log
|
||||||
|
{
|
||||||
|
previousGesture = currentGesture;
|
||||||
|
gestureColor = GetGestureColor(currentGesture);
|
||||||
|
if (gestureLogIndex <= 0) gestureLogIndex = GESTURE_LOG_SIZE;
|
||||||
|
gestureLogIndex--;
|
||||||
|
|
||||||
|
// Copy the gesture respective name to the gesture log array
|
||||||
|
TextCopy(gestureLog[gestureLogIndex], GetGestureName(currentGesture));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle protractor
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
if (currentGesture > 255) // aka Pinch In and Pinch Out
|
||||||
|
{
|
||||||
|
currentAngleDegrees = currentPitchDegrees;
|
||||||
|
}
|
||||||
|
else if (currentGesture > 15) // aka Swipe Right, Swipe Left, Swipe Up and Swipe Down
|
||||||
|
{
|
||||||
|
currentAngleDegrees = currentDragDegrees;
|
||||||
|
}
|
||||||
|
else if (currentGesture > 0) // aka Tap, Doubletap, Hold and Grab
|
||||||
|
{
|
||||||
|
currentAngleDegrees = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float currentAngleRadians = ((currentAngleDegrees +90.0f)*PI/180); // Convert the current angle to Radians
|
||||||
|
finalVector = (Vector2){ (angleLength*sinf(currentAngleRadians)) + protractorPosition.x, (angleLength*cosf(currentAngleRadians)) + protractorPosition.y }; // Calculate the final vector for display
|
||||||
|
|
||||||
|
// Handle touch and mouse pointer points
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
#define MAX_TOUCH_COUNT 32
|
||||||
|
|
||||||
|
Vector2 touchPosition[MAX_TOUCH_COUNT] = { 0 };
|
||||||
|
Vector2 mousePosition = {0, 0};
|
||||||
|
if (currentGesture != GESTURE_NONE)
|
||||||
|
{
|
||||||
|
if (touchCount != 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < touchCount; i++) touchPosition[i] = GetTouchPosition(i); // Fill the touch positions
|
||||||
|
}
|
||||||
|
else mousePosition = GetMousePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
// Draw common
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
DrawText("*", messagePosition.x + 5, messagePosition.y + 5, 10, BLACK);
|
||||||
|
DrawText("Example optimized for Web/HTML5\non Smartphones with Touch Screen.", messagePosition.x + 15, messagePosition.y + 5, 10, BLACK);
|
||||||
|
DrawText("*", messagePosition.x + 5, messagePosition.y + 35, 10, BLACK);
|
||||||
|
DrawText("While running on Desktop Web Browsers,\ninspect and turn on Touch Emulation.", messagePosition.x + 15, messagePosition.y + 35, 10, BLACK);
|
||||||
|
|
||||||
|
// Draw last gesture
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
DrawText("Last gesture", lastGesturePosition.x + 33, lastGesturePosition.y - 47, 20, BLACK);
|
||||||
|
DrawText("Swipe Tap Pinch Touch", lastGesturePosition.x + 17, lastGesturePosition.y - 18, 10, BLACK);
|
||||||
|
DrawRectangle(lastGesturePosition.x + 20, lastGesturePosition.y, 20, 20, lastGesture == GESTURE_SWIPE_UP ? RED : LIGHTGRAY);
|
||||||
|
DrawRectangle(lastGesturePosition.x, lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_LEFT ? RED : LIGHTGRAY);
|
||||||
|
DrawRectangle(lastGesturePosition.x + 40, lastGesturePosition.y + 20, 20, 20, lastGesture == GESTURE_SWIPE_RIGHT ? RED : LIGHTGRAY);
|
||||||
|
DrawRectangle(lastGesturePosition.x + 20, lastGesturePosition.y + 40, 20, 20, lastGesture == GESTURE_SWIPE_DOWN ? RED : LIGHTGRAY);
|
||||||
|
DrawCircle(lastGesturePosition.x + 80, lastGesturePosition.y + 16, 10, lastGesture == GESTURE_TAP ? BLUE : LIGHTGRAY);
|
||||||
|
DrawRing( (Vector2){lastGesturePosition.x + 103, lastGesturePosition.y + 16}, 6.0f, 11.0f, 0.0f, 360.0f, 0, lastGesture == GESTURE_DRAG ? LIME : LIGHTGRAY);
|
||||||
|
DrawCircle(lastGesturePosition.x + 80, lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY);
|
||||||
|
DrawCircle(lastGesturePosition.x + 103, lastGesturePosition.y + 43, 10, lastGesture == GESTURE_DOUBLETAP ? SKYBLUE : LIGHTGRAY);
|
||||||
|
DrawTriangle((Vector2){ lastGesturePosition.x + 122, lastGesturePosition.y + 16 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 26 }, (Vector2){ lastGesturePosition.x + 137, lastGesturePosition.y + 6 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY);
|
||||||
|
DrawTriangle((Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 6 }, (Vector2){ lastGesturePosition.x + 147, lastGesturePosition.y + 26 }, (Vector2){ lastGesturePosition.x + 162, lastGesturePosition.y + 16 }, lastGesture == GESTURE_PINCH_OUT? ORANGE : LIGHTGRAY);
|
||||||
|
DrawTriangle((Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 33 }, (Vector2){ lastGesturePosition.x + 125, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 140, lastGesturePosition.y + 43 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY);
|
||||||
|
DrawTriangle((Vector2){ lastGesturePosition.x + 144, lastGesturePosition.y + 43 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 53 }, (Vector2){ lastGesturePosition.x + 159, lastGesturePosition.y + 33 }, lastGesture == GESTURE_PINCH_IN? VIOLET : LIGHTGRAY);
|
||||||
|
for (i = 0; i < 4; i++) DrawCircle(lastGesturePosition.x + 180, lastGesturePosition.y + 7 + i*15, 5, touchCount <= i? LIGHTGRAY : gestureColor);
|
||||||
|
|
||||||
|
// Draw gesture log
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
DrawText("Log", gestureLogPosition.x, gestureLogPosition.y, 20, BLACK);
|
||||||
|
|
||||||
|
// Loop in both directions to print the gesture log array in the inverted order (and looping around if the index started somewhere in the middle)
|
||||||
|
for (i = 0, ii = gestureLogIndex; i < GESTURE_LOG_SIZE; i++, ii = (ii + 1) % GESTURE_LOG_SIZE) DrawText(gestureLog[ii], gestureLogPosition.x, gestureLogPosition.y + 410 - i*20, 20, (i == 0 ? gestureColor : LIGHTGRAY));
|
||||||
|
Color logButton1Color, logButton2Color;
|
||||||
|
switch (logMode)
|
||||||
|
{
|
||||||
|
case 3: logButton1Color=MAROON; logButton2Color=MAROON; break;
|
||||||
|
case 2: logButton1Color=GRAY; logButton2Color=MAROON; break;
|
||||||
|
case 1: logButton1Color=MAROON; logButton2Color=GRAY; break;
|
||||||
|
default: logButton1Color=GRAY; logButton2Color=GRAY; break;
|
||||||
|
}
|
||||||
|
DrawRectangleRec(logButton1, logButton1Color);
|
||||||
|
DrawText("Hide", logButton1.x + 7, logButton1.y + 3, 10, WHITE);
|
||||||
|
DrawText("Repeat", logButton1.x + 7, logButton1.y + 13, 10, WHITE);
|
||||||
|
DrawRectangleRec(logButton2, logButton2Color);
|
||||||
|
DrawText("Hide", logButton1.x + 62, logButton1.y + 3, 10, WHITE);
|
||||||
|
DrawText("Hold", logButton1.x + 62, logButton1.y + 13, 10, WHITE);
|
||||||
|
|
||||||
|
// Draw protractor
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
DrawText("Angle", protractorPosition.x + 55, protractorPosition.y + 76, 10, BLACK);
|
||||||
|
const char *angleString = TextFormat("%f", currentAngleDegrees);
|
||||||
|
const int angleStringDot = TextFindIndex(angleString, ".");
|
||||||
|
const char *angleStringTrim = TextSubtext(angleString, 0, angleStringDot + 3);
|
||||||
|
DrawText( angleStringTrim, protractorPosition.x + 55, protractorPosition.y + 92, 20, gestureColor);
|
||||||
|
DrawCircle(protractorPosition.x, protractorPosition.y, 80.0f, WHITE);
|
||||||
|
DrawLineEx((Vector2){ protractorPosition.x - 90, protractorPosition.y }, (Vector2){ protractorPosition.x + 90, protractorPosition.y }, 3.0f, LIGHTGRAY);
|
||||||
|
DrawLineEx((Vector2){ protractorPosition.x, protractorPosition.y - 90 }, (Vector2){ protractorPosition.x, protractorPosition.y + 90 }, 3.0f, LIGHTGRAY);
|
||||||
|
DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y - 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y + 45 }, 3.0f, GREEN);
|
||||||
|
DrawLineEx((Vector2){ protractorPosition.x - 80, protractorPosition.y + 45 }, (Vector2){ protractorPosition.x + 80, protractorPosition.y - 45 }, 3.0f, GREEN);
|
||||||
|
DrawText("0", protractorPosition.x + 96, protractorPosition.y - 9, 20, BLACK);
|
||||||
|
DrawText("30", protractorPosition.x + 74, protractorPosition.y - 68, 20, BLACK);
|
||||||
|
DrawText("90", protractorPosition.x - 11, protractorPosition.y - 110, 20, BLACK);
|
||||||
|
DrawText("150", protractorPosition.x - 100, protractorPosition.y - 68, 20, BLACK);
|
||||||
|
DrawText("180", protractorPosition.x - 124, protractorPosition.y - 9, 20, BLACK);
|
||||||
|
DrawText("210", protractorPosition.x - 100, protractorPosition.y + 50, 20, BLACK);
|
||||||
|
DrawText("270", protractorPosition.x - 18, protractorPosition.y + 92, 20, BLACK);
|
||||||
|
DrawText("330", protractorPosition.x + 72, protractorPosition.y + 50, 20, BLACK);
|
||||||
|
if (currentAngleDegrees != 0.0f) DrawLineEx(protractorPosition, finalVector, 3.0f, gestureColor);
|
||||||
|
|
||||||
|
// Draw touch and mouse pointer points
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
if (currentGesture != GESTURE_NONE)
|
||||||
|
{
|
||||||
|
if ( touchCount != 0 )
|
||||||
|
{
|
||||||
|
for (i = 0; i < touchCount; i++)
|
||||||
|
{
|
||||||
|
DrawCircleV(touchPosition[i], 50.0f, Fade(gestureColor, 0.5f));
|
||||||
|
DrawCircleV(touchPosition[i], 5.0f, gestureColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (touchCount == 2) DrawLineEx(touchPosition[0], touchPosition[1], ((currentGesture == 512)? 8 : 12), gestureColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawCircleV(mousePosition, 35.0f, Fade(gestureColor, 0.5f));
|
||||||
|
DrawCircleV(mousePosition, 5.0f, gestureColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
#if defined( PLATFORM_WEB )
|
||||||
|
// Using Emscripten EM_ASM_INT macro, get the page canvas width
|
||||||
|
const int canvasWidth = EM_ASM_INT( return document.getElementById('canvas').getBoundingClientRect().width; );
|
||||||
|
|
||||||
|
if (canvasWidth > 400) screenWidth = canvasWidth;
|
||||||
|
else screenWidth = 400; // Set a minimum width for the screen
|
||||||
|
#endif
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [core] example - input gestures web");
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
emscripten_set_main_loop(Update, 0, 1);
|
||||||
|
#else
|
||||||
|
SetTargetFPS(60);
|
||||||
|
while (!WindowShouldClose()) Update(); // Detect window close button or ESC key
|
||||||
|
#endif
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
examples/core/core_input_gestures_web.png
Normal file
BIN
examples/core/core_input_gestures_web.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
|
|
@ -41,7 +41,7 @@
|
||||||
*
|
*
|
||||||
* raylib [core] example - Basic window
|
* raylib [core] example - Basic window
|
||||||
*
|
*
|
||||||
* Example originally created with raylib 4.2, last time updated with raylib 4.2
|
* Example originally created with raylib 4.5, last time updated with raylib 4.5
|
||||||
*
|
*
|
||||||
* Example contributed by <user_name> (@<user_github>) and reviewed by Ramon Santamaria (@raysan5)
|
* Example contributed by <user_name> (@<user_github>) and reviewed by Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
|
|
|
||||||
106
examples/others/raymath_vector_angle.c
Normal file
106
examples/others/raymath_vector_angle.c
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [shapes] example - Vector Angle
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 1.0, last time updated with raylib 4.2
|
||||||
|
*
|
||||||
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
|
* BSD-like license that allows static linking with closed source software
|
||||||
|
*
|
||||||
|
* Copyright (c) 2023 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include "raymath.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Program main entry point
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const int screenWidth = 800;
|
||||||
|
const int screenHeight = 450;
|
||||||
|
|
||||||
|
InitWindow(screenWidth, screenHeight, "raylib [math] example - vector angle");
|
||||||
|
|
||||||
|
Vector2 v0 = { screenWidth/2, screenHeight/2 };
|
||||||
|
Vector2 v1 = { 100.0f, 80.0f };
|
||||||
|
Vector2 v2 = { 0 }; // Updated with mouse position
|
||||||
|
|
||||||
|
float angle = 0.0f; // Angle in degrees
|
||||||
|
int angleMode = 0; // 0-Vector2Angle(), 1-Vector2LineAngle()
|
||||||
|
|
||||||
|
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
if (IsKeyPressed(KEY_SPACE)) angleMode = !angleMode;
|
||||||
|
|
||||||
|
if (angleMode == 0)
|
||||||
|
{
|
||||||
|
// Calculate angle between two vectors, considering a common origin (v0)
|
||||||
|
v1 = Vector2Add(v0, (Vector2){ 100.0f, 80.0f });
|
||||||
|
v2 = GetMousePosition();
|
||||||
|
angle = Vector2Angle(Vector2Normalize(Vector2Subtract(v1, v0)), Vector2Normalize(Vector2Subtract(v2, v0)))*RAD2DEG;
|
||||||
|
}
|
||||||
|
else if (angleMode == 1)
|
||||||
|
{
|
||||||
|
// Calculate angle defined by a two vectors line, in reference to horizontal line
|
||||||
|
v1 = (Vector2){ screenWidth/2, screenHeight/2 };
|
||||||
|
v2 = GetMousePosition();
|
||||||
|
angle = Vector2LineAngle(v1, v2)*RAD2DEG;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
BeginDrawing();
|
||||||
|
|
||||||
|
ClearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
if (angleMode == 0) DrawText("v0", v0.x, v0.y, 10, DARKGRAY);
|
||||||
|
DrawText("v1", v1.x, v1.y, 10, DARKGRAY);
|
||||||
|
DrawText("v2", v2.x, v2.y, 10, DARKGRAY);
|
||||||
|
|
||||||
|
if (angleMode == 0)
|
||||||
|
{
|
||||||
|
DrawText("MODE: Angle between V1 and V2", 10, 10, 20, BLACK);
|
||||||
|
|
||||||
|
DrawLineEx(v0, v1, 2.0f, BLACK);
|
||||||
|
DrawLineEx(v0, v2, 2.0f, RED);
|
||||||
|
|
||||||
|
float startangle = 90 - Vector2LineAngle(v0, v1)*RAD2DEG;
|
||||||
|
DrawCircleSector(v0, 40.0f, startangle, startangle + angle - 360.0f*(angle > 180.0f), 32, Fade(GREEN, 0.6f));
|
||||||
|
}
|
||||||
|
else if (angleMode == 1)
|
||||||
|
{
|
||||||
|
DrawText("MODE: Angle formed by line V1 to V2", 10, 10, 20, BLACK);
|
||||||
|
|
||||||
|
DrawLine(0, screenHeight/2, screenWidth, screenHeight/2, LIGHTGRAY);
|
||||||
|
DrawLineEx(v1, v2, 2.0f, RED);
|
||||||
|
|
||||||
|
DrawCircleSector(v1, 40.0f, 90.0f, 180 - angle - 90, 32, Fade(GREEN, 0.6f));
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawText("Press SPACE to change MODE", 460, 10, 20, DARKGRAY);
|
||||||
|
DrawText(TextFormat("ANGLE: %2.2f", angle), 10, 40, 20, LIME);
|
||||||
|
|
||||||
|
EndDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
CloseWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
BIN
examples/others/raymath_vector_angle.png
Normal file
BIN
examples/others/raymath_vector_angle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
|
|
@ -181,6 +181,11 @@
|
||||||
// If not defined, still some functions are supported: TextLength(), TextFormat()
|
// If not defined, still some functions are supported: TextLength(), TextFormat()
|
||||||
#define SUPPORT_TEXT_MANIPULATION 1
|
#define SUPPORT_TEXT_MANIPULATION 1
|
||||||
|
|
||||||
|
// On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
|
||||||
|
// at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
|
||||||
|
// drawing text and shapes with a single draw call [SetShapesTexture()].
|
||||||
|
#define SUPPORT_FONT_ATLAS_WHITE_REC 1
|
||||||
|
|
||||||
// rtext: Configuration values
|
// rtext: Configuration values
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
|
#define MAX_TEXT_BUFFER_LENGTH 1024 // Size of internal static buffers used on some functions:
|
||||||
|
|
|
||||||
145
src/external/sdefl.h
vendored
145
src/external/sdefl.h
vendored
|
|
@ -71,7 +71,7 @@ Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
ALTERNATIVE A - MIT License
|
ALTERNATIVE A - MIT License
|
||||||
Copyright (c) 2020 Micha Mettke
|
Copyright (c) 2020-2023 Micha Mettke
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
|
|
@ -125,7 +125,7 @@ extern "C" {
|
||||||
|
|
||||||
#define SDEFL_MIN_MATCH 4
|
#define SDEFL_MIN_MATCH 4
|
||||||
#define SDEFL_BLK_MAX (256*1024)
|
#define SDEFL_BLK_MAX (256*1024)
|
||||||
#define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX + SDEFL_MIN_MATCH)/SDEFL_MIN_MATCH)
|
#define SDEFL_SEQ_SIZ ((SDEFL_BLK_MAX+2)/3)
|
||||||
|
|
||||||
#define SDEFL_SYM_MAX (288)
|
#define SDEFL_SYM_MAX (288)
|
||||||
#define SDEFL_OFF_MAX (32)
|
#define SDEFL_OFF_MAX (32)
|
||||||
|
|
@ -185,6 +185,7 @@ extern int zsdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
|
||||||
#define SDEFL_MAX_CODE_LEN (15)
|
#define SDEFL_MAX_CODE_LEN (15)
|
||||||
#define SDEFL_SYM_BITS (10u)
|
#define SDEFL_SYM_BITS (10u)
|
||||||
#define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u)
|
#define SDEFL_SYM_MSK ((1u << SDEFL_SYM_BITS)-1u)
|
||||||
|
#define SDEFL_RAW_BLK_SIZE (65535)
|
||||||
#define SDEFL_LIT_LEN_CODES (14)
|
#define SDEFL_LIT_LEN_CODES (14)
|
||||||
#define SDEFL_OFF_CODES (15)
|
#define SDEFL_OFF_CODES (15)
|
||||||
#define SDEFL_PRE_CODES (7)
|
#define SDEFL_PRE_CODES (7)
|
||||||
|
|
@ -192,6 +193,7 @@ extern int zsdeflate(struct sdefl *s, void *o, const void *i, int n, int lvl);
|
||||||
#define SDEFL_EOB (256)
|
#define SDEFL_EOB (256)
|
||||||
|
|
||||||
#define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1))
|
#define sdefl_npow2(n) (1 << (sdefl_ilog2((n)-1) + 1))
|
||||||
|
#define sdefl_div_round_up(n,d) (((n)+((d)-1))/(d))
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sdefl_ilog2(int n) {
|
sdefl_ilog2(int n) {
|
||||||
|
|
@ -438,12 +440,12 @@ sdefl_precode(struct sdefl_symcnt *cnt, unsigned *freqs, unsigned *items,
|
||||||
} while (run_start != total);
|
} while (run_start != total);
|
||||||
cnt->items = (int)(at - items);
|
cnt->items = (int)(at - items);
|
||||||
}
|
}
|
||||||
struct sdefl_match_codes {
|
struct sdefl_match_codest {
|
||||||
int ls, lc;
|
int ls, lc;
|
||||||
int dc, dx;
|
int dc, dx;
|
||||||
};
|
};
|
||||||
static void
|
static void
|
||||||
sdefl_match_codes(struct sdefl_match_codes *cod, int dist, int len) {
|
sdefl_match_codes(struct sdefl_match_codest *cod, int dist, int len) {
|
||||||
static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576};
|
static const short dxmax[] = {0,6,12,24,48,96,192,384,768,1536,3072,6144,12288,24576};
|
||||||
static const unsigned char lslot[258+1] = {
|
static const unsigned char lslot[258+1] = {
|
||||||
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
|
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12,
|
||||||
|
|
@ -471,6 +473,44 @@ sdefl_match_codes(struct sdefl_match_codes *cod, int dist, int len) {
|
||||||
cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2);
|
cod->dx = sdefl_ilog2(sdefl_npow2(dist) >> 2);
|
||||||
cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1;
|
cod->dc = cod->dx ? ((cod->dx + 1) << 1) + (dist > dxmax[cod->dx]) : dist-1;
|
||||||
}
|
}
|
||||||
|
enum sdefl_blk_type {
|
||||||
|
SDEFL_BLK_UCOMPR,
|
||||||
|
SDEFL_BLK_DYN
|
||||||
|
};
|
||||||
|
static enum sdefl_blk_type
|
||||||
|
sdefl_blk_type(const struct sdefl *s, int blk_len, int pre_item_len,
|
||||||
|
const unsigned *pre_freq, const unsigned char *pre_len) {
|
||||||
|
static const unsigned char x_pre_bits[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
|
||||||
|
static const unsigned char x_len_bits[] = {0,0,0,0,0,0,0,0, 1,1,1,1,2,2,2,2,
|
||||||
|
3,3,3,3,4,4,4,4, 5,5,5,5,0};
|
||||||
|
static const unsigned char x_off_bits[] = {0,0,0,0,1,1,2,2, 3,3,4,4,5,5,6,6,
|
||||||
|
7,7,8,8,9,9,10,10, 11,11,12,12,13,13};
|
||||||
|
|
||||||
|
int dyn_cost = 0;
|
||||||
|
int fix_cost = 0;
|
||||||
|
int sym = 0;
|
||||||
|
|
||||||
|
dyn_cost += 5 + 5 + 4 + (3 * pre_item_len);
|
||||||
|
for (sym = 0; sym < SDEFL_PRE_MAX; sym++)
|
||||||
|
dyn_cost += pre_freq[sym] * (x_pre_bits[sym] + pre_len[sym]);
|
||||||
|
for (sym = 0; sym < 256; sym++)
|
||||||
|
dyn_cost += s->freq.lit[sym] * s->cod.len.lit[sym];
|
||||||
|
dyn_cost += s->cod.len.lit[SDEFL_EOB];
|
||||||
|
for (sym = 257; sym < 286; sym++)
|
||||||
|
dyn_cost += s->freq.lit[sym] * (x_len_bits[sym - 257] + s->cod.len.lit[sym]);
|
||||||
|
for (sym = 0; sym < 30; sym++)
|
||||||
|
dyn_cost += s->freq.off[sym] * (x_off_bits[sym] + s->cod.len.off[sym]);
|
||||||
|
|
||||||
|
fix_cost += 8*(5 * sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE) + blk_len + 1 + 2);
|
||||||
|
return (dyn_cost < fix_cost) ? SDEFL_BLK_DYN : SDEFL_BLK_UCOMPR;
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
sdefl_put16(unsigned char **dst, unsigned short x) {
|
||||||
|
unsigned char *val = *dst;
|
||||||
|
val[0] = (unsigned char)(x & 0xff);
|
||||||
|
val[1] = (unsigned char)(x >> 8);
|
||||||
|
*dst = val + 2;
|
||||||
|
}
|
||||||
static void
|
static void
|
||||||
sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||||
static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
|
static const char lxn[] = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
|
||||||
|
|
@ -479,7 +519,7 @@ sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||||
static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,
|
static const short dmin[] = {1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,
|
||||||
385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577};
|
||||||
|
|
||||||
struct sdefl_match_codes cod;
|
struct sdefl_match_codest cod;
|
||||||
sdefl_match_codes(&cod, dist, len);
|
sdefl_match_codes(&cod, dist, len);
|
||||||
sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]);
|
sdefl_put(dst, s, (int)s->cod.word.lit[cod.lc], s->cod.len.lit[cod.lc]);
|
||||||
sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]);
|
sdefl_put(dst, s, len - lmin[cod.ls], lxn[cod.ls]);
|
||||||
|
|
@ -488,7 +528,8 @@ sdefl_match(unsigned char **dst, struct sdefl *s, int dist, int len) {
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
const unsigned char *in) {
|
const unsigned char *in, int blk_begin, int blk_end) {
|
||||||
|
int blk_len = blk_end - blk_begin;
|
||||||
int j, i = 0, item_cnt = 0;
|
int j, i = 0, item_cnt = 0;
|
||||||
struct sdefl_symcnt symcnt = {0};
|
struct sdefl_symcnt symcnt = {0};
|
||||||
unsigned codes[SDEFL_PRE_MAX];
|
unsigned codes[SDEFL_PRE_MAX];
|
||||||
|
|
@ -498,7 +539,7 @@ sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11,
|
static const unsigned char perm[SDEFL_PRE_MAX] = {16,17,18,0,8,7,9,6,10,5,11,
|
||||||
4,12,3,13,2,14,1,15};
|
4,12,3,13,2,14,1,15};
|
||||||
|
|
||||||
/* huffman codes */
|
/* calculate huffman codes */
|
||||||
s->freq.lit[SDEFL_EOB]++;
|
s->freq.lit[SDEFL_EOB]++;
|
||||||
sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES);
|
sdefl_huff(s->cod.len.lit, s->cod.word.lit, s->freq.lit, SDEFL_SYM_MAX, SDEFL_LIT_LEN_CODES);
|
||||||
sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES);
|
sdefl_huff(s->cod.len.off, s->cod.word.off, s->freq.off, SDEFL_OFF_MAX, SDEFL_OFF_CODES);
|
||||||
|
|
@ -509,8 +550,30 @@ sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* block header */
|
/* write block */
|
||||||
sdefl_put(dst, s, is_last ? 0x01 : 0x00, 1); /* block */
|
switch (sdefl_blk_type(s, blk_len, item_cnt, freqs, lens)) {
|
||||||
|
case SDEFL_BLK_UCOMPR: {
|
||||||
|
/* uncompressed blocks */
|
||||||
|
int n = sdefl_div_round_up(blk_len, SDEFL_RAW_BLK_SIZE);
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
int fin = is_last && (i + 1 == n);
|
||||||
|
int amount = blk_len < SDEFL_RAW_BLK_SIZE ? blk_len : SDEFL_RAW_BLK_SIZE;
|
||||||
|
sdefl_put(dst, s, !!fin, 1); /* block */
|
||||||
|
sdefl_put(dst, s, 0x00, 2); /* stored block */
|
||||||
|
if (s->bitcnt) {
|
||||||
|
sdefl_put(dst, s, 0x00, 8 - s->bitcnt);
|
||||||
|
}
|
||||||
|
assert(s->bitcnt == 0);
|
||||||
|
sdefl_put16(dst, (unsigned short)amount);
|
||||||
|
sdefl_put16(dst, ~(unsigned short)amount);
|
||||||
|
memcpy(*dst, in + blk_begin + i * SDEFL_RAW_BLK_SIZE, amount);
|
||||||
|
*dst = *dst + amount;
|
||||||
|
blk_len -= amount;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case SDEFL_BLK_DYN: {
|
||||||
|
/* dynamic huffman block */
|
||||||
|
sdefl_put(dst, s, !!is_last, 1); /* block */
|
||||||
sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */
|
sdefl_put(dst, s, 0x02, 2); /* dynamic huffman */
|
||||||
sdefl_put(dst, s, symcnt.lit - 257, 5);
|
sdefl_put(dst, s, symcnt.lit - 257, 5);
|
||||||
sdefl_put(dst, s, symcnt.off - 1, 5);
|
sdefl_put(dst, s, symcnt.off - 1, 5);
|
||||||
|
|
@ -538,6 +601,7 @@ sdefl_flush(unsigned char **dst, struct sdefl *s, int is_last,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]);
|
sdefl_put(dst, s, (int)(s)->cod.word.lit[SDEFL_EOB], (s)->cod.len.lit[SDEFL_EOB]);
|
||||||
|
} break;}
|
||||||
memset(&s->freq, 0, sizeof(s->freq));
|
memset(&s->freq, 0, sizeof(s->freq));
|
||||||
s->seq_cnt = 0;
|
s->seq_cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -550,8 +614,12 @@ sdefl_seq(struct sdefl *s, int off, int len) {
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
sdefl_reg_match(struct sdefl *s, int off, int len) {
|
sdefl_reg_match(struct sdefl *s, int off, int len) {
|
||||||
struct sdefl_match_codes cod;
|
struct sdefl_match_codest cod;
|
||||||
sdefl_match_codes(&cod, off, len);
|
sdefl_match_codes(&cod, off, len);
|
||||||
|
|
||||||
|
assert(cod.lc < SDEFL_SYM_MAX);
|
||||||
|
assert(cod.dc < SDEFL_OFF_MAX);
|
||||||
|
|
||||||
s->freq.lit[cod.lc]++;
|
s->freq.lit[cod.lc]++;
|
||||||
s->freq.off[cod.dc]++;
|
s->freq.off[cod.dc]++;
|
||||||
}
|
}
|
||||||
|
|
@ -560,22 +628,35 @@ struct sdefl_match {
|
||||||
int len;
|
int len;
|
||||||
};
|
};
|
||||||
static void
|
static void
|
||||||
sdefl_fnd(struct sdefl_match *m, const struct sdefl *s,
|
sdefl_fnd(struct sdefl_match *m, const struct sdefl *s, int chain_len,
|
||||||
int chain_len, int max_match, const unsigned char *in, int p) {
|
int max_match, const unsigned char *in, int p, int e) {
|
||||||
int i = s->tbl[sdefl_hash32(&in[p])];
|
int i = s->tbl[sdefl_hash32(in + p)];
|
||||||
int limit = ((p-SDEFL_WIN_SIZ)<SDEFL_NIL)?SDEFL_NIL:(p-SDEFL_WIN_SIZ);
|
int limit = ((p - SDEFL_WIN_SIZ) < SDEFL_NIL) ? SDEFL_NIL : (p-SDEFL_WIN_SIZ);
|
||||||
|
|
||||||
|
assert(p < e);
|
||||||
|
assert(p + max_match <= e);
|
||||||
while (i > limit) {
|
while (i > limit) {
|
||||||
if (in[i+m->len] == in[p+m->len] &&
|
assert(i + m->len < e);
|
||||||
(sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))){
|
assert(p + m->len < e);
|
||||||
|
assert(i + SDEFL_MIN_MATCH < e);
|
||||||
|
assert(p + SDEFL_MIN_MATCH < e);
|
||||||
|
|
||||||
|
if (in[i + m->len] == in[p + m->len] &&
|
||||||
|
(sdefl_uload32(&in[i]) == sdefl_uload32(&in[p]))) {
|
||||||
int n = SDEFL_MIN_MATCH;
|
int n = SDEFL_MIN_MATCH;
|
||||||
while (n < max_match && in[i+n] == in[p+n]) n++;
|
while (n < max_match && in[i + n] == in[p + n]) {
|
||||||
|
assert(i + n < e);
|
||||||
|
assert(p + n < e);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
if (n > m->len) {
|
if (n > m->len) {
|
||||||
m->len = n, m->off = p - i;
|
m->len = n, m->off = p - i;
|
||||||
if (n == max_match) break;
|
if (n == max_match)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(--chain_len)) break;
|
if (!(--chain_len)) break;
|
||||||
i = s->prv[i&SDEFL_WIN_MSK];
|
i = s->prv[i & SDEFL_WIN_MSK];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
|
|
@ -588,19 +669,20 @@ sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in,
|
||||||
for (n = 0; n < SDEFL_HASH_SIZ; ++n) {
|
for (n = 0; n < SDEFL_HASH_SIZ; ++n) {
|
||||||
s->tbl[n] = SDEFL_NIL;
|
s->tbl[n] = SDEFL_NIL;
|
||||||
}
|
}
|
||||||
do {int blk_end = ((i + SDEFL_BLK_MAX) < in_len) ? (i + SDEFL_BLK_MAX) : in_len;
|
do {int blk_begin = i;
|
||||||
|
int blk_end = ((i + SDEFL_BLK_MAX) < in_len) ? (i + SDEFL_BLK_MAX) : in_len;
|
||||||
while (i < blk_end) {
|
while (i < blk_end) {
|
||||||
struct sdefl_match m = {0};
|
struct sdefl_match m = {0};
|
||||||
int left = blk_end - i;
|
int left = blk_end - i;
|
||||||
int max_match = (left >= SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH : left;
|
int max_match = (left > SDEFL_MAX_MATCH) ? SDEFL_MAX_MATCH : left;
|
||||||
int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match;
|
int nice_match = pref[lvl] < max_match ? pref[lvl] : max_match;
|
||||||
int run = 1, inc = 1, run_inc = 0;
|
int run = 1, inc = 1, run_inc = 0;
|
||||||
if (max_match > SDEFL_MIN_MATCH) {
|
if (max_match > SDEFL_MIN_MATCH) {
|
||||||
sdefl_fnd(&m, s, max_chain, max_match, in, i);
|
sdefl_fnd(&m, s, max_chain, max_match, in, i, in_len);
|
||||||
}
|
}
|
||||||
if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len < nice_match){
|
if (lvl >= 5 && m.len >= SDEFL_MIN_MATCH && m.len + 1 < nice_match){
|
||||||
struct sdefl_match m2 = {0};
|
struct sdefl_match m2 = {0};
|
||||||
sdefl_fnd(&m2, s, max_chain, m.len+1, in, i+1);
|
sdefl_fnd(&m2, s, max_chain, m.len + 1, in, i + 1, in_len);
|
||||||
m.len = (m2.len > m.len) ? 0 : m.len;
|
m.len = (m2.len > m.len) ? 0 : m.len;
|
||||||
}
|
}
|
||||||
if (m.len >= SDEFL_MIN_MATCH) {
|
if (m.len >= SDEFL_MIN_MATCH) {
|
||||||
|
|
@ -636,12 +718,12 @@ sdefl_compr(struct sdefl *s, unsigned char *out, const unsigned char *in,
|
||||||
sdefl_seq(s, i - litlen, litlen);
|
sdefl_seq(s, i - litlen, litlen);
|
||||||
litlen = 0;
|
litlen = 0;
|
||||||
}
|
}
|
||||||
sdefl_flush(&q, s, blk_end == in_len, in);
|
sdefl_flush(&q, s, blk_end == in_len, in, blk_begin, blk_end);
|
||||||
} while (i < in_len);
|
} while (i < in_len);
|
||||||
|
if (s->bitcnt) {
|
||||||
if (s->bitcnt > 0)
|
|
||||||
sdefl_put(&q, s, 0x00, 8 - s->bitcnt);
|
sdefl_put(&q, s, 0x00, 8 - s->bitcnt);
|
||||||
|
}
|
||||||
|
assert(s->bitcnt == 0);
|
||||||
return (int)(q - out);
|
return (int)(q - out);
|
||||||
}
|
}
|
||||||
extern int
|
extern int
|
||||||
|
|
@ -701,9 +783,8 @@ zsdeflate(struct sdefl *s, void *out, const void *in, int n, int lvl) {
|
||||||
}
|
}
|
||||||
extern int
|
extern int
|
||||||
sdefl_bound(int len) {
|
sdefl_bound(int len) {
|
||||||
int a = 128 + (len * 110) / 100;
|
int max_blocks = 1 + sdefl_div_round_up(len, SDEFL_RAW_BLK_SIZE);
|
||||||
int b = 128 + len + ((len / (31 * 1024)) + 1) * 5;
|
int bound = 5 * max_blocks + len + 1 + 4 + 8;
|
||||||
return (a > b) ? a : b;
|
return bound;
|
||||||
}
|
}
|
||||||
#endif /* SDEFL_IMPLEMENTATION */
|
#endif /* SDEFL_IMPLEMENTATION */
|
||||||
|
|
||||||
|
|
|
||||||
28
src/external/sinfl.h
vendored
28
src/external/sinfl.h
vendored
|
|
@ -72,7 +72,7 @@ Results on the [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index
|
||||||
This software is available under 2 licenses -- choose whichever you prefer.
|
This software is available under 2 licenses -- choose whichever you prefer.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
ALTERNATIVE A - MIT License
|
ALTERNATIVE A - MIT License
|
||||||
Copyright (c) 2020 Micha Mettke
|
Copyright (c) 2020-2023 Micha Mettke
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
the Software without restriction, including without limitation the rights to
|
the Software without restriction, including without limitation the rights to
|
||||||
|
|
@ -400,17 +400,21 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
} break;
|
} break;
|
||||||
case stored: {
|
case stored: {
|
||||||
/* uncompressed block */
|
/* uncompressed block */
|
||||||
int len, nlen;
|
unsigned len, nlen;
|
||||||
sinfl_refill(&s);
|
|
||||||
sinfl__get(&s,s.bitcnt & 7);
|
sinfl__get(&s,s.bitcnt & 7);
|
||||||
len = sinfl__get(&s,16);
|
len = (unsigned short)sinfl__get(&s,16);
|
||||||
nlen = sinfl__get(&s,16);
|
nlen = (unsigned short)sinfl__get(&s,16);
|
||||||
in -= 2; s.bitcnt = 0;
|
s.bitptr -= s.bitcnt / 8;
|
||||||
|
s.bitbuf = s.bitcnt = 0;
|
||||||
|
|
||||||
if (len > (e-in) || !len)
|
if ((unsigned short)len != (unsigned short)~nlen)
|
||||||
return (int)(out-o);
|
return (int)(out-o);
|
||||||
memcpy(out, in, (size_t)len);
|
if (len > (e - s.bitptr) || !len)
|
||||||
in += len, out += len;
|
return (int)(out-o);
|
||||||
|
|
||||||
|
memcpy(out, s.bitptr, (size_t)len);
|
||||||
|
s.bitptr += len, out += len;
|
||||||
|
if (last) return (int)(out-o);
|
||||||
state = hdr;
|
state = hdr;
|
||||||
} break;
|
} break;
|
||||||
case fixed: {
|
case fixed: {
|
||||||
|
|
@ -443,8 +447,9 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
|
|
||||||
/* decode code lengths */
|
/* decode code lengths */
|
||||||
for (n = 0; n < nlit + ndist;) {
|
for (n = 0; n < nlit + ndist;) {
|
||||||
|
int sym = 0;
|
||||||
sinfl_refill(&s);
|
sinfl_refill(&s);
|
||||||
int sym = sinfl_decode(&s, hlens, 7);
|
sym = sinfl_decode(&s, hlens, 7);
|
||||||
switch (sym) {default: lens[n++] = (unsigned char)sym; break;
|
switch (sym) {default: lens[n++] = (unsigned char)sym; break;
|
||||||
case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break;
|
case 16: for (i=3+sinfl_get(&s,2);i;i--,n++) lens[n]=lens[n-1]; break;
|
||||||
case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break;
|
case 17: for (i=3+sinfl_get(&s,3);i;i--,n++) lens[n]=0; break;
|
||||||
|
|
@ -458,8 +463,9 @@ sinfl_decompress(unsigned char *out, int cap, const unsigned char *in, int size)
|
||||||
case blk: {
|
case blk: {
|
||||||
/* decompress block */
|
/* decompress block */
|
||||||
while (1) {
|
while (1) {
|
||||||
|
int sym;
|
||||||
sinfl_refill(&s);
|
sinfl_refill(&s);
|
||||||
int sym = sinfl_decode(&s, s.lits, 10);
|
sym = sinfl_decode(&s, s.lits, 10);
|
||||||
if (sym < 256) {
|
if (sym < 256) {
|
||||||
/* literal */
|
/* literal */
|
||||||
if (sinfl_unlikely(out >= oe)) {
|
if (sinfl_unlikely(out >= oe)) {
|
||||||
|
|
|
||||||
|
|
@ -958,6 +958,7 @@ RLAPI void SetWindowMonitor(int monitor); // Set monitor
|
||||||
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
RLAPI void SetWindowMinSize(int width, int height); // Set window minimum dimensions (for FLAG_WINDOW_RESIZABLE)
|
||||||
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
RLAPI void SetWindowSize(int width, int height); // Set window dimensions
|
||||||
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
RLAPI void SetWindowOpacity(float opacity); // Set window opacity [0.0f..1.0f] (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI void SetWindowFocused(void); // Set window focused (only PLATFORM_DESKTOP)
|
||||||
RLAPI void *GetWindowHandle(void); // Get native window handle
|
RLAPI void *GetWindowHandle(void); // Get native window handle
|
||||||
RLAPI int GetScreenWidth(void); // Get current screen width
|
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||||
RLAPI int GetScreenHeight(void); // Get current screen height
|
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||||
|
|
@ -1381,6 +1382,7 @@ RLAPI void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float f
|
||||||
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
RLAPI void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 position, float fontSize, float spacing, Color tint); // Draw multiple character (codepoint)
|
||||||
|
|
||||||
// Text font info functions
|
// Text font info functions
|
||||||
|
RLAPI void SetTextLineSpacing(int spacing); // Set vertical line spacing when drawing with line-breaks
|
||||||
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
RLAPI Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing); // Measure string size for Font
|
||||||
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
RLAPI int GetGlyphIndex(Font font, int codepoint); // Get glyph index position in font for a codepoint (unicode character), fallback to '?' if not found
|
||||||
|
|
@ -1589,7 +1591,7 @@ RLAPI void SetAudioStreamCallback(AudioStream stream, AudioCallback callback);
|
||||||
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream
|
RLAPI void AttachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Attach audio stream processor to stream
|
||||||
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
RLAPI void DetachAudioStreamProcessor(AudioStream stream, AudioCallback processor); // Detach audio stream processor from stream
|
||||||
|
|
||||||
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline
|
RLAPI void AttachAudioMixedProcessor(AudioCallback processor); // Attach audio stream processor to the entire audio pipeline, receives the samples as <float>s
|
||||||
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
RLAPI void DetachAudioMixedProcessor(AudioCallback processor); // Detach audio stream processor from the entire audio pipeline
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,11 @@ RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2)
|
||||||
// NOTE: Angle is calculated from origin point (0, 0)
|
// NOTE: Angle is calculated from origin point (0, 0)
|
||||||
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
RMAPI float Vector2Angle(Vector2 v1, Vector2 v2)
|
||||||
{
|
{
|
||||||
float result = atan2f(v2.y - v1.y, v2.x - v1.x);
|
float result = 0.0f;
|
||||||
|
|
||||||
|
float dot = v1.x*v2.x + v1.y*v2.y;
|
||||||
|
float det = v1.x*v2.y - v1.y*v2.x;
|
||||||
|
result = -atan2f(det, dot);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -326,17 +330,7 @@ RMAPI float Vector2LineAngle(Vector2 start, Vector2 end)
|
||||||
{
|
{
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
|
|
||||||
float dot = start.x*end.x + start.y*end.y; // Dot product
|
result = atan2f(end.y - start.y, end.x - start.x);
|
||||||
|
|
||||||
float dotClamp = (dot < -1.0f)? -1.0f : dot; // Clamp
|
|
||||||
if (dotClamp > 1.0f) dotClamp = 1.0f;
|
|
||||||
|
|
||||||
result = acosf(dotClamp);
|
|
||||||
|
|
||||||
// Alternative implementation, more costly
|
|
||||||
//float v1Length = sqrtf((start.x*start.x) + (start.y*start.y));
|
|
||||||
//float v2Length = sqrtf((end.x*end.x) + (end.y*end.y));
|
|
||||||
//float result = -acosf((start.x*end.x + start.y*end.y)/(v1Length*v2Length));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -1515,11 +1509,11 @@ RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top,
|
||||||
|
|
||||||
// Get perspective projection matrix
|
// Get perspective projection matrix
|
||||||
// NOTE: Fovy angle must be provided in radians
|
// NOTE: Fovy angle must be provided in radians
|
||||||
RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
|
RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane)
|
||||||
{
|
{
|
||||||
Matrix result = { 0 };
|
Matrix result = { 0 };
|
||||||
|
|
||||||
double top = near*tan(fovy*0.5);
|
double top = nearPlane*tan(fovY*0.5);
|
||||||
double bottom = -top;
|
double bottom = -top;
|
||||||
double right = top*aspect;
|
double right = top*aspect;
|
||||||
double left = -right;
|
double left = -right;
|
||||||
|
|
@ -1527,27 +1521,27 @@ RMAPI Matrix MatrixPerspective(double fovy, double aspect, double near, double f
|
||||||
// MatrixFrustum(-right, right, -top, top, near, far);
|
// MatrixFrustum(-right, right, -top, top, near, far);
|
||||||
float rl = (float)(right - left);
|
float rl = (float)(right - left);
|
||||||
float tb = (float)(top - bottom);
|
float tb = (float)(top - bottom);
|
||||||
float fn = (float)(far - near);
|
float fn = (float)(farPlane - nearPlane);
|
||||||
|
|
||||||
result.m0 = ((float)near*2.0f)/rl;
|
result.m0 = ((float)nearPlane*2.0f)/rl;
|
||||||
result.m5 = ((float)near*2.0f)/tb;
|
result.m5 = ((float)nearPlane*2.0f)/tb;
|
||||||
result.m8 = ((float)right + (float)left)/rl;
|
result.m8 = ((float)right + (float)left)/rl;
|
||||||
result.m9 = ((float)top + (float)bottom)/tb;
|
result.m9 = ((float)top + (float)bottom)/tb;
|
||||||
result.m10 = -((float)far + (float)near)/fn;
|
result.m10 = -((float)farPlane + (float)nearPlane)/fn;
|
||||||
result.m11 = -1.0f;
|
result.m11 = -1.0f;
|
||||||
result.m14 = -((float)far*(float)near*2.0f)/fn;
|
result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get orthographic projection matrix
|
// Get orthographic projection matrix
|
||||||
RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far)
|
RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane)
|
||||||
{
|
{
|
||||||
Matrix result = { 0 };
|
Matrix result = { 0 };
|
||||||
|
|
||||||
float rl = (float)(right - left);
|
float rl = (float)(right - left);
|
||||||
float tb = (float)(top - bottom);
|
float tb = (float)(top - bottom);
|
||||||
float fn = (float)(far - near);
|
float fn = (float)(farPlane - nearPlane);
|
||||||
|
|
||||||
result.m0 = 2.0f/rl;
|
result.m0 = 2.0f/rl;
|
||||||
result.m1 = 0.0f;
|
result.m1 = 0.0f;
|
||||||
|
|
@ -1563,7 +1557,7 @@ RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, d
|
||||||
result.m11 = 0.0f;
|
result.m11 = 0.0f;
|
||||||
result.m12 = -((float)left + (float)right)/rl;
|
result.m12 = -((float)left + (float)right)/rl;
|
||||||
result.m13 = -((float)top + (float)bottom)/tb;
|
result.m13 = -((float)top + (float)bottom)/tb;
|
||||||
result.m14 = -((float)far + (float)near)/fn;
|
result.m14 = -((float)farPlane + (float)nearPlane)/fn;
|
||||||
result.m15 = 1.0f;
|
result.m15 = 1.0f;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
* rcamera - Basic camera system with support for multiple camera modes
|
* rcamera - Basic camera system with support for multiple camera modes
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define CAMERA_IMPLEMENTATION
|
* #define RCAMERA_IMPLEMENTATION
|
||||||
* Generates the implementation of the library into the included file.
|
* Generates the implementation of the library into the included file.
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
*
|
*
|
||||||
* #define CAMERA_STANDALONE
|
* #define RCAMERA_STANDALONE
|
||||||
* If defined, the library can be used as standalone as a camera system but some
|
* If defined, the library can be used as standalone as a camera system but some
|
||||||
* functions must be redefined to manage inputs accordingly.
|
* functions must be redefined to manage inputs accordingly.
|
||||||
*
|
*
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
|
#define RLAPI // Functions defined as 'extern' by default (implicit specifiers)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CAMERA_STANDALONE)
|
#if defined(RCAMERA_STANDALONE)
|
||||||
#define CAMERA_CULL_DISTANCE_NEAR 0.01
|
#define CAMERA_CULL_DISTANCE_NEAR 0.01
|
||||||
#define CAMERA_CULL_DISTANCE_FAR 1000.0
|
#define CAMERA_CULL_DISTANCE_FAR 1000.0
|
||||||
#else
|
#else
|
||||||
|
|
@ -60,9 +60,9 @@
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
// NOTE: Below types are required for CAMERA_STANDALONE usage
|
// NOTE: Below types are required for standalone usage
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(CAMERA_STANDALONE)
|
#if defined(RCAMERA_STANDALONE)
|
||||||
// Vector2, 2 components
|
// Vector2, 2 components
|
||||||
typedef struct Vector2 {
|
typedef struct Vector2 {
|
||||||
float x; // Vector x component
|
float x; // Vector x component
|
||||||
|
|
@ -76,6 +76,14 @@
|
||||||
float z; // Vector z component
|
float z; // Vector z component
|
||||||
} Vector3;
|
} Vector3;
|
||||||
|
|
||||||
|
// Matrix, 4x4 components, column major, OpenGL style, right-handed
|
||||||
|
typedef struct Matrix {
|
||||||
|
float m0, m4, m8, m12; // Matrix first row (4 components)
|
||||||
|
float m1, m5, m9, m13; // Matrix second row (4 components)
|
||||||
|
float m2, m6, m10, m14; // Matrix third row (4 components)
|
||||||
|
float m3, m7, m11, m15; // Matrix fourth row (4 components)
|
||||||
|
} Matrix;
|
||||||
|
|
||||||
// Camera type, defines a camera position/orientation in 3d space
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
typedef struct Camera3D {
|
typedef struct Camera3D {
|
||||||
Vector3 position; // Camera position
|
Vector3 position; // Camera position
|
||||||
|
|
@ -138,7 +146,7 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // CAMERA_H
|
#endif // RCAMERA_H
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************************
|
/***********************************************************************************
|
||||||
|
|
@ -147,7 +155,7 @@ RLAPI Matrix GetCameraProjectionMatrix(Camera* camera, float aspect);
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#if defined(CAMERA_IMPLEMENTATION)
|
#if defined(RCAMERA_IMPLEMENTATION)
|
||||||
|
|
||||||
#include "raymath.h" // Required for vector maths:
|
#include "raymath.h" // Required for vector maths:
|
||||||
// Vector3Add()
|
// Vector3Add()
|
||||||
|
|
@ -417,7 +425,7 @@ Matrix GetCameraProjectionMatrix(Camera *camera, float aspect)
|
||||||
return MatrixIdentity();
|
return MatrixIdentity();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CAMERA_STANDALONE
|
#if !defined(RCAMERA_STANDALONE)
|
||||||
// Update camera position for selected mode
|
// Update camera position for selected mode
|
||||||
// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
|
// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM
|
||||||
void UpdateCamera(Camera *camera, int mode)
|
void UpdateCamera(Camera *camera, int mode)
|
||||||
|
|
@ -483,7 +491,7 @@ void UpdateCamera(Camera *camera, int mode)
|
||||||
if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
|
if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !CAMERA_STANDALONE
|
#endif // !RCAMERA_STANDALONE
|
||||||
|
|
||||||
// Update camera movement, movement/rotation values should be provided by user
|
// Update camera movement, movement/rotation values should be provided by user
|
||||||
void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
|
void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom)
|
||||||
|
|
@ -516,4 +524,4 @@ void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float z
|
||||||
CameraMoveToTarget(camera, zoom);
|
CameraMoveToTarget(camera, zoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CAMERA_IMPLEMENTATION
|
#endif // RCAMERA_IMPLEMENTATION
|
||||||
|
|
|
||||||
27
src/rcore.c
27
src/rcore.c
|
|
@ -124,12 +124,12 @@
|
||||||
#include "raymath.h" // Vector3, Quaternion and Matrix functionality
|
#include "raymath.h" // Vector3, Quaternion and Matrix functionality
|
||||||
|
|
||||||
#if defined(SUPPORT_GESTURES_SYSTEM)
|
#if defined(SUPPORT_GESTURES_SYSTEM)
|
||||||
#define GESTURES_IMPLEMENTATION
|
#define RGESTURES_IMPLEMENTATION
|
||||||
#include "rgestures.h" // Gestures detection functionality
|
#include "rgestures.h" // Gestures detection functionality
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SUPPORT_CAMERA_SYSTEM)
|
#if defined(SUPPORT_CAMERA_SYSTEM)
|
||||||
#define CAMERA_IMPLEMENTATION
|
#define RCAMERA_IMPLEMENTATION
|
||||||
#include "rcamera.h" // Camera system functionality
|
#include "rcamera.h" // Camera system functionality
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -1705,6 +1705,14 @@ void SetWindowOpacity(float opacity)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set window focused
|
||||||
|
void SetWindowFocused(void)
|
||||||
|
{
|
||||||
|
#if defined(PLATFORM_DESKTOP)
|
||||||
|
glfwFocusWindow(CORE.Window.handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Get current screen width
|
// Get current screen width
|
||||||
int GetScreenWidth(void)
|
int GetScreenWidth(void)
|
||||||
{
|
{
|
||||||
|
|
@ -3219,7 +3227,7 @@ const char *GetApplicationDirectory(void)
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
int len = 0;
|
int len = 0;
|
||||||
#if defined (UNICODE)
|
#if defined(UNICODE)
|
||||||
unsigned short widePath[MAX_PATH];
|
unsigned short widePath[MAX_PATH];
|
||||||
len = GetModuleFileNameW(NULL, widePath, MAX_PATH);
|
len = GetModuleFileNameW(NULL, widePath, MAX_PATH);
|
||||||
len = WideCharToMultiByte(0, 0, widePath, len, appDir, MAX_PATH, NULL, NULL);
|
len = WideCharToMultiByte(0, 0, widePath, len, appDir, MAX_PATH, NULL, NULL);
|
||||||
|
|
@ -5585,8 +5593,14 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int
|
||||||
gestureEvent.position[0].y /= (float)GetScreenHeight();
|
gestureEvent.position[0].y /= (float)GetScreenHeight();
|
||||||
|
|
||||||
// Gesture data is sent to gestures-system for processing
|
// Gesture data is sent to gestures-system for processing
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
// Prevent calling ProcessGestureEvent() when Emscripten is present and there's a touch gesture, so EmscriptenTouchCallback() can handle it itself
|
||||||
|
if (GetMouseX() != 0 || GetMouseY() != 0) ProcessGestureEvent(gestureEvent);
|
||||||
|
#else
|
||||||
ProcessGestureEvent(gestureEvent);
|
ProcessGestureEvent(gestureEvent);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// GLFW3 Cursor Position Callback, runs on mouse move
|
// GLFW3 Cursor Position Callback, runs on mouse move
|
||||||
|
|
@ -6123,10 +6137,17 @@ static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent
|
||||||
{
|
{
|
||||||
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
gestureEvent.pointId[i] = CORE.Input.Touch.pointId[i];
|
||||||
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
gestureEvent.position[i] = CORE.Input.Touch.position[i];
|
||||||
|
|
||||||
|
// Normalize gestureEvent.position[i]
|
||||||
|
gestureEvent.position[i].x /= (float)GetScreenWidth();
|
||||||
|
gestureEvent.position[i].y /= (float)GetScreenHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gesture data is sent to gestures system for processing
|
// Gesture data is sent to gestures system for processing
|
||||||
ProcessGestureEvent(gestureEvent);
|
ProcessGestureEvent(gestureEvent);
|
||||||
|
|
||||||
|
// Reset the pointCount for web, if it was the last Touch End event
|
||||||
|
if (eventType == EMSCRIPTEN_EVENT_TOUCHEND && CORE.Input.Touch.pointCount == 1) CORE.Input.Touch.pointCount = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 1; // The event was consumed by the callback handler
|
return 1; // The event was consumed by the callback handler
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
* rgestures - Gestures system, gestures processing based on input events (touch/mouse)
|
* rgestures - Gestures system, gestures processing based on input events (touch/mouse)
|
||||||
*
|
*
|
||||||
* CONFIGURATION:
|
* CONFIGURATION:
|
||||||
* #define GESTURES_IMPLEMENTATION
|
* #define RGESTURES_IMPLEMENTATION
|
||||||
* Generates the implementation of the library into the included file.
|
* Generates the implementation of the library into the included file.
|
||||||
* If not defined, the library is in header only mode and can be included in other headers
|
* If not defined, the library is in header only mode and can be included in other headers
|
||||||
* or source files without problems. But only ONE file should hold the implementation.
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
*
|
*
|
||||||
* #define GESTURES_STANDALONE
|
* #define RGESTURES_STANDALONE
|
||||||
* If defined, the library can be used as standalone to process gesture events with
|
* If defined, the library can be used as standalone to process gesture events with
|
||||||
* no external dependencies.
|
* no external dependencies.
|
||||||
*
|
*
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Types and Structures Definition
|
// Types and Structures Definition
|
||||||
// NOTE: Below types are required for GESTURES_STANDALONE usage
|
// NOTE: Below types are required for standalone usage
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Boolean type
|
// Boolean type
|
||||||
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
#if (defined(__STDC__) && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||||
|
|
@ -73,7 +73,7 @@ typedef struct Vector2 {
|
||||||
} Vector2;
|
} Vector2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
// Gestures type
|
// Gestures type
|
||||||
// NOTE: It could be used as flags to enable only some gestures
|
// NOTE: It could be used as flags to enable only some gestures
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -122,12 +122,12 @@ extern "C" { // Prevents name mangling of functions
|
||||||
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
||||||
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
void SetGesturesEnabled(unsigned int flags); // Enable a set of gestures using flags
|
||||||
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
int GetGestureDetected(void); // Get latest detected gesture
|
int GetGestureDetected(void); // Get latest detected gesture
|
||||||
|
|
||||||
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
float GetGestureHoldDuration(void); // Get gesture hold time in seconds
|
||||||
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
float GetGestureDragAngle(void); // Get gesture drag angle
|
float GetGestureDragAngle(void); // Get gesture drag angle
|
||||||
Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
||||||
|
|
@ -138,17 +138,17 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // GESTURES_H
|
#endif // RGESTURES_H
|
||||||
|
|
||||||
/***********************************************************************************
|
/***********************************************************************************
|
||||||
*
|
*
|
||||||
* GESTURES IMPLEMENTATION
|
* RGESTURES IMPLEMENTATION
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#if defined(GESTURES_IMPLEMENTATION)
|
#if defined(RGESTURES_IMPLEMENTATION)
|
||||||
|
|
||||||
#if defined(GESTURES_STANDALONE)
|
#if defined(RGESTURES_STANDALONE)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" { // Prevents name mangling of functions
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
|
@ -178,11 +178,12 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Defines and Macros
|
// Defines and Macros
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#define FORCE_TO_SWIPE 0.0005f // Swipe force, measured in normalized screen units/time
|
#define FORCE_TO_SWIPE 0.2f // Swipe force, measured in normalized screen units/time
|
||||||
#define MINIMUM_DRAG 0.015f // Drag minimum force, measured in normalized screen units (0.0f to 1.0f)
|
#define MINIMUM_DRAG 0.015f // Drag minimum force, measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
#define DRAG_TIMEOUT 0.2f // Drag minimum time for web, measured in seconds
|
||||||
#define MINIMUM_PINCH 0.005f // Pinch minimum force, measured in normalized screen units (0.0f to 1.0f)
|
#define MINIMUM_PINCH 0.005f // Pinch minimum force, measured in normalized screen units (0.0f to 1.0f)
|
||||||
#define TAP_TIMEOUT 300 // Tap minimum time, measured in milliseconds
|
#define TAP_TIMEOUT 0.3f // Tap minimum time, measured in seconds
|
||||||
#define PINCH_TIMEOUT 300 // Pinch minimum time, measured in milliseconds
|
#define PINCH_TIMEOUT 0.3f // Pinch minimum time, measured in seconds
|
||||||
#define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f)
|
#define DOUBLETAP_RANGE 0.03f // DoubleTap range, measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -203,11 +204,13 @@ typedef struct {
|
||||||
Vector2 downDragPosition; // Touch drag position
|
Vector2 downDragPosition; // Touch drag position
|
||||||
Vector2 moveDownPositionA; // First touch down position on move
|
Vector2 moveDownPositionA; // First touch down position on move
|
||||||
Vector2 moveDownPositionB; // Second touch down position on move
|
Vector2 moveDownPositionB; // Second touch down position on move
|
||||||
|
Vector2 previousPositionA; // Previous position A to compare for pinch gestures
|
||||||
|
Vector2 previousPositionB; // Previous position B to compare for pinch gestures
|
||||||
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
|
int tapCounter; // TAP counter (one tap implies TOUCH_ACTION_DOWN and TOUCH_ACTION_UP actions)
|
||||||
} Touch;
|
} Touch;
|
||||||
struct {
|
struct {
|
||||||
bool resetRequired; // HOLD reset to get first touch point again
|
bool resetRequired; // HOLD reset to get first touch point again
|
||||||
double timeDuration; // HOLD duration in milliseconds
|
double timeDuration; // HOLD duration in seconds
|
||||||
} Hold;
|
} Hold;
|
||||||
struct {
|
struct {
|
||||||
Vector2 vector; // DRAG vector (between initial and current position)
|
Vector2 vector; // DRAG vector (between initial and current position)
|
||||||
|
|
@ -295,7 +298,8 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
}
|
}
|
||||||
else if (event.touchAction == TOUCH_ACTION_UP)
|
else if (event.touchAction == TOUCH_ACTION_UP)
|
||||||
{
|
{
|
||||||
if (GESTURES.current == GESTURE_DRAG) GESTURES.Touch.upPosition = event.position[0];
|
// A swipe can happen while the current gesture is drag, but (specially for web) also hold, so set upPosition for both cases
|
||||||
|
if (GESTURES.current == GESTURE_DRAG || GESTURES.current == GESTURE_HOLD) GESTURES.Touch.upPosition = event.position[0];
|
||||||
|
|
||||||
// NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
|
// NOTE: GESTURES.Drag.intensity dependent on the resolution of the screen
|
||||||
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
|
|
@ -310,9 +314,9 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
GESTURES.Drag.angle = 360.0f - rgVector2Angle(GESTURES.Touch.downPositionA, GESTURES.Touch.upPosition);
|
||||||
|
|
||||||
if ((GESTURES.Drag.angle < 30) || (GESTURES.Drag.angle > 330)) GESTURES.current = GESTURE_SWIPE_RIGHT; // Right
|
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 >= 30) && (GESTURES.Drag.angle <= 150)) 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 > 150) && (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 if ((GESTURES.Drag.angle >= 210) && (GESTURES.Drag.angle <= 330)) GESTURES.current = GESTURE_SWIPE_DOWN; // Down
|
||||||
else GESTURES.current = GESTURE_NONE;
|
else GESTURES.current = GESTURE_NONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -346,7 +350,12 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Hold.resetRequired = false;
|
GESTURES.Hold.resetRequired = false;
|
||||||
|
|
||||||
// Detect GESTURE_DRAG
|
// Detect GESTURE_DRAG
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
// An alternative check to detect gesture drag is necessary since moveDownPositionA on touch for web is always zero, causing the distance calculation to be inaccurate
|
||||||
|
if ((rgGetCurrentTime() - GESTURES.Touch.eventTime) > DRAG_TIMEOUT)
|
||||||
|
#else
|
||||||
if (rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
|
if (rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_DRAG)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
GESTURES.Touch.eventTime = rgGetCurrentTime();
|
||||||
GESTURES.current = GESTURE_DRAG;
|
GESTURES.current = GESTURE_DRAG;
|
||||||
|
|
@ -364,6 +373,9 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
GESTURES.Touch.downPositionA = event.position[0];
|
GESTURES.Touch.downPositionA = event.position[0];
|
||||||
GESTURES.Touch.downPositionB = event.position[1];
|
GESTURES.Touch.downPositionB = event.position[1];
|
||||||
|
|
||||||
|
GESTURES.Touch.previousPositionA = GESTURES.Touch.downPositionA;
|
||||||
|
GESTURES.Touch.previousPositionB = GESTURES.Touch.downPositionB;
|
||||||
|
|
||||||
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
|
//GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.downPositionB);
|
||||||
|
|
||||||
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
|
GESTURES.Pinch.vector.x = GESTURES.Touch.downPositionB.x - GESTURES.Touch.downPositionA.x;
|
||||||
|
|
@ -376,18 +388,15 @@ void ProcessGestureEvent(GestureEvent event)
|
||||||
{
|
{
|
||||||
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
GESTURES.Pinch.distance = rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB);
|
||||||
|
|
||||||
GESTURES.Touch.downPositionA = GESTURES.Touch.moveDownPositionA;
|
|
||||||
GESTURES.Touch.downPositionB = GESTURES.Touch.moveDownPositionB;
|
|
||||||
|
|
||||||
GESTURES.Touch.moveDownPositionA = event.position[0];
|
GESTURES.Touch.moveDownPositionA = event.position[0];
|
||||||
GESTURES.Touch.moveDownPositionB = event.position[1];
|
GESTURES.Touch.moveDownPositionB = event.position[1];
|
||||||
|
|
||||||
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
|
GESTURES.Pinch.vector.x = GESTURES.Touch.moveDownPositionB.x - GESTURES.Touch.moveDownPositionA.x;
|
||||||
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
|
GESTURES.Pinch.vector.y = GESTURES.Touch.moveDownPositionB.y - GESTURES.Touch.moveDownPositionA.y;
|
||||||
|
|
||||||
if ((rgVector2Distance(GESTURES.Touch.downPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.downPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
|
if ((rgVector2Distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.moveDownPositionA) >= MINIMUM_PINCH) || (rgVector2Distance(GESTURES.Touch.previousPositionB, GESTURES.Touch.moveDownPositionB) >= MINIMUM_PINCH))
|
||||||
{
|
{
|
||||||
if ((rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) - GESTURES.Pinch.distance) < 0) GESTURES.current = GESTURE_PINCH_IN;
|
if ( rgVector2Distance(GESTURES.Touch.previousPositionA, GESTURES.Touch.previousPositionB) > rgVector2Distance(GESTURES.Touch.moveDownPositionA, GESTURES.Touch.moveDownPositionB) ) GESTURES.current = GESTURE_PINCH_IN;
|
||||||
else GESTURES.current = GESTURE_PINCH_OUT;
|
else GESTURES.current = GESTURE_PINCH_OUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -520,12 +529,12 @@ static float rgVector2Distance(Vector2 v1, Vector2 v2)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time measure returned are milliseconds
|
// Time measure returned are seconds
|
||||||
static double rgGetCurrentTime(void)
|
static double rgGetCurrentTime(void)
|
||||||
{
|
{
|
||||||
double time = 0;
|
double time = 0;
|
||||||
|
|
||||||
#if !defined(GESTURES_STANDALONE)
|
#if !defined(RGESTURES_STANDALONE)
|
||||||
time = GetTime();
|
time = GetTime();
|
||||||
#else
|
#else
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
@ -534,7 +543,7 @@ static double rgGetCurrentTime(void)
|
||||||
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
QueryPerformanceFrequency(&clockFrequency); // BE CAREFUL: Costly operation!
|
||||||
QueryPerformanceCounter(¤tTime);
|
QueryPerformanceCounter(¤tTime);
|
||||||
|
|
||||||
time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds
|
time = (double)currentTime/clockFrequency; // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
|
@ -543,7 +552,7 @@ static double rgGetCurrentTime(void)
|
||||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||||
|
|
||||||
time = ((double)nowTime/1000000.0); // Time in miliseconds
|
time = ((double)nowTime*1e-9); // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
|
@ -559,11 +568,11 @@ static double rgGetCurrentTime(void)
|
||||||
mach_port_deallocate(mach_task_self(), cclock);
|
mach_port_deallocate(mach_task_self(), cclock);
|
||||||
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
unsigned long long int nowTime = (unsigned long long int)now.tv_sec*1000000000LLU + (unsigned long long int)now.tv_nsec; // Time in nanoseconds
|
||||||
|
|
||||||
time = ((double)nowTime/1000000.0); // Time in miliseconds
|
time = ((double)nowTime*1e-9); // Time in seconds
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GESTURES_IMPLEMENTATION
|
#endif // RGESTURES_IMPLEMENTATION
|
||||||
|
|
|
||||||
229
src/rshapes.c
229
src/rshapes.c
|
|
@ -80,7 +80,7 @@
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (usually a white pixel)
|
Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (white pixel loaded by rlgl)
|
||||||
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
|
Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
@ -97,8 +97,19 @@ static float EaseCubicInOut(float t, float b, float c, float d); // Cubic eas
|
||||||
// defining a font char white rectangle would allow drawing everything in a single draw call
|
// defining a font char white rectangle would allow drawing everything in a single draw call
|
||||||
void SetShapesTexture(Texture2D texture, Rectangle source)
|
void SetShapesTexture(Texture2D texture, Rectangle source)
|
||||||
{
|
{
|
||||||
|
// Reset texture to default pixel if required
|
||||||
|
// WARNING: Shapes texture should be probably better validated,
|
||||||
|
// it can break the rendering of all shapes if missused
|
||||||
|
if ((texture.id == 0) || (source.width == 0) || (source.height == 0))
|
||||||
|
{
|
||||||
|
texShapes = (Texture2D){ 1, 1, 1, 1, 7 };
|
||||||
|
texShapesRec = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
texShapes = texture;
|
texShapes = texture;
|
||||||
texShapesRec = source;
|
texShapesRec = source;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a pixel
|
// Draw a pixel
|
||||||
|
|
@ -382,14 +393,14 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += (stepLength*2);
|
angle += (stepLength*2);
|
||||||
}
|
}
|
||||||
|
|
@ -402,11 +413,11 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
@ -421,8 +432,8 @@ void DrawCircleSector(Vector2 center, float radius, float startAngle, float endA
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -464,15 +475,15 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -481,7 +492,7 @@ void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -496,9 +507,9 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co
|
||||||
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||||
rlVertex2f((float)centerX, (float)centerY);
|
rlVertex2f((float)centerX, (float)centerY);
|
||||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radius, (float)centerY + cosf(DEG2RAD*i)*radius);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radius, (float)centerY + sinf(DEG2RAD*(i + 10))*radius);
|
||||||
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radius, (float)centerY + cosf(DEG2RAD*(i + 10))*radius);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radius, (float)centerY + sinf(DEG2RAD*i)*radius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -519,8 +530,8 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
||||||
for (int i = 0; i < 360; i += 10)
|
for (int i = 0; i < 360; i += 10)
|
||||||
{
|
{
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
rlVertex2f(centerX + cosf(DEG2RAD*i)*radius, centerY + sinf(DEG2RAD*i)*radius);
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
rlVertex2f(centerX + cosf(DEG2RAD*(i + 10))*radius, centerY + sinf(DEG2RAD*(i + 10))*radius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -533,8 +544,8 @@ void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color c
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f((float)centerX, (float)centerY);
|
rlVertex2f((float)centerX, (float)centerY);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radiusH, (float)centerY + cosf(DEG2RAD*i)*radiusV);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*(i + 10))*radiusH, (float)centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||||
rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radiusH, (float)centerY + cosf(DEG2RAD*(i + 10))*radiusV);
|
rlVertex2f((float)centerX + cosf(DEG2RAD*i)*radiusH, (float)centerY + sinf(DEG2RAD*i)*radiusV);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -546,8 +557,8 @@ void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Co
|
||||||
for (int i = 0; i < 360; i += 10)
|
for (int i = 0; i < 360; i += 10)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*i)*radiusH, centerY + cosf(DEG2RAD*i)*radiusV);
|
rlVertex2f(centerX + cosf(DEG2RAD*(i + 10))*radiusH, centerY + sinf(DEG2RAD*(i + 10))*radiusV);
|
||||||
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radiusH, centerY + cosf(DEG2RAD*(i + 10))*radiusV);
|
rlVertex2f(centerX + cosf(DEG2RAD*i)*radiusH, centerY + sinf(DEG2RAD*i)*radiusV);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -605,17 +616,17 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startA
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -628,13 +639,13 @@ void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startA
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -691,19 +702,19 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float s
|
||||||
if (showCapLines)
|
if (showCapLines)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -711,8 +722,8 @@ void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float s
|
||||||
if (showCapLines)
|
if (showCapLines)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -971,7 +982,7 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
|
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
|
||||||
const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
|
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||||
|
|
||||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
|
|
@ -989,12 +1000,16 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
angle += (stepLength*2);
|
angle += (stepLength*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1004,10 +1019,13 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
}
|
}
|
||||||
|
|
@ -1082,8 +1100,8 @@ void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color co
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1197,7 +1215,7 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
{(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
|
{(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
|
||||||
};
|
};
|
||||||
|
|
||||||
const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
|
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
|
||||||
|
|
||||||
if (lineThick > 1)
|
if (lineThick > 1)
|
||||||
{
|
{
|
||||||
|
|
@ -1214,14 +1232,18 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -1286,13 +1308,13 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*innerRadius, center.y + sinf(DEG2RAD*angle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
|
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
|
|
@ -1350,8 +1372,8 @@ void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, flo
|
||||||
for (int i = 0; i < segments; i++)
|
for (int i = 0; i < segments; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*angle)*outerRadius, center.y + sinf(DEG2RAD*angle)*outerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + sinf(DEG2RAD*(angle + stepLength))*outerRadius);
|
||||||
angle += stepLength;
|
angle += stepLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1481,7 +1503,8 @@ void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)
|
||||||
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
float centralAngle = rotation;
|
float centralAngle = rotation*DEG2RAD;
|
||||||
|
float angleStep = 360.0f/(float)sides*DEG2RAD;
|
||||||
|
|
||||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||||
rlSetTexture(texShapes.id);
|
rlSetTexture(texShapes.id);
|
||||||
|
|
@ -1490,19 +1513,21 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < sides; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
float nextAngle = centralAngle + angleStep;
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
centralAngle += 360.0f/(float)sides;
|
centralAngle = nextAngle;
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
|
@ -1513,10 +1538,10 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x, center.y);
|
rlVertex2f(center.x, center.y);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle + angleStep)*radius, center.y + sinf(centralAngle + angleStep)*radius);
|
||||||
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
centralAngle += 360.0f/(float)sides;
|
centralAngle += angleStep;
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1526,16 +1551,18 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
|
||||||
void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
|
void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
float centralAngle = rotation;
|
float centralAngle = rotation*DEG2RAD;
|
||||||
|
float angleStep = 360.0f/(float)sides*DEG2RAD;
|
||||||
|
|
||||||
rlBegin(RL_LINES);
|
rlBegin(RL_LINES);
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < sides; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
centralAngle += 360.0f/(float)sides;
|
rlVertex2f(center.x + cosf(centralAngle + angleStep)*radius, center.y + sinf(centralAngle + angleStep)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
|
centralAngle += angleStep;
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
}
|
}
|
||||||
|
|
@ -1543,8 +1570,8 @@ void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Colo
|
||||||
void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
|
void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
|
||||||
{
|
{
|
||||||
if (sides < 3) sides = 3;
|
if (sides < 3) sides = 3;
|
||||||
float centralAngle = rotation;
|
float centralAngle = rotation*DEG2RAD;
|
||||||
float exteriorAngle = 360.0f/(float)sides;
|
float exteriorAngle = 360.0f/(float)sides*DEG2RAD;
|
||||||
float innerRadius = radius - (lineThick*cosf(DEG2RAD*exteriorAngle/2.0f));
|
float innerRadius = radius - (lineThick*cosf(DEG2RAD*exteriorAngle/2.0f));
|
||||||
|
|
||||||
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
||||||
|
|
@ -1554,19 +1581,21 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
|
||||||
for (int i = 0; i < sides; i++)
|
for (int i = 0; i < sides; i++)
|
||||||
{
|
{
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
float nextAngle = centralAngle + exteriorAngle;
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
|
||||||
|
|
||||||
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
|
|
||||||
centralAngle += exteriorAngle;
|
rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
|
||||||
|
|
||||||
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
|
||||||
|
|
||||||
|
rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height);
|
||||||
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
|
|
||||||
|
centralAngle = nextAngle;
|
||||||
}
|
}
|
||||||
rlEnd();
|
rlEnd();
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
|
|
@ -1577,13 +1606,13 @@ void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, fl
|
||||||
rlColor4ub(color.r, color.g, color.b, color.a);
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
float nextAngle = centralAngle + exteriorAngle;
|
float nextAngle = centralAngle + exteriorAngle;
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*radius, center.y + cosf(DEG2RAD*centralAngle)*radius);
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(centralAngle)*radius, center.y + sinf(centralAngle)*radius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*nextAngle)*radius, center.y + cosf(DEG2RAD*nextAngle)*radius);
|
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
|
||||||
|
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*centralAngle)*innerRadius, center.y + cosf(DEG2RAD*centralAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(centralAngle)*innerRadius, center.y + sinf(centralAngle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*nextAngle)*radius, center.y + cosf(DEG2RAD*nextAngle)*radius);
|
rlVertex2f(center.x + cosf(nextAngle)*innerRadius, center.y + sinf(nextAngle)*innerRadius);
|
||||||
rlVertex2f(center.x + sinf(DEG2RAD*nextAngle)*innerRadius, center.y + cosf(DEG2RAD*nextAngle)*innerRadius);
|
rlVertex2f(center.x + cosf(nextAngle)*radius, center.y + sinf(nextAngle)*radius);
|
||||||
|
|
||||||
centralAngle = nextAngle;
|
centralAngle = nextAngle;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
src/rtext.c
112
src/rtext.c
|
|
@ -6,14 +6,19 @@
|
||||||
* #define SUPPORT_MODULE_RTEXT
|
* #define SUPPORT_MODULE_RTEXT
|
||||||
* rtext module is included in the build
|
* rtext module is included in the build
|
||||||
*
|
*
|
||||||
|
* #define SUPPORT_DEFAULT_FONT
|
||||||
|
* Load default raylib font on initialization to be used by DrawText() and MeasureText().
|
||||||
|
* If no default font loaded, DrawTextEx() and MeasureTextEx() are required.
|
||||||
|
*
|
||||||
* #define SUPPORT_FILEFORMAT_FNT
|
* #define SUPPORT_FILEFORMAT_FNT
|
||||||
* #define SUPPORT_FILEFORMAT_TTF
|
* #define SUPPORT_FILEFORMAT_TTF
|
||||||
* Selected desired fileformats to be supported for loading. Some of those formats are
|
* Selected desired fileformats to be supported for loading. Some of those formats are
|
||||||
* supported by default, to remove support, just comment unrequired #define in this module
|
* supported by default, to remove support, just comment unrequired #define in this module
|
||||||
*
|
*
|
||||||
* #define SUPPORT_DEFAULT_FONT
|
* #define SUPPORT_FONT_ATLAS_WHITE_REC
|
||||||
* Load default raylib font on initialization to be used by DrawText() and MeasureText().
|
* On font atlas image generation [GenImageFontAtlas()], add a 3x3 pixels white rectangle
|
||||||
* If no default font loaded, DrawTextEx() and MeasureTextEx() are required.
|
* at the bottom-right corner of the atlas. It can be useful to for shapes drawing, to allow
|
||||||
|
* drawing text and shapes with a single draw call [SetShapesTexture()].
|
||||||
*
|
*
|
||||||
* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
|
* #define TEXTSPLIT_MAX_TEXT_BUFFER_LENGTH
|
||||||
* TextSplit() function static buffer max size
|
* TextSplit() function static buffer max size
|
||||||
|
|
@ -113,6 +118,7 @@ static Font defaultFont = { 0 };
|
||||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||||
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||||
#endif
|
#endif
|
||||||
|
static int textLineSpacing = 15; // Text vertical line spacing in pixels
|
||||||
|
|
||||||
#if defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_DEFAULT_FONT)
|
||||||
extern void LoadFontDefault(void);
|
extern void LoadFontDefault(void);
|
||||||
|
|
@ -123,7 +129,6 @@ extern void UnloadFontDefault(void);
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(SUPPORT_DEFAULT_FONT)
|
#if defined(SUPPORT_DEFAULT_FONT)
|
||||||
|
|
||||||
// Load raylib default font
|
// Load raylib default font
|
||||||
extern void LoadFontDefault(void)
|
extern void LoadFontDefault(void)
|
||||||
{
|
{
|
||||||
|
|
@ -699,9 +704,11 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
for (int i = 0; i < glyphCount; i++)
|
for (int i = 0; i < glyphCount; i++)
|
||||||
{
|
{
|
||||||
if (chars[i].image.width > maxGlyphWidth) maxGlyphWidth = chars[i].image.width;
|
if (chars[i].image.width > maxGlyphWidth) maxGlyphWidth = chars[i].image.width;
|
||||||
totalWidth += chars[i].image.width + 2*padding;
|
totalWidth += chars[i].image.width + 4*padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#define SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE
|
||||||
|
#if defined(SUPPORT_FONT_ATLAS_SIZE_CONSERVATIVE)
|
||||||
int rowCount = 0;
|
int rowCount = 0;
|
||||||
int imageSize = 64; // Define minimum starting value to avoid unnecessary calculation steps for very small images
|
int imageSize = 64; // Define minimum starting value to avoid unnecessary calculation steps for very small images
|
||||||
|
|
||||||
|
|
@ -714,6 +721,24 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
|
|
||||||
atlas.width = imageSize; // Atlas bitmap width
|
atlas.width = imageSize; // Atlas bitmap width
|
||||||
atlas.height = imageSize; // Atlas bitmap height
|
atlas.height = imageSize; // Atlas bitmap height
|
||||||
|
#else
|
||||||
|
// No need for a so-conservative atlas generation
|
||||||
|
float totalArea = totalWidth*fontSize*1.2f;
|
||||||
|
float imageMinSize = sqrtf(totalArea);
|
||||||
|
int imageSize = (int)powf(2, ceilf(logf(imageMinSize)/logf(2)));
|
||||||
|
|
||||||
|
if (totalArea < ((imageSize*imageSize)/2))
|
||||||
|
{
|
||||||
|
atlas.width = imageSize; // Atlas bitmap width
|
||||||
|
atlas.height = imageSize/2; // Atlas bitmap height
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
atlas.width = imageSize; // Atlas bitmap width
|
||||||
|
atlas.height = imageSize; // Atlas bitmap height
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
atlas.data = (unsigned char *)RL_CALLOC(1, atlas.width*atlas.height); // Create a bitmap to store characters (8 bpp)
|
||||||
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
atlas.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE;
|
||||||
atlas.mipmaps = 1;
|
atlas.mipmaps = 1;
|
||||||
|
|
@ -819,6 +844,19 @@ Image GenImageFontAtlas(const GlyphInfo *chars, Rectangle **charRecs, int glyphC
|
||||||
RL_FREE(context);
|
RL_FREE(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(SUPPORT_FONT_ATLAS_WHITE_REC)
|
||||||
|
// Add a 3x3 white rectangle at the bottom-right corner of the generated atlas,
|
||||||
|
// useful to use as the white texture to draw shapes with raylib, using this rectangle
|
||||||
|
// shapes and text can be backed into a single draw call: SetShapesTexture()
|
||||||
|
for (int i = 0, k = atlas.width*atlas.height - 1; i < 3; i++)
|
||||||
|
{
|
||||||
|
((unsigned char *)atlas.data)[k - 0] = 255;
|
||||||
|
((unsigned char *)atlas.data)[k - 1] = 255;
|
||||||
|
((unsigned char *)atlas.data)[k - 2] = 255;
|
||||||
|
k -= atlas.width;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Convert image data from GRAYSCALE to GRAY_ALPHA
|
// Convert image data from GRAYSCALE to GRAY_ALPHA
|
||||||
unsigned char *dataGrayAlpha = (unsigned char *)RL_MALLOC(atlas.width*atlas.height*sizeof(unsigned char)*2); // Two channels
|
unsigned char *dataGrayAlpha = (unsigned char *)RL_MALLOC(atlas.width*atlas.height*sizeof(unsigned char)*2); // Two channels
|
||||||
|
|
||||||
|
|
@ -1071,9 +1109,8 @@ void DrawTextEx(Font font, const char *text, Vector2 position, float fontSize, f
|
||||||
|
|
||||||
if (codepoint == '\n')
|
if (codepoint == '\n')
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 line-height
|
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||||
// TODO: Support custom line spacing defined by user
|
textOffsetY += textLineSpacing;
|
||||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
|
||||||
textOffsetX = 0.0f;
|
textOffsetX = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1143,9 +1180,8 @@ void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 pos
|
||||||
|
|
||||||
if (codepoints[i] == '\n')
|
if (codepoints[i] == '\n')
|
||||||
{
|
{
|
||||||
// NOTE: Fixed line spacing of 1.5 line-height
|
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||||
// TODO: Support custom line spacing defined by user
|
textOffsetY += textLineSpacing;
|
||||||
textOffsetY += (int)((font.baseSize + font.baseSize/2.0f)*scaleFactor);
|
|
||||||
textOffsetX = 0.0f;
|
textOffsetX = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1161,6 +1197,12 @@ void DrawTextCodepoints(Font font, const int *codepoints, int count, Vector2 pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set vertical line spacing when drawing with line-breaks
|
||||||
|
void SetTextLineSpacing(int spacing)
|
||||||
|
{
|
||||||
|
textLineSpacing = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
// Measure string width for default font
|
// Measure string width for default font
|
||||||
int MeasureText(const char *text, int fontSize)
|
int MeasureText(const char *text, int fontSize)
|
||||||
{
|
{
|
||||||
|
|
@ -1219,7 +1261,9 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
byteCounter = 0;
|
byteCounter = 0;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
textHeight += ((float)font.baseSize*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
|
||||||
|
// NOTE: Line spacing is a global variable, use SetTextLineSpacing() to setup
|
||||||
|
textHeight += (float)textLineSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
if (tempByteCounter < byteCounter) tempByteCounter = byteCounter;
|
||||||
|
|
@ -1227,7 +1271,7 @@ Vector2 MeasureTextEx(Font font, const char *text, float fontSize, float spacing
|
||||||
|
|
||||||
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
|
|
||||||
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing); // Adds chars spacing to measure
|
textSize.x = tempTextWidth*scaleFactor + (float)((tempByteCounter - 1)*spacing);
|
||||||
textSize.y = textHeight*scaleFactor;
|
textSize.y = textHeight*scaleFactor;
|
||||||
|
|
||||||
return textSize;
|
return textSize;
|
||||||
|
|
@ -1574,7 +1618,8 @@ int TextFindIndex(const char *text, const char *find)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get upper case version of provided string
|
// Get upper case version of provided string
|
||||||
// REQUIRES: toupper()
|
// WARNING: Limited functionality, only basic characters set
|
||||||
|
// TODO: Support UTF-8 diacritics to upper-case, check codepoints
|
||||||
const char *TextToUpper(const char *text)
|
const char *TextToUpper(const char *text)
|
||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
|
@ -1582,17 +1627,10 @@ const char *TextToUpper(const char *text)
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
|
for (int i = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[i] != '\0'); i++)
|
||||||
{
|
{
|
||||||
if (text[i] != '\0')
|
if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32;
|
||||||
{
|
else buffer[i] = text[i];
|
||||||
buffer[i] = (char)toupper(text[i]);
|
|
||||||
//if ((text[i] >= 'a') && (text[i] <= 'z')) buffer[i] = text[i] - 32;
|
|
||||||
|
|
||||||
// TODO: Support UTF-8 diacritics to upper-case
|
|
||||||
//if ((text[i] >= 'à') && (text[i] <= 'ý')) buffer[i] = text[i] - 32;
|
|
||||||
}
|
|
||||||
else { buffer[i] = '\0'; break; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1600,7 +1638,7 @@ const char *TextToUpper(const char *text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get lower case version of provided string
|
// Get lower case version of provided string
|
||||||
// REQUIRES: tolower()
|
// WARNING: Limited functionality, only basic characters set
|
||||||
const char *TextToLower(const char *text)
|
const char *TextToLower(const char *text)
|
||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
|
@ -1608,14 +1646,10 @@ const char *TextToLower(const char *text)
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
|
for (int i = 0; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[i] != '\0'); i++)
|
||||||
{
|
{
|
||||||
if (text[i] != '\0')
|
if ((text[i] >= 'A') && (text[i] <= 'Z')) buffer[i] = text[i] + 32;
|
||||||
{
|
else buffer[i] = text[i];
|
||||||
buffer[i] = (char)tolower(text[i]);
|
|
||||||
//if ((text[i] >= 'A') && (text[i] <= 'Z')) buffer[i] = text[i] + 32;
|
|
||||||
}
|
|
||||||
else { buffer[i] = '\0'; break; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1623,7 +1657,7 @@ const char *TextToLower(const char *text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Pascal case notation version of provided string
|
// Get Pascal case notation version of provided string
|
||||||
// REQUIRES: toupper()
|
// WARNING: Limited functionality, only basic characters set
|
||||||
const char *TextToPascal(const char *text)
|
const char *TextToPascal(const char *text)
|
||||||
{
|
{
|
||||||
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
static char buffer[MAX_TEXT_BUFFER_LENGTH] = { 0 };
|
||||||
|
|
@ -1631,21 +1665,19 @@ const char *TextToPascal(const char *text)
|
||||||
|
|
||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
buffer[0] = (char)toupper(text[0]);
|
// Upper case first character
|
||||||
|
if ((text[0] >= 'a') && (text[0] <= 'z')) buffer[0] = text[0] - 32;
|
||||||
|
|
||||||
for (int i = 1, j = 1; i < MAX_TEXT_BUFFER_LENGTH; i++, j++)
|
// Check for next separator to upper case another character
|
||||||
{
|
for (int i = 1, j = 1; (i < MAX_TEXT_BUFFER_LENGTH - 1) && (text[j] != '\0'); i++, j++)
|
||||||
if (text[j] != '\0')
|
|
||||||
{
|
{
|
||||||
if (text[j] != '_') buffer[i] = text[j];
|
if (text[j] != '_') buffer[i] = text[j];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
j++;
|
j++;
|
||||||
buffer[i] = (char)toupper(text[j]);
|
if ((text[j] >= 'a') && (text[j] <= 'z')) buffer[i] = text[j] - 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { buffer[i] = '\0'; break; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
|
|
|
||||||
|
|
@ -3290,8 +3290,7 @@ void ImageDrawText(Image *dst, const char *text, int posX, int posY, int fontSiz
|
||||||
if (GetFontDefault().texture.id == 0) LoadFontDefault();
|
if (GetFontDefault().texture.id == 0) LoadFontDefault();
|
||||||
|
|
||||||
Vector2 position = { (float)posX, (float)posY };
|
Vector2 position = { (float)posX, (float)posY };
|
||||||
// NOTE: For default font, spacing is set to desired font size / default font size (10)
|
ImageDrawTextEx(dst, GetFontDefault(), text, position, (float)fontSize, 1.0f, color); // WARNING: Module required: rtext
|
||||||
ImageDrawTextEx(dst, GetFontDefault(), text, position, (float)fontSize, (float)fontSize/10, color); // WARNING: Module required: rtext
|
|
||||||
#else
|
#else
|
||||||
TRACELOG(LOG_WARNING, "IMAGE: ImageDrawText() requires module: rtext");
|
TRACELOG(LOG_WARNING, "IMAGE: ImageDrawText() requires module: rtext");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user