Bundle raylib C sources and switch to develop branch
This commit is contained in:
parent
e2f3bed444
commit
f89d1164a5
36 changed files with 54932 additions and 193 deletions
|
@ -6,7 +6,6 @@ Golang bindings for [raylib](http://www.raylib.com/), a simple and easy-to-use l
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
* [raylib](http://www.raylib.com/)
|
|
||||||
* [GLFW3](http://www.glfw.org/) (desktop platform only, not needed on Android and RPi)
|
* [GLFW3](http://www.glfw.org/) (desktop platform only, not needed on Android and RPi)
|
||||||
* [OpenAL Soft](http://kcat.strangesoft.net/openal.html)
|
* [OpenAL Soft](http://kcat.strangesoft.net/openal.html)
|
||||||
|
|
||||||
|
|
1230
raylib/audio.c
Normal file
1230
raylib/audio.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -122,13 +122,12 @@ func LoadWave(fileName string) Wave {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load wave data from float array data (32bit)
|
// Load wave data from float array data (32bit)
|
||||||
func LoadWaveEx(data []float32, sampleCount int32, sampleRate int32, sampleSize int32, channels int32) Wave {
|
func LoadWaveEx(data unsafe.Pointer, sampleCount int32, sampleRate int32, sampleSize int32, channels int32) Wave {
|
||||||
cdata := (*C.float)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&data)).Data))
|
|
||||||
csampleCount := (C.int)(sampleCount)
|
csampleCount := (C.int)(sampleCount)
|
||||||
csampleRate := (C.int)(sampleRate)
|
csampleRate := (C.int)(sampleRate)
|
||||||
csampleSize := (C.int)(sampleSize)
|
csampleSize := (C.int)(sampleSize)
|
||||||
cchannels := (C.int)(channels)
|
cchannels := (C.int)(channels)
|
||||||
ret := C.LoadWaveEx(cdata, csampleCount, csampleRate, csampleSize, cchannels)
|
ret := C.LoadWaveEx(data, csampleCount, csampleRate, csampleSize, cchannels)
|
||||||
v := NewWaveFromPointer(unsafe.Pointer(&ret))
|
v := NewWaveFromPointer(unsafe.Pointer(&ret))
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
@ -150,16 +149,6 @@ func LoadSoundFromWave(wave Wave) Sound {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load sound to memory from rRES file (raylib Resource)
|
|
||||||
func LoadSoundFromRES(rresName string, resId int32) Sound {
|
|
||||||
crresName := C.CString(rresName)
|
|
||||||
defer C.free(unsafe.Pointer(crresName))
|
|
||||||
cresId := (C.int)(resId)
|
|
||||||
ret := C.LoadSoundFromRES(crresName, cresId)
|
|
||||||
v := NewSoundFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sound buffer with new data
|
// Update sound buffer with new data
|
||||||
func UpdateSound(sound Sound, data unsafe.Pointer, numSamples int32) {
|
func UpdateSound(sound Sound, data unsafe.Pointer, numSamples int32) {
|
||||||
csound := sound.cptr()
|
csound := sound.cptr()
|
||||||
|
|
159
raylib/audio.h
Normal file
159
raylib/audio.h
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib.audio
|
||||||
|
*
|
||||||
|
* This module provides basic functionality to work with audio:
|
||||||
|
* Manage audio device (init/close)
|
||||||
|
* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD)
|
||||||
|
* Play/Stop/Pause/Resume loaded audio
|
||||||
|
* Manage mixing channels
|
||||||
|
* Manage raw audio context
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html)
|
||||||
|
* stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/)
|
||||||
|
* jar_xm - XM module file loading
|
||||||
|
* jar_mod - MOD audio file loading
|
||||||
|
* dr_flac - FLAC audio file loading
|
||||||
|
*
|
||||||
|
* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions:
|
||||||
|
* XM audio module support (jar_xm)
|
||||||
|
* MOD audio module support (jar_mod)
|
||||||
|
* Mixing channels support
|
||||||
|
* Raw audio context support
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef AUDIO_H
|
||||||
|
#define AUDIO_H
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
// NOTE: Below types are required for CAMERA_STANDALONE usage
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// Boolean type
|
||||||
|
#if !defined(_STDBOOL_H)
|
||||||
|
typedef enum { false, true } bool;
|
||||||
|
#define _STDBOOL_H
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Wave type, defines audio wave data
|
||||||
|
typedef struct Wave {
|
||||||
|
unsigned int sampleCount; // Number of samples
|
||||||
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
|
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
||||||
|
void *data; // Buffer data pointer
|
||||||
|
} Wave;
|
||||||
|
|
||||||
|
// Sound source type
|
||||||
|
typedef struct Sound {
|
||||||
|
unsigned int source; // OpenAL audio source id
|
||||||
|
unsigned int buffer; // OpenAL audio buffer id
|
||||||
|
int format; // OpenAL audio format specifier
|
||||||
|
} Sound;
|
||||||
|
|
||||||
|
// Music type (file streaming from memory)
|
||||||
|
// NOTE: Anything longer than ~10 seconds should be streamed
|
||||||
|
typedef struct MusicData *Music;
|
||||||
|
|
||||||
|
// Audio stream type
|
||||||
|
// NOTE: Useful to create custom audio streams not bound to a specific file
|
||||||
|
typedef struct AudioStream {
|
||||||
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
|
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
||||||
|
|
||||||
|
int format; // OpenAL audio format specifier
|
||||||
|
unsigned int source; // OpenAL audio source id
|
||||||
|
unsigned int buffers[2]; // OpenAL audio buffers (double buffering)
|
||||||
|
} AudioStream;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
void InitAudioDevice(void); // Initialize audio device and context
|
||||||
|
void CloseAudioDevice(void); // Close the audio device and context
|
||||||
|
bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
||||||
|
|
||||||
|
Wave LoadWave(const char *fileName); // Load wave data from file
|
||||||
|
Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from raw array data
|
||||||
|
Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
|
Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
|
void UpdateSound(Sound sound, const void *data, int numSamples);// Update sound buffer with new data
|
||||||
|
void UnloadWave(Wave wave); // Unload wave data
|
||||||
|
void UnloadSound(Sound sound); // Unload sound
|
||||||
|
void PlaySound(Sound sound); // Play a sound
|
||||||
|
void PauseSound(Sound sound); // Pause a sound
|
||||||
|
void ResumeSound(Sound sound); // Resume a paused sound
|
||||||
|
void StopSound(Sound sound); // Stop playing a sound
|
||||||
|
bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
||||||
|
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
||||||
|
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||||
|
void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
|
||||||
|
Wave WaveCopy(Wave wave); // Copy a wave to a new wave
|
||||||
|
void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range
|
||||||
|
float *GetWaveData(Wave wave); // Get samples data from wave as a floats array
|
||||||
|
Music LoadMusicStream(const char *fileName); // Load music stream from file
|
||||||
|
void UnloadMusicStream(Music music); // Unload music stream
|
||||||
|
void PlayMusicStream(Music music); // Start music playing
|
||||||
|
void UpdateMusicStream(Music music); // Updates buffers for music streaming
|
||||||
|
void StopMusicStream(Music music); // Stop music playing
|
||||||
|
void PauseMusicStream(Music music); // Pause music playing
|
||||||
|
void ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
|
bool IsMusicPlaying(Music music); // Check if music is playing
|
||||||
|
void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
|
void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||||
|
float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
|
float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||||
|
|
||||||
|
AudioStream InitAudioStream(unsigned int sampleRate,
|
||||||
|
unsigned int sampleSize,
|
||||||
|
unsigned int channels); // Init audio stream (to stream raw audio pcm data)
|
||||||
|
void UpdateAudioStream(AudioStream stream, void *data, int numSamples); // Update audio stream buffers with data
|
||||||
|
void CloseAudioStream(AudioStream stream); // Close audio stream and free memory
|
||||||
|
bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
||||||
|
void PlayAudioStream(AudioStream stream); // Play audio stream
|
||||||
|
void PauseAudioStream(AudioStream stream); // Pause audio stream
|
||||||
|
void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
||||||
|
void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // AUDIO_H
|
505
raylib/camera.h
Normal file
505
raylib/camera.h
Normal file
|
@ -0,0 +1,505 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib Camera System - Camera Modes Setup and Control Functions
|
||||||
|
*
|
||||||
|
* #define CAMERA_IMPLEMENTATION
|
||||||
|
* 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
|
||||||
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
|
*
|
||||||
|
* #define CAMERA_STANDALONE
|
||||||
|
* If defined, the library can be used as standalone as a camera system but some
|
||||||
|
* functions must be redefined to manage inputs accordingly.
|
||||||
|
*
|
||||||
|
* NOTE: Memory footprint of this library is aproximately 52 bytes (global variables)
|
||||||
|
*
|
||||||
|
* Initial design by Marc Palau (2014)
|
||||||
|
* Reviewed by Ramon Santamaria (2015-2016)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef CAMERA_H
|
||||||
|
#define CAMERA_H
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
// NOTE: Below types are required for CAMERA_STANDALONE usage
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(CAMERA_STANDALONE)
|
||||||
|
// Camera modes
|
||||||
|
typedef enum {
|
||||||
|
CAMERA_CUSTOM = 0,
|
||||||
|
CAMERA_FREE,
|
||||||
|
CAMERA_ORBITAL,
|
||||||
|
CAMERA_FIRST_PERSON,
|
||||||
|
CAMERA_THIRD_PERSON
|
||||||
|
} CameraMode;
|
||||||
|
|
||||||
|
// Vector2 type
|
||||||
|
typedef struct Vector2 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} Vector2;
|
||||||
|
|
||||||
|
// Vector3 type
|
||||||
|
typedef struct Vector3 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} Vector3;
|
||||||
|
|
||||||
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
|
typedef struct Camera {
|
||||||
|
Vector3 position;
|
||||||
|
Vector3 target;
|
||||||
|
Vector3 up;
|
||||||
|
float fovy;
|
||||||
|
} Camera;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(CAMERA_STANDALONE)
|
||||||
|
void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
||||||
|
void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
||||||
|
|
||||||
|
void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera)
|
||||||
|
void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera)
|
||||||
|
void SetCameraSmoothZoomControl(int szKey); // Set camera smooth zoom key to combine with mouse (free camera)
|
||||||
|
void SetCameraMoveControls(int frontKey, int backKey,
|
||||||
|
int rightKey, int leftKey,
|
||||||
|
int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CAMERA_H
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************
|
||||||
|
*
|
||||||
|
* CAMERA IMPLEMENTATION
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#if defined(CAMERA_IMPLEMENTATION)
|
||||||
|
|
||||||
|
#include <math.h> // Required for: sqrt(), sin(), cos()
|
||||||
|
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEG2RAD
|
||||||
|
#define DEG2RAD (PI/180.0f)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RAD2DEG
|
||||||
|
#define RAD2DEG (180.0f/PI)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Camera mouse movement sensitivity
|
||||||
|
#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f
|
||||||
|
#define CAMERA_MOUSE_SCROLL_SENSITIVITY 1.5f
|
||||||
|
|
||||||
|
// FREE_CAMERA
|
||||||
|
#define CAMERA_FREE_MOUSE_SENSITIVITY 0.01f
|
||||||
|
#define CAMERA_FREE_DISTANCE_MIN_CLAMP 0.3f
|
||||||
|
#define CAMERA_FREE_DISTANCE_MAX_CLAMP 120.0f
|
||||||
|
#define CAMERA_FREE_MIN_CLAMP 85.0f
|
||||||
|
#define CAMERA_FREE_MAX_CLAMP -85.0f
|
||||||
|
#define CAMERA_FREE_SMOOTH_ZOOM_SENSITIVITY 0.05f
|
||||||
|
#define CAMERA_FREE_PANNING_DIVIDER 5.1f
|
||||||
|
|
||||||
|
// ORBITAL_CAMERA
|
||||||
|
#define CAMERA_ORBITAL_SPEED 0.01f // Radians per frame
|
||||||
|
|
||||||
|
// FIRST_PERSON
|
||||||
|
//#define CAMERA_FIRST_PERSON_MOUSE_SENSITIVITY 0.003f
|
||||||
|
#define CAMERA_FIRST_PERSON_FOCUS_DISTANCE 25.0f
|
||||||
|
#define CAMERA_FIRST_PERSON_MIN_CLAMP 85.0f
|
||||||
|
#define CAMERA_FIRST_PERSON_MAX_CLAMP -85.0f
|
||||||
|
|
||||||
|
#define CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0f
|
||||||
|
#define CAMERA_FIRST_PERSON_STEP_DIVIDER 30.0f
|
||||||
|
#define CAMERA_FIRST_PERSON_WAVING_DIVIDER 200.0f
|
||||||
|
|
||||||
|
// THIRD_PERSON
|
||||||
|
//#define CAMERA_THIRD_PERSON_MOUSE_SENSITIVITY 0.003f
|
||||||
|
#define CAMERA_THIRD_PERSON_DISTANCE_CLAMP 1.2f
|
||||||
|
#define CAMERA_THIRD_PERSON_MIN_CLAMP 5.0f
|
||||||
|
#define CAMERA_THIRD_PERSON_MAX_CLAMP -85.0f
|
||||||
|
#define CAMERA_THIRD_PERSON_OFFSET (Vector3){ 0.4f, 0.0f, 0.0f }
|
||||||
|
|
||||||
|
// PLAYER (used by camera)
|
||||||
|
#define PLAYER_MOVEMENT_SENSITIVITY 20.0f
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Camera move modes (first person and third person cameras)
|
||||||
|
typedef enum { MOVE_FRONT = 0, MOVE_BACK, MOVE_RIGHT, MOVE_LEFT, MOVE_UP, MOVE_DOWN } CameraMove;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static Vector2 cameraAngle = { 0.0f, 0.0f }; // TODO: Remove! Compute it in UpdateCamera()
|
||||||
|
static float cameraTargetDistance = 0.0f; // TODO: Remove! Compute it in UpdateCamera()
|
||||||
|
static float playerEyesPosition = 1.85f; // Default player eyes position from ground (in meters)
|
||||||
|
|
||||||
|
static int cameraMoveControl[6] = { 'W', 'S', 'D', 'A', 'E', 'Q' };
|
||||||
|
static int cameraPanControlKey = 2; // raylib: MOUSE_MIDDLE_BUTTON
|
||||||
|
static int cameraAltControlKey = 342; // raylib: KEY_LEFT_ALT
|
||||||
|
static int cameraSmoothZoomControlKey = 341; // raylib: KEY_LEFT_CONTROL
|
||||||
|
|
||||||
|
static int cameraMode = CAMERA_CUSTOM; // Current camera mode
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(CAMERA_STANDALONE)
|
||||||
|
// NOTE: Camera controls depend on some raylib input functions
|
||||||
|
// TODO: Set your own input functions (used in UpdateCamera())
|
||||||
|
static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; }
|
||||||
|
static void SetMousePosition(Vector2 pos) {}
|
||||||
|
static int IsMouseButtonDown(int button) { return 0;}
|
||||||
|
static int GetMouseWheelMove() { return 0; }
|
||||||
|
static int GetScreenWidth() { return 1280; }
|
||||||
|
static int GetScreenHeight() { return 720; }
|
||||||
|
static void ShowCursor() {}
|
||||||
|
static void HideCursor() {}
|
||||||
|
static int IsKeyDown(int key) { return 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Select camera mode (multiple camera modes available)
|
||||||
|
void SetCameraMode(Camera camera, int mode)
|
||||||
|
{
|
||||||
|
// TODO: cameraTargetDistance and cameraAngle should be
|
||||||
|
// calculated using camera parameters on UpdateCamera()
|
||||||
|
|
||||||
|
Vector3 v1 = camera.position;
|
||||||
|
Vector3 v2 = camera.target;
|
||||||
|
|
||||||
|
float dx = v2.x - v1.x;
|
||||||
|
float dy = v2.y - v1.y;
|
||||||
|
float dz = v2.z - v1.z;
|
||||||
|
|
||||||
|
cameraTargetDistance = sqrtf(dx*dx + dy*dy + dz*dz);
|
||||||
|
|
||||||
|
Vector2 distance = { 0.0f, 0.0f };
|
||||||
|
distance.x = sqrtf(dx*dx + dz*dz);
|
||||||
|
distance.y = sqrtf(dx*dx + dy*dy);
|
||||||
|
|
||||||
|
// Camera angle calculation
|
||||||
|
cameraAngle.x = asinf(fabsf(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||||
|
cameraAngle.y = -asinf(fabsf(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW)
|
||||||
|
|
||||||
|
// NOTE: Just testing what cameraAngle means
|
||||||
|
//cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW)
|
||||||
|
//cameraAngle.y = -60.0f*DEG2RAD; // Camera angle in plane XY (0 aligned with X, move positive CW)
|
||||||
|
|
||||||
|
playerEyesPosition = camera.position.y;
|
||||||
|
|
||||||
|
cameraMode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update camera depending on selected mode
|
||||||
|
// NOTE: Camera controls depend on some raylib functions:
|
||||||
|
// Mouse: GetMousePosition(), SetMousePosition(), IsMouseButtonDown(), GetMouseWheelMove()
|
||||||
|
// System: GetScreenWidth(), GetScreenHeight(), ShowCursor(), HideCursor()
|
||||||
|
// Keys: IsKeyDown()
|
||||||
|
// TODO: Port to quaternion-based camera
|
||||||
|
void UpdateCamera(Camera *camera)
|
||||||
|
{
|
||||||
|
static int swingCounter = 0; // Used for 1st person swinging movement
|
||||||
|
static Vector2 previousMousePosition = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
// TODO: Compute cameraTargetDistance and cameraAngle here
|
||||||
|
|
||||||
|
// Mouse movement detection
|
||||||
|
Vector2 mousePositionDelta = { 0.0f, 0.0f };
|
||||||
|
Vector2 mousePosition = GetMousePosition();
|
||||||
|
int mouseWheelMove = GetMouseWheelMove();
|
||||||
|
|
||||||
|
// Keys input detection
|
||||||
|
bool panKey = IsMouseButtonDown(cameraPanControlKey);
|
||||||
|
bool altKey = IsKeyDown(cameraAltControlKey);
|
||||||
|
bool szoomKey = IsKeyDown(cameraSmoothZoomControlKey);
|
||||||
|
|
||||||
|
bool direction[6] = { IsKeyDown(cameraMoveControl[MOVE_FRONT]),
|
||||||
|
IsKeyDown(cameraMoveControl[MOVE_BACK]),
|
||||||
|
IsKeyDown(cameraMoveControl[MOVE_RIGHT]),
|
||||||
|
IsKeyDown(cameraMoveControl[MOVE_LEFT]),
|
||||||
|
IsKeyDown(cameraMoveControl[MOVE_UP]),
|
||||||
|
IsKeyDown(cameraMoveControl[MOVE_DOWN]) };
|
||||||
|
|
||||||
|
// TODO: Consider touch inputs for camera
|
||||||
|
|
||||||
|
if (cameraMode != CAMERA_CUSTOM)
|
||||||
|
{
|
||||||
|
// Get screen size
|
||||||
|
int screenWidth = GetScreenWidth();
|
||||||
|
int screenHeight = GetScreenHeight();
|
||||||
|
|
||||||
|
if ((cameraMode == CAMERA_FIRST_PERSON) ||
|
||||||
|
(cameraMode == CAMERA_THIRD_PERSON))
|
||||||
|
{
|
||||||
|
HideCursor();
|
||||||
|
|
||||||
|
if (mousePosition.x < (float)screenHeight/3.0f) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y });
|
||||||
|
else if (mousePosition.y < (float)screenHeight/3.0f) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3 });
|
||||||
|
else if (mousePosition.x > (screenWidth - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ screenHeight/3, mousePosition.y });
|
||||||
|
else if (mousePosition.y > (screenHeight - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3 });
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
|
||||||
|
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // CAMERA_FREE, CAMERA_ORBITAL
|
||||||
|
{
|
||||||
|
ShowCursor();
|
||||||
|
|
||||||
|
mousePositionDelta.x = mousePosition.x - previousMousePosition.x;
|
||||||
|
mousePositionDelta.y = mousePosition.y - previousMousePosition.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: We GetMousePosition() again because it can be modified by a previous SetMousePosition() call
|
||||||
|
// If using directly mousePosition variable we have problems on CAMERA_FIRST_PERSON and CAMERA_THIRD_PERSON
|
||||||
|
previousMousePosition = GetMousePosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Support for multiple automatic camera modes
|
||||||
|
switch (cameraMode)
|
||||||
|
{
|
||||||
|
case CAMERA_FREE:
|
||||||
|
{
|
||||||
|
// Camera zoom
|
||||||
|
if ((cameraTargetDistance < CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
|
||||||
|
{
|
||||||
|
cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
|
||||||
|
|
||||||
|
if (cameraTargetDistance > CAMERA_FREE_DISTANCE_MAX_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MAX_CLAMP;
|
||||||
|
}
|
||||||
|
// Camera looking down
|
||||||
|
// TODO: Review, weird comparisson of cameraTargetDistance == 120.0f?
|
||||||
|
else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
|
||||||
|
{
|
||||||
|
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
}
|
||||||
|
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
|
||||||
|
{
|
||||||
|
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
|
||||||
|
// if (camera->target.y < 0) camera->target.y = -0.001;
|
||||||
|
}
|
||||||
|
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (mouseWheelMove > 0))
|
||||||
|
{
|
||||||
|
cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
|
||||||
|
if (cameraTargetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP;
|
||||||
|
}
|
||||||
|
// Camera looking up
|
||||||
|
// TODO: Review, weird comparisson of cameraTargetDistance == 120.0f?
|
||||||
|
else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
|
||||||
|
{
|
||||||
|
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
}
|
||||||
|
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
|
||||||
|
{
|
||||||
|
camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance;
|
||||||
|
|
||||||
|
// if (camera->target.y > 0) camera->target.y = 0.001;
|
||||||
|
}
|
||||||
|
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (mouseWheelMove > 0))
|
||||||
|
{
|
||||||
|
cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
|
||||||
|
if (cameraTargetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input keys checks
|
||||||
|
if (panKey)
|
||||||
|
{
|
||||||
|
if (altKey) // Alternative key behaviour
|
||||||
|
{
|
||||||
|
if (szoomKey)
|
||||||
|
{
|
||||||
|
// Camera smooth zoom
|
||||||
|
cameraTargetDistance += (mousePositionDelta.y*CAMERA_FREE_SMOOTH_ZOOM_SENSITIVITY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Camera rotation
|
||||||
|
cameraAngle.x += mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY;
|
||||||
|
cameraAngle.y += mousePositionDelta.y*-CAMERA_FREE_MOUSE_SENSITIVITY;
|
||||||
|
|
||||||
|
// Angle clamp
|
||||||
|
if (cameraAngle.y > CAMERA_FREE_MIN_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FREE_MIN_CLAMP*DEG2RAD;
|
||||||
|
else if (cameraAngle.y < CAMERA_FREE_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FREE_MAX_CLAMP*DEG2RAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Camera panning
|
||||||
|
camera->target.x += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(cameraAngle.x)*sinf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||||
|
camera->target.y += ((mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||||
|
camera->target.z += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.x)*sinf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case CAMERA_ORBITAL:
|
||||||
|
{
|
||||||
|
cameraAngle.x += CAMERA_ORBITAL_SPEED; // Camera orbit angle
|
||||||
|
cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY); // Camera zoom
|
||||||
|
|
||||||
|
// Camera distance clamp
|
||||||
|
if (cameraTargetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case CAMERA_FIRST_PERSON:
|
||||||
|
case CAMERA_THIRD_PERSON:
|
||||||
|
{
|
||||||
|
camera->position.x += (sinf(cameraAngle.x)*direction[MOVE_BACK] -
|
||||||
|
sinf(cameraAngle.x)*direction[MOVE_FRONT] -
|
||||||
|
cosf(cameraAngle.x)*direction[MOVE_LEFT] +
|
||||||
|
cosf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||||
|
|
||||||
|
camera->position.y += (sinf(cameraAngle.y)*direction[MOVE_FRONT] -
|
||||||
|
sinf(cameraAngle.y)*direction[MOVE_BACK] +
|
||||||
|
1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||||
|
|
||||||
|
camera->position.z += (cosf(cameraAngle.x)*direction[MOVE_BACK] -
|
||||||
|
cosf(cameraAngle.x)*direction[MOVE_FRONT] +
|
||||||
|
sinf(cameraAngle.x)*direction[MOVE_LEFT] -
|
||||||
|
sinf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY;
|
||||||
|
|
||||||
|
bool isMoving = false; // Required for swinging
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) if (direction[i]) { isMoving = true; break; }
|
||||||
|
|
||||||
|
// Camera orientation calculation
|
||||||
|
cameraAngle.x += (mousePositionDelta.x*-CAMERA_MOUSE_MOVE_SENSITIVITY);
|
||||||
|
cameraAngle.y += (mousePositionDelta.y*-CAMERA_MOUSE_MOVE_SENSITIVITY);
|
||||||
|
|
||||||
|
if (cameraMode == CAMERA_THIRD_PERSON)
|
||||||
|
{
|
||||||
|
// Angle clamp
|
||||||
|
if (cameraAngle.y > CAMERA_THIRD_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_THIRD_PERSON_MIN_CLAMP*DEG2RAD;
|
||||||
|
else if (cameraAngle.y < CAMERA_THIRD_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_THIRD_PERSON_MAX_CLAMP*DEG2RAD;
|
||||||
|
|
||||||
|
// Camera zoom
|
||||||
|
cameraTargetDistance -= (mouseWheelMove*CAMERA_MOUSE_SCROLL_SENSITIVITY);
|
||||||
|
|
||||||
|
// Camera distance clamp
|
||||||
|
if (cameraTargetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP;
|
||||||
|
|
||||||
|
// Camera is always looking at player
|
||||||
|
camera->target.x = camera->position.x + CAMERA_THIRD_PERSON_OFFSET.x*cosf(cameraAngle.x) + CAMERA_THIRD_PERSON_OFFSET.z*sinf(cameraAngle.x);
|
||||||
|
camera->target.y = camera->position.y + CAMERA_THIRD_PERSON_OFFSET.y;
|
||||||
|
camera->target.z = camera->position.z + CAMERA_THIRD_PERSON_OFFSET.z*sinf(cameraAngle.x) - CAMERA_THIRD_PERSON_OFFSET.x*sinf(cameraAngle.x);
|
||||||
|
}
|
||||||
|
else // CAMERA_FIRST_PERSON
|
||||||
|
{
|
||||||
|
// Angle clamp
|
||||||
|
if (cameraAngle.y > CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FIRST_PERSON_MIN_CLAMP*DEG2RAD;
|
||||||
|
else if (cameraAngle.y < CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD;
|
||||||
|
|
||||||
|
// Camera is always looking at player
|
||||||
|
camera->target.x = camera->position.x - sinf(cameraAngle.x)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE;
|
||||||
|
camera->target.y = camera->position.y + sinf(cameraAngle.y)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE;
|
||||||
|
camera->target.z = camera->position.z - cosf(cameraAngle.x)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE;
|
||||||
|
|
||||||
|
if (isMoving) swingCounter++;
|
||||||
|
|
||||||
|
// Camera position update
|
||||||
|
// NOTE: On CAMERA_FIRST_PERSON player Y-movement is limited to player 'eyes position'
|
||||||
|
camera->position.y = playerEyesPosition - sinf(swingCounter/CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/CAMERA_FIRST_PERSON_STEP_DIVIDER;
|
||||||
|
|
||||||
|
camera->up.x = sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER;
|
||||||
|
camera->up.z = -sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update camera position with changes
|
||||||
|
if ((cameraMode == CAMERA_FREE) ||
|
||||||
|
(cameraMode == CAMERA_ORBITAL) ||
|
||||||
|
(cameraMode == CAMERA_THIRD_PERSON))
|
||||||
|
{
|
||||||
|
// TODO: It seems camera->position is not correctly updated or some rounding issue makes the camera move straight to camera->target...
|
||||||
|
camera->position.x = sinf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.x;
|
||||||
|
if (cameraAngle.y <= 0.0f) camera->position.y = sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y;
|
||||||
|
else camera->position.y = -sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y;
|
||||||
|
camera->position.z = cosf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set camera pan key to combine with mouse movement (free camera)
|
||||||
|
void SetCameraPanControl(int panKey) { cameraPanControlKey = panKey; }
|
||||||
|
|
||||||
|
// Set camera alt key to combine with mouse movement (free camera)
|
||||||
|
void SetCameraAltControl(int altKey) { cameraAltControlKey = altKey; }
|
||||||
|
|
||||||
|
// Set camera smooth zoom key to combine with mouse (free camera)
|
||||||
|
void SetCameraSmoothZoomControl(int szKey) { cameraSmoothZoomControlKey = szKey; }
|
||||||
|
|
||||||
|
// Set camera move controls (1st person and 3rd person cameras)
|
||||||
|
void SetCameraMoveControls(int frontKey, int backKey, int rightKey, int leftKey, int upKey, int downKey)
|
||||||
|
{
|
||||||
|
cameraMoveControl[MOVE_FRONT] = frontKey;
|
||||||
|
cameraMoveControl[MOVE_BACK] = backKey;
|
||||||
|
cameraMoveControl[MOVE_RIGHT] = rightKey;
|
||||||
|
cameraMoveControl[MOVE_LEFT] = leftKey;
|
||||||
|
cameraMoveControl[MOVE_UP] = upKey;
|
||||||
|
cameraMoveControl[MOVE_DOWN] = downKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CAMERA_IMPLEMENTATION
|
|
@ -1,14 +1,15 @@
|
||||||
package raylib
|
package raylib
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux,!arm LDFLAGS: -lraylib -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
|
#cgo linux,!arm LDFLAGS: -lglfw3 -lGL -lopenal -lm -pthread -ldl -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor
|
||||||
#cgo linux,arm,!android LDFLAGS: -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lvcos -lvchiq_arm -lopenal
|
#cgo linux,arm,!android LDFLAGS: -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lvcos -lvchiq_arm -lopenal
|
||||||
#cgo windows LDFLAGS: -lraylib -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm
|
#cgo windows LDFLAGS: -lglfw3 -lopengl32 -lgdi32 -lopenal32 -lwinmm
|
||||||
#cgo darwin LDFLAGS: -lraylib -lglfw3 -framework OpenGL -framework OpenAl -framework Cocoa
|
#cgo darwin LDFLAGS: -lglfw3 -framework OpenGL -framework OpenAl -framework Cocoa
|
||||||
#cgo android LDFLAGS: -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lopenal -lm -landroid_native_app_glue
|
#cgo android LDFLAGS: -llog -landroid -lEGL -lGLESv2 -lOpenSLES -lopenal -lm -landroid_native_app_glue
|
||||||
|
|
||||||
#cgo linux,windows,darwin,!android,!arm CFLAGS: -DPLATFORM_DESKTOP
|
#cgo CFLAGS: -std=gnu99 -fgnu89-inline -Wno-missing-braces -Wno-unused-result
|
||||||
#cgo linux,arm,!android CFLAGS: -DPLATFORM_RPI
|
#cgo linux,windows,darwin,!android,!arm CFLAGS: -DPLATFORM_DESKTOP -DGRAPHICS_API_OPENGL_33
|
||||||
#cgo android CFLAGS: -DPLATFORM_ANDROID
|
#cgo linux,arm,!android CFLAGS: -DPLATFORM_RPI -DGRAPHICS_API_OPENGL_ES2
|
||||||
|
#cgo android CFLAGS: -DPLATFORM_ANDROID -DGRAPHICS_API_OPENGL_ES2
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
3222
raylib/core.c
Normal file
3222
raylib/core.c
Normal file
File diff suppressed because it is too large
Load diff
4564
raylib/external/dr_flac.h
vendored
Normal file
4564
raylib/external/dr_flac.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
5441
raylib/external/glad.h
vendored
Normal file
5441
raylib/external/glad.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1595
raylib/external/jar_mod.h
vendored
Normal file
1595
raylib/external/jar_mod.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
2664
raylib/external/jar_xm.h
vendored
Normal file
2664
raylib/external/jar_xm.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
7110
raylib/external/stb_image.h
vendored
Normal file
7110
raylib/external/stb_image.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
2580
raylib/external/stb_image_resize.h
vendored
Normal file
2580
raylib/external/stb_image_resize.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
1049
raylib/external/stb_image_write.h
vendored
Normal file
1049
raylib/external/stb_image_write.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
583
raylib/external/stb_rect_pack.h
vendored
Normal file
583
raylib/external/stb_rect_pack.h
vendored
Normal file
|
@ -0,0 +1,583 @@
|
||||||
|
// stb_rect_pack.h - v0.10 - public domain - rectangle packing
|
||||||
|
// Sean Barrett 2014
|
||||||
|
//
|
||||||
|
// Useful for e.g. packing rectangular textures into an atlas.
|
||||||
|
// Does not do rotation.
|
||||||
|
//
|
||||||
|
// Not necessarily the awesomest packing method, but better than
|
||||||
|
// the totally naive one in stb_truetype (which is primarily what
|
||||||
|
// this is meant to replace).
|
||||||
|
//
|
||||||
|
// Has only had a few tests run, may have issues.
|
||||||
|
//
|
||||||
|
// More docs to come.
|
||||||
|
//
|
||||||
|
// No memory allocations; uses qsort() and assert() from stdlib.
|
||||||
|
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
|
||||||
|
//
|
||||||
|
// This library currently uses the Skyline Bottom-Left algorithm.
|
||||||
|
//
|
||||||
|
// Please note: better rectangle packers are welcome! Please
|
||||||
|
// implement them to the same API, but with a different init
|
||||||
|
// function.
|
||||||
|
//
|
||||||
|
// Credits
|
||||||
|
//
|
||||||
|
// Library
|
||||||
|
// Sean Barrett
|
||||||
|
// Minor features
|
||||||
|
// Martins Mozeiko
|
||||||
|
// Bugfixes / warning fixes
|
||||||
|
// Jeremy Jaussaud
|
||||||
|
//
|
||||||
|
// Version history:
|
||||||
|
//
|
||||||
|
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||||
|
// 0.09 (2016-08-27) fix compiler warnings
|
||||||
|
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
|
||||||
|
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
|
||||||
|
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
|
||||||
|
// 0.05: added STBRP_ASSERT to allow replacing assert
|
||||||
|
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
|
||||||
|
// 0.01: initial release
|
||||||
|
//
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// This software is dual-licensed to the public domain and under the following
|
||||||
|
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||||
|
// publish, and distribute this file as you see fit.
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// INCLUDE SECTION
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STB_INCLUDE_STB_RECT_PACK_H
|
||||||
|
#define STB_INCLUDE_STB_RECT_PACK_H
|
||||||
|
|
||||||
|
#define STB_RECT_PACK_VERSION 1
|
||||||
|
|
||||||
|
#ifdef STBRP_STATIC
|
||||||
|
#define STBRP_DEF static
|
||||||
|
#else
|
||||||
|
#define STBRP_DEF extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct stbrp_context stbrp_context;
|
||||||
|
typedef struct stbrp_node stbrp_node;
|
||||||
|
typedef struct stbrp_rect stbrp_rect;
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
typedef int stbrp_coord;
|
||||||
|
#else
|
||||||
|
typedef unsigned short stbrp_coord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
|
||||||
|
// Assign packed locations to rectangles. The rectangles are of type
|
||||||
|
// 'stbrp_rect' defined below, stored in the array 'rects', and there
|
||||||
|
// are 'num_rects' many of them.
|
||||||
|
//
|
||||||
|
// Rectangles which are successfully packed have the 'was_packed' flag
|
||||||
|
// set to a non-zero value and 'x' and 'y' store the minimum location
|
||||||
|
// on each axis (i.e. bottom-left in cartesian coordinates, top-left
|
||||||
|
// if you imagine y increasing downwards). Rectangles which do not fit
|
||||||
|
// have the 'was_packed' flag set to 0.
|
||||||
|
//
|
||||||
|
// You should not try to access the 'rects' array from another thread
|
||||||
|
// while this function is running, as the function temporarily reorders
|
||||||
|
// the array while it executes.
|
||||||
|
//
|
||||||
|
// To pack into another rectangle, you need to call stbrp_init_target
|
||||||
|
// again. To continue packing into the same rectangle, you can call
|
||||||
|
// this function again. Calling this multiple times with multiple rect
|
||||||
|
// arrays will probably produce worse packing results than calling it
|
||||||
|
// a single time with the full rectangle array, but the option is
|
||||||
|
// available.
|
||||||
|
|
||||||
|
struct stbrp_rect
|
||||||
|
{
|
||||||
|
// reserved for your use:
|
||||||
|
int id;
|
||||||
|
|
||||||
|
// input:
|
||||||
|
stbrp_coord w, h;
|
||||||
|
|
||||||
|
// output:
|
||||||
|
stbrp_coord x, y;
|
||||||
|
int was_packed; // non-zero if valid packing
|
||||||
|
|
||||||
|
}; // 16 bytes, nominally
|
||||||
|
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes);
|
||||||
|
// Initialize a rectangle packer to:
|
||||||
|
// pack a rectangle that is 'width' by 'height' in dimensions
|
||||||
|
// using temporary storage provided by the array 'nodes', which is 'num_nodes' long
|
||||||
|
//
|
||||||
|
// You must call this function every time you start packing into a new target.
|
||||||
|
//
|
||||||
|
// There is no "shutdown" function. The 'nodes' memory must stay valid for
|
||||||
|
// the following stbrp_pack_rects() call (or calls), but can be freed after
|
||||||
|
// the call (or calls) finish.
|
||||||
|
//
|
||||||
|
// Note: to guarantee best results, either:
|
||||||
|
// 1. make sure 'num_nodes' >= 'width'
|
||||||
|
// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1'
|
||||||
|
//
|
||||||
|
// If you don't do either of the above things, widths will be quantized to multiples
|
||||||
|
// of small integers to guarantee the algorithm doesn't run out of temporary storage.
|
||||||
|
//
|
||||||
|
// If you do #2, then the non-quantized algorithm will be used, but the algorithm
|
||||||
|
// may run out of temporary storage and be unable to pack some rectangles.
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem);
|
||||||
|
// Optionally call this function after init but before doing any packing to
|
||||||
|
// change the handling of the out-of-temp-memory scenario, described above.
|
||||||
|
// If you call init again, this will be reset to the default (false).
|
||||||
|
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic);
|
||||||
|
// Optionally select which packing heuristic the library should use. Different
|
||||||
|
// heuristics will produce better/worse results for different data sets.
|
||||||
|
// If you call init again, this will be reset to the default.
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBRP_HEURISTIC_Skyline_default=0,
|
||||||
|
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
|
||||||
|
STBRP_HEURISTIC_Skyline_BF_sortHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// the details of the following structures don't matter to you, but they must
|
||||||
|
// be visible so you can handle the memory allocations for them
|
||||||
|
|
||||||
|
struct stbrp_node
|
||||||
|
{
|
||||||
|
stbrp_coord x,y;
|
||||||
|
stbrp_node *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct stbrp_context
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int align;
|
||||||
|
int init_mode;
|
||||||
|
int heuristic;
|
||||||
|
int num_nodes;
|
||||||
|
stbrp_node *active_head;
|
||||||
|
stbrp_node *free_head;
|
||||||
|
stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2'
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// IMPLEMENTATION SECTION
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
#ifndef STBRP_SORT
|
||||||
|
#include <stdlib.h>
|
||||||
|
#define STBRP_SORT qsort
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBRP_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#define STBRP_ASSERT assert
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define STBRP__NOTUSED(v) (void)(v)
|
||||||
|
#else
|
||||||
|
#define STBRP__NOTUSED(v) (void)sizeof(v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBRP__INIT_skyline = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
|
||||||
|
{
|
||||||
|
switch (context->init_mode) {
|
||||||
|
case STBRP__INIT_skyline:
|
||||||
|
STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight);
|
||||||
|
context->heuristic = heuristic;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
STBRP_ASSERT(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem)
|
||||||
|
{
|
||||||
|
if (allow_out_of_mem)
|
||||||
|
// if it's ok to run out of memory, then don't bother aligning them;
|
||||||
|
// this gives better packing, but may fail due to OOM (even though
|
||||||
|
// the rectangles easily fit). @TODO a smarter approach would be to only
|
||||||
|
// quantize once we've hit OOM, then we could get rid of this parameter.
|
||||||
|
context->align = 1;
|
||||||
|
else {
|
||||||
|
// if it's not ok to run out of memory, then quantize the widths
|
||||||
|
// so that num_nodes is always enough nodes.
|
||||||
|
//
|
||||||
|
// I.e. num_nodes * align >= width
|
||||||
|
// align >= width / num_nodes
|
||||||
|
// align = ceil(width/num_nodes)
|
||||||
|
|
||||||
|
context->align = (context->width + context->num_nodes-1) / context->num_nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
#ifndef STBRP_LARGE_RECTS
|
||||||
|
STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i=0; i < num_nodes-1; ++i)
|
||||||
|
nodes[i].next = &nodes[i+1];
|
||||||
|
nodes[i].next = NULL;
|
||||||
|
context->init_mode = STBRP__INIT_skyline;
|
||||||
|
context->heuristic = STBRP_HEURISTIC_Skyline_default;
|
||||||
|
context->free_head = &nodes[0];
|
||||||
|
context->active_head = &context->extra[0];
|
||||||
|
context->width = width;
|
||||||
|
context->height = height;
|
||||||
|
context->num_nodes = num_nodes;
|
||||||
|
stbrp_setup_allow_out_of_mem(context, 0);
|
||||||
|
|
||||||
|
// node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly)
|
||||||
|
context->extra[0].x = 0;
|
||||||
|
context->extra[0].y = 0;
|
||||||
|
context->extra[0].next = &context->extra[1];
|
||||||
|
context->extra[1].x = (stbrp_coord) width;
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
context->extra[1].y = (1<<30);
|
||||||
|
#else
|
||||||
|
context->extra[1].y = 65535;
|
||||||
|
#endif
|
||||||
|
context->extra[1].next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find minimum y position if it starts at x1
|
||||||
|
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
|
||||||
|
{
|
||||||
|
stbrp_node *node = first;
|
||||||
|
int x1 = x0 + width;
|
||||||
|
int min_y, visited_width, waste_area;
|
||||||
|
|
||||||
|
STBRP__NOTUSED(c);
|
||||||
|
|
||||||
|
STBRP_ASSERT(first->x <= x0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// skip in case we're past the node
|
||||||
|
while (node->next->x <= x0)
|
||||||
|
++node;
|
||||||
|
#else
|
||||||
|
STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_ASSERT(node->x <= x0);
|
||||||
|
|
||||||
|
min_y = 0;
|
||||||
|
waste_area = 0;
|
||||||
|
visited_width = 0;
|
||||||
|
while (node->x < x1) {
|
||||||
|
if (node->y > min_y) {
|
||||||
|
// raise min_y higher.
|
||||||
|
// we've accounted for all waste up to min_y,
|
||||||
|
// but we'll now add more waste for everything we've visted
|
||||||
|
waste_area += visited_width * (node->y - min_y);
|
||||||
|
min_y = node->y;
|
||||||
|
// the first time through, visited_width might be reduced
|
||||||
|
if (node->x < x0)
|
||||||
|
visited_width += node->next->x - x0;
|
||||||
|
else
|
||||||
|
visited_width += node->next->x - node->x;
|
||||||
|
} else {
|
||||||
|
// add waste area
|
||||||
|
int under_width = node->next->x - node->x;
|
||||||
|
if (under_width + visited_width > width)
|
||||||
|
under_width = width - visited_width;
|
||||||
|
waste_area += under_width * (min_y - node->y);
|
||||||
|
visited_width += under_width;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pwaste = waste_area;
|
||||||
|
return min_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int x,y;
|
||||||
|
stbrp_node **prev_link;
|
||||||
|
} stbrp__findresult;
|
||||||
|
|
||||||
|
static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height)
|
||||||
|
{
|
||||||
|
int best_waste = (1<<30), best_x, best_y = (1 << 30);
|
||||||
|
stbrp__findresult fr;
|
||||||
|
stbrp_node **prev, *node, *tail, **best = NULL;
|
||||||
|
|
||||||
|
// align to multiple of c->align
|
||||||
|
width = (width + c->align - 1);
|
||||||
|
width -= width % c->align;
|
||||||
|
STBRP_ASSERT(width % c->align == 0);
|
||||||
|
|
||||||
|
node = c->active_head;
|
||||||
|
prev = &c->active_head;
|
||||||
|
while (node->x + width <= c->width) {
|
||||||
|
int y,waste;
|
||||||
|
y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste);
|
||||||
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL
|
||||||
|
// bottom left
|
||||||
|
if (y < best_y) {
|
||||||
|
best_y = y;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// best-fit
|
||||||
|
if (y + height <= c->height) {
|
||||||
|
// can only use it if it first vertically
|
||||||
|
if (y < best_y || (y == best_y && waste < best_waste)) {
|
||||||
|
best_y = y;
|
||||||
|
best_waste = waste;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev = &node->next;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
best_x = (best == NULL) ? 0 : (*best)->x;
|
||||||
|
|
||||||
|
// if doing best-fit (BF), we also have to try aligning right edge to each node position
|
||||||
|
//
|
||||||
|
// e.g, if fitting
|
||||||
|
//
|
||||||
|
// ____________________
|
||||||
|
// |____________________|
|
||||||
|
//
|
||||||
|
// into
|
||||||
|
//
|
||||||
|
// | |
|
||||||
|
// | ____________|
|
||||||
|
// |____________|
|
||||||
|
//
|
||||||
|
// then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned
|
||||||
|
//
|
||||||
|
// This makes BF take about 2x the time
|
||||||
|
|
||||||
|
if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) {
|
||||||
|
tail = c->active_head;
|
||||||
|
node = c->active_head;
|
||||||
|
prev = &c->active_head;
|
||||||
|
// find first node that's admissible
|
||||||
|
while (tail->x < width)
|
||||||
|
tail = tail->next;
|
||||||
|
while (tail) {
|
||||||
|
int xpos = tail->x - width;
|
||||||
|
int y,waste;
|
||||||
|
STBRP_ASSERT(xpos >= 0);
|
||||||
|
// find the left position that matches this
|
||||||
|
while (node->next->x <= xpos) {
|
||||||
|
prev = &node->next;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||||
|
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||||
|
if (y + height < c->height) {
|
||||||
|
if (y <= best_y) {
|
||||||
|
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||||
|
best_x = xpos;
|
||||||
|
STBRP_ASSERT(y <= best_y);
|
||||||
|
best_y = y;
|
||||||
|
best_waste = waste;
|
||||||
|
best = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tail = tail->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fr.prev_link = best;
|
||||||
|
fr.x = best_x;
|
||||||
|
fr.y = best_y;
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height)
|
||||||
|
{
|
||||||
|
// find best position according to heuristic
|
||||||
|
stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height);
|
||||||
|
stbrp_node *node, *cur;
|
||||||
|
|
||||||
|
// bail if:
|
||||||
|
// 1. it failed
|
||||||
|
// 2. the best node doesn't fit (we don't always check this)
|
||||||
|
// 3. we're out of memory
|
||||||
|
if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) {
|
||||||
|
res.prev_link = NULL;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on success, create new node
|
||||||
|
node = context->free_head;
|
||||||
|
node->x = (stbrp_coord) res.x;
|
||||||
|
node->y = (stbrp_coord) (res.y + height);
|
||||||
|
|
||||||
|
context->free_head = node->next;
|
||||||
|
|
||||||
|
// insert the new node into the right starting point, and
|
||||||
|
// let 'cur' point to the remaining nodes needing to be
|
||||||
|
// stiched back in
|
||||||
|
|
||||||
|
cur = *res.prev_link;
|
||||||
|
if (cur->x < res.x) {
|
||||||
|
// preserve the existing one, so start testing with the next one
|
||||||
|
stbrp_node *next = cur->next;
|
||||||
|
cur->next = node;
|
||||||
|
cur = next;
|
||||||
|
} else {
|
||||||
|
*res.prev_link = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// from here, traverse cur and free the nodes, until we get to one
|
||||||
|
// that shouldn't be freed
|
||||||
|
while (cur->next && cur->next->x <= res.x + width) {
|
||||||
|
stbrp_node *next = cur->next;
|
||||||
|
// move the current node to the free list
|
||||||
|
cur->next = context->free_head;
|
||||||
|
context->free_head = cur;
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stitch the list back in
|
||||||
|
node->next = cur;
|
||||||
|
|
||||||
|
if (cur->x < res.x + width)
|
||||||
|
cur->x = (stbrp_coord) (res.x + width);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
cur = context->active_head;
|
||||||
|
while (cur->x < context->width) {
|
||||||
|
STBRP_ASSERT(cur->x < cur->next->x);
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(cur->next == NULL);
|
||||||
|
|
||||||
|
{
|
||||||
|
stbrp_node *L1 = NULL, *L2 = NULL;
|
||||||
|
int count=0;
|
||||||
|
cur = context->active_head;
|
||||||
|
while (cur) {
|
||||||
|
L1 = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
cur = context->free_head;
|
||||||
|
while (cur) {
|
||||||
|
L2 = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
STBRP_ASSERT(count == context->num_nodes+2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rect_height_compare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
if (p->h > q->h)
|
||||||
|
return -1;
|
||||||
|
if (p->h < q->h)
|
||||||
|
return 1;
|
||||||
|
return (p->w > q->w) ? -1 : (p->w < q->w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rect_width_compare(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
if (p->w > q->w)
|
||||||
|
return -1;
|
||||||
|
if (p->w < q->w)
|
||||||
|
return 1;
|
||||||
|
return (p->h > q->h) ? -1 : (p->h < q->h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rect_original_order(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const stbrp_rect *p = (const stbrp_rect *) a;
|
||||||
|
const stbrp_rect *q = (const stbrp_rect *) b;
|
||||||
|
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STBRP_LARGE_RECTS
|
||||||
|
#define STBRP__MAXVAL 0xffffffff
|
||||||
|
#else
|
||||||
|
#define STBRP__MAXVAL 0xffff
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// we use the 'was_packed' field internally to allow sorting/unsorting
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
rects[i].was_packed = i;
|
||||||
|
#ifndef STBRP_LARGE_RECTS
|
||||||
|
STBRP_ASSERT(rects[i].w <= 0xffff && rects[i].h <= 0xffff);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort according to heuristic
|
||||||
|
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
|
||||||
|
|
||||||
|
for (i=0; i < num_rects; ++i) {
|
||||||
|
if (rects[i].w == 0 || rects[i].h == 0) {
|
||||||
|
rects[i].x = rects[i].y = 0; // empty rect needs no space
|
||||||
|
} else {
|
||||||
|
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
|
||||||
|
if (fr.prev_link) {
|
||||||
|
rects[i].x = (stbrp_coord) fr.x;
|
||||||
|
rects[i].y = (stbrp_coord) fr.y;
|
||||||
|
} else {
|
||||||
|
rects[i].x = rects[i].y = STBRP__MAXVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsort
|
||||||
|
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
|
||||||
|
|
||||||
|
// set was_packed flags
|
||||||
|
for (i=0; i < num_rects; ++i)
|
||||||
|
rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL);
|
||||||
|
}
|
||||||
|
#endif
|
4018
raylib/external/stb_truetype.h
vendored
Normal file
4018
raylib/external/stb_truetype.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
393
raylib/external/stb_vorbis.h
vendored
Normal file
393
raylib/external/stb_vorbis.h
vendored
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
// Ogg Vorbis audio decoder - v1.09 - public domain
|
||||||
|
// http://nothings.org/stb_vorbis/
|
||||||
|
//
|
||||||
|
// Original version written by Sean Barrett in 2007.
|
||||||
|
//
|
||||||
|
// Originally sponsored by RAD Game Tools. Seeking sponsored
|
||||||
|
// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
|
||||||
|
// Aras Pranckevicius, and Sean Barrett.
|
||||||
|
//
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// This software is dual-licensed to the public domain and under the following
|
||||||
|
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||||
|
// publish, and distribute this file as you see fit.
|
||||||
|
//
|
||||||
|
// No warranty for any purpose is expressed or implied by the author (nor
|
||||||
|
// by RAD Game Tools). Report bugs and send enhancements to the author.
|
||||||
|
//
|
||||||
|
// Limitations:
|
||||||
|
//
|
||||||
|
// - floor 0 not supported (used in old ogg vorbis files pre-2004)
|
||||||
|
// - lossless sample-truncation at beginning ignored
|
||||||
|
// - cannot concatenate multiple vorbis streams
|
||||||
|
// - sample positions are 32-bit, limiting seekable 192Khz
|
||||||
|
// files to around 6 hours (Ogg supports 64-bit)
|
||||||
|
//
|
||||||
|
// Feature contributors:
|
||||||
|
// Dougall Johnson (sample-exact seeking)
|
||||||
|
//
|
||||||
|
// Bugfix/warning contributors:
|
||||||
|
// Terje Mathisen Niklas Frykholm Andy Hill
|
||||||
|
// Casey Muratori John Bolton Gargaj
|
||||||
|
// Laurent Gomila Marc LeBlanc Ronny Chevalier
|
||||||
|
// Bernhard Wodo Evan Balster alxprd@github
|
||||||
|
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
|
||||||
|
// Phillip Bennefall Rohit Thiago Goulart
|
||||||
|
// manxorist@github saga musix
|
||||||
|
//
|
||||||
|
// Partial history:
|
||||||
|
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
|
||||||
|
// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
|
||||||
|
// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
|
||||||
|
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
|
||||||
|
// some crash fixes when out of memory or with corrupt files
|
||||||
|
// fix some inappropriately signed shifts
|
||||||
|
// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
|
||||||
|
// 1.04 - 2014/08/27 - fix missing const-correct case in API
|
||||||
|
// 1.03 - 2014/08/07 - warning fixes
|
||||||
|
// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows
|
||||||
|
// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
|
||||||
|
// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
|
||||||
|
// (API change) report sample rate for decode-full-file funcs
|
||||||
|
//
|
||||||
|
// See end of file for full version history.
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// HEADER BEGINS HERE
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
|
||||||
|
#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
|
||||||
|
#define STB_VORBIS_NO_STDIO 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_STDIO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: Added to work with raylib on Android
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
#include "utils.h" // Android fopen function map
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/////////// THREAD SAFETY
|
||||||
|
|
||||||
|
// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
|
||||||
|
// them from multiple threads at the same time. However, you can have multiple
|
||||||
|
// stb_vorbis* handles and decode from them independently in multiple thrads.
|
||||||
|
|
||||||
|
|
||||||
|
/////////// MEMORY ALLOCATION
|
||||||
|
|
||||||
|
// normally stb_vorbis uses malloc() to allocate memory at startup,
|
||||||
|
// and alloca() to allocate temporary memory during a frame on the
|
||||||
|
// stack. (Memory consumption will depend on the amount of setup
|
||||||
|
// data in the file and how you set the compile flags for speed
|
||||||
|
// vs. size. In my test files the maximal-size usage is ~150KB.)
|
||||||
|
//
|
||||||
|
// You can modify the wrapper functions in the source (setup_malloc,
|
||||||
|
// setup_temp_malloc, temp_malloc) to change this behavior, or you
|
||||||
|
// can use a simpler allocation model: you pass in a buffer from
|
||||||
|
// which stb_vorbis will allocate _all_ its memory (including the
|
||||||
|
// temp memory). "open" may fail with a VORBIS_outofmem if you
|
||||||
|
// do not pass in enough data; there is no way to determine how
|
||||||
|
// much you do need except to succeed (at which point you can
|
||||||
|
// query get_info to find the exact amount required. yes I know
|
||||||
|
// this is lame).
|
||||||
|
//
|
||||||
|
// If you pass in a non-NULL buffer of the type below, allocation
|
||||||
|
// will occur from it as described above. Otherwise just pass NULL
|
||||||
|
// to use malloc()/alloca()
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *alloc_buffer;
|
||||||
|
int alloc_buffer_length_in_bytes;
|
||||||
|
} stb_vorbis_alloc;
|
||||||
|
|
||||||
|
|
||||||
|
/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES
|
||||||
|
|
||||||
|
typedef struct stb_vorbis stb_vorbis;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int sample_rate;
|
||||||
|
int channels;
|
||||||
|
|
||||||
|
unsigned int setup_memory_required;
|
||||||
|
unsigned int setup_temp_memory_required;
|
||||||
|
unsigned int temp_memory_required;
|
||||||
|
|
||||||
|
int max_frame_size;
|
||||||
|
} stb_vorbis_info;
|
||||||
|
|
||||||
|
// get general information about the file
|
||||||
|
extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
|
||||||
|
|
||||||
|
// get the last error detected (clears it, too)
|
||||||
|
extern int stb_vorbis_get_error(stb_vorbis *f);
|
||||||
|
|
||||||
|
// close an ogg vorbis file and free all memory in use
|
||||||
|
extern void stb_vorbis_close(stb_vorbis *f);
|
||||||
|
|
||||||
|
// this function returns the offset (in samples) from the beginning of the
|
||||||
|
// file that will be returned by the next decode, if it is known, or -1
|
||||||
|
// otherwise. after a flush_pushdata() call, this may take a while before
|
||||||
|
// it becomes valid again.
|
||||||
|
// NOT WORKING YET after a seek with PULLDATA API
|
||||||
|
extern int stb_vorbis_get_sample_offset(stb_vorbis *f);
|
||||||
|
|
||||||
|
// returns the current seek point within the file, or offset from the beginning
|
||||||
|
// of the memory buffer. In pushdata mode it returns 0.
|
||||||
|
extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
|
||||||
|
|
||||||
|
/////////// PUSHDATA API
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_PUSHDATA_API
|
||||||
|
|
||||||
|
// this API allows you to get blocks of data from any source and hand
|
||||||
|
// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
|
||||||
|
// you how much it used, and you have to give it the rest next time;
|
||||||
|
// and stb_vorbis may not have enough data to work with and you will
|
||||||
|
// need to give it the same data again PLUS more. Note that the Vorbis
|
||||||
|
// specification does not bound the size of an individual frame.
|
||||||
|
|
||||||
|
extern stb_vorbis *stb_vorbis_open_pushdata(
|
||||||
|
const unsigned char * datablock, int datablock_length_in_bytes,
|
||||||
|
int *datablock_memory_consumed_in_bytes,
|
||||||
|
int *error,
|
||||||
|
const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create a vorbis decoder by passing in the initial data block containing
|
||||||
|
// the ogg&vorbis headers (you don't need to do parse them, just provide
|
||||||
|
// the first N bytes of the file--you're told if it's not enough, see below)
|
||||||
|
// on success, returns an stb_vorbis *, does not set error, returns the amount of
|
||||||
|
// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
|
||||||
|
// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
|
||||||
|
// if returns NULL and *error is VORBIS_need_more_data, then the input block was
|
||||||
|
// incomplete and you need to pass in a larger block from the start of the file
|
||||||
|
|
||||||
|
extern int stb_vorbis_decode_frame_pushdata(
|
||||||
|
stb_vorbis *f,
|
||||||
|
const unsigned char *datablock, int datablock_length_in_bytes,
|
||||||
|
int *channels, // place to write number of float * buffers
|
||||||
|
float ***output, // place to write float ** array of float * buffers
|
||||||
|
int *samples // place to write number of output samples
|
||||||
|
);
|
||||||
|
// decode a frame of audio sample data if possible from the passed-in data block
|
||||||
|
//
|
||||||
|
// return value: number of bytes we used from datablock
|
||||||
|
//
|
||||||
|
// possible cases:
|
||||||
|
// 0 bytes used, 0 samples output (need more data)
|
||||||
|
// N bytes used, 0 samples output (resynching the stream, keep going)
|
||||||
|
// N bytes used, M samples output (one frame of data)
|
||||||
|
// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
|
||||||
|
// frame, because Vorbis always "discards" the first frame.
|
||||||
|
//
|
||||||
|
// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
|
||||||
|
// instead only datablock_length_in_bytes-3 or less. This is because it wants
|
||||||
|
// to avoid missing parts of a page header if they cross a datablock boundary,
|
||||||
|
// without writing state-machiney code to record a partial detection.
|
||||||
|
//
|
||||||
|
// The number of channels returned are stored in *channels (which can be
|
||||||
|
// NULL--it is always the same as the number of channels reported by
|
||||||
|
// get_info). *output will contain an array of float* buffers, one per
|
||||||
|
// channel. In other words, (*output)[0][0] contains the first sample from
|
||||||
|
// the first channel, and (*output)[1][0] contains the first sample from
|
||||||
|
// the second channel.
|
||||||
|
|
||||||
|
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
|
||||||
|
// inform stb_vorbis that your next datablock will not be contiguous with
|
||||||
|
// previous ones (e.g. you've seeked in the data); future attempts to decode
|
||||||
|
// frames will cause stb_vorbis to resynchronize (as noted above), and
|
||||||
|
// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
|
||||||
|
// will begin decoding the _next_ frame.
|
||||||
|
//
|
||||||
|
// if you want to seek using pushdata, you need to seek in your file, then
|
||||||
|
// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
|
||||||
|
// decoding is returning you data, call stb_vorbis_get_sample_offset, and
|
||||||
|
// if you don't like the result, seek your file again and repeat.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////// PULLING INPUT API
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_PULLDATA_API
|
||||||
|
// This API assumes stb_vorbis is allowed to pull data from a source--
|
||||||
|
// either a block of memory containing the _entire_ vorbis stream, or a
|
||||||
|
// FILE * that you or it create, or possibly some other reading mechanism
|
||||||
|
// if you go modify the source to replace the FILE * case with some kind
|
||||||
|
// of callback to your code. (But if you don't support seeking, you may
|
||||||
|
// just want to go ahead and use pushdata.)
|
||||||
|
|
||||||
|
#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
|
||||||
|
extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output);
|
||||||
|
#endif
|
||||||
|
#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
|
||||||
|
extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output);
|
||||||
|
#endif
|
||||||
|
// decode an entire file and output the data interleaved into a malloc()ed
|
||||||
|
// buffer stored in *output. The return value is the number of samples
|
||||||
|
// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
|
||||||
|
// When you're done with it, just free() the pointer returned in *output.
|
||||||
|
|
||||||
|
extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
|
||||||
|
// this must be the entire stream!). on failure, returns NULL and sets *error
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_STDIO
|
||||||
|
extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create an ogg vorbis decoder from a filename via fopen(). on failure,
|
||||||
|
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
|
||||||
|
|
||||||
|
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||||
|
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
||||||
|
// note that stb_vorbis must "own" this stream; if you seek it in between
|
||||||
|
// calls to stb_vorbis, it will become confused. Morever, if you attempt to
|
||||||
|
// perform stb_vorbis_seek_*() operations on this file, it will assume it
|
||||||
|
// owns the _entire_ rest of the file after the start point. Use the next
|
||||||
|
// function, stb_vorbis_open_file_section(), to limit it.
|
||||||
|
|
||||||
|
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);
|
||||||
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||||
|
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
|
||||||
|
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
|
||||||
|
// this stream; if you seek it in between calls to stb_vorbis, it will become
|
||||||
|
// confused.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
|
||||||
|
extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
|
||||||
|
// these functions seek in the Vorbis file to (approximately) 'sample_number'.
|
||||||
|
// after calling seek_frame(), the next call to get_frame_*() will include
|
||||||
|
// the specified sample. after calling stb_vorbis_seek(), the next call to
|
||||||
|
// stb_vorbis_get_samples_* will start with the specified sample. If you
|
||||||
|
// do not need to seek to EXACTLY the target sample when using get_samples_*,
|
||||||
|
// you can also use seek_frame().
|
||||||
|
|
||||||
|
extern void stb_vorbis_seek_start(stb_vorbis *f);
|
||||||
|
// this function is equivalent to stb_vorbis_seek(f,0)
|
||||||
|
|
||||||
|
extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
|
||||||
|
extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
|
||||||
|
// these functions return the total length of the vorbis stream
|
||||||
|
|
||||||
|
extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);
|
||||||
|
// decode the next frame and return the number of samples. the number of
|
||||||
|
// channels returned are stored in *channels (which can be NULL--it is always
|
||||||
|
// the same as the number of channels reported by get_info). *output will
|
||||||
|
// contain an array of float* buffers, one per channel. These outputs will
|
||||||
|
// be overwritten on the next call to stb_vorbis_get_frame_*.
|
||||||
|
//
|
||||||
|
// You generally should not intermix calls to stb_vorbis_get_frame_*()
|
||||||
|
// and stb_vorbis_get_samples_*(), since the latter calls the former.
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
|
||||||
|
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
|
||||||
|
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
|
||||||
|
#endif
|
||||||
|
// decode the next frame and return the number of *samples* per channel.
|
||||||
|
// Note that for interleaved data, you pass in the number of shorts (the
|
||||||
|
// size of your array), but the return value is the number of samples per
|
||||||
|
// channel, not the total number of samples.
|
||||||
|
//
|
||||||
|
// The data is coerced to the number of channels you request according to the
|
||||||
|
// channel coercion rules (see below). You must pass in the size of your
|
||||||
|
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
|
||||||
|
// The maximum buffer size needed can be gotten from get_info(); however,
|
||||||
|
// the Vorbis I specification implies an absolute maximum of 4096 samples
|
||||||
|
// per channel.
|
||||||
|
|
||||||
|
// Channel coercion rules:
|
||||||
|
// Let M be the number of channels requested, and N the number of channels present,
|
||||||
|
// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
|
||||||
|
// and stereo R be the sum of all R and center channels (channel assignment from the
|
||||||
|
// vorbis spec).
|
||||||
|
// M N output
|
||||||
|
// 1 k sum(Ck) for all k
|
||||||
|
// 2 * stereo L, stereo R
|
||||||
|
// k l k > l, the first l channels, then 0s
|
||||||
|
// k l k <= l, the first k channels
|
||||||
|
// Note that this is not _good_ surround etc. mixing at all! It's just so
|
||||||
|
// you get something useful.
|
||||||
|
|
||||||
|
extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);
|
||||||
|
extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);
|
||||||
|
// gets num_samples samples, not necessarily on a frame boundary--this requires
|
||||||
|
// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
|
||||||
|
// Returns the number of samples stored per channel; it may be less than requested
|
||||||
|
// at the end of the file. If there are no more samples in the file, returns 0.
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
|
||||||
|
extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);
|
||||||
|
extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);
|
||||||
|
#endif
|
||||||
|
// gets num_samples samples, not necessarily on a frame boundary--this requires
|
||||||
|
// buffering so you have to supply the buffers. Applies the coercion rules above
|
||||||
|
// to produce 'channels' channels. Returns the number of samples stored per channel;
|
||||||
|
// it may be less than requested at the end of the file. If there are no more
|
||||||
|
// samples in the file, returns 0.
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////// ERROR CODES
|
||||||
|
|
||||||
|
enum STBVorbisError
|
||||||
|
{
|
||||||
|
VORBIS__no_error,
|
||||||
|
|
||||||
|
VORBIS_need_more_data=1, // not a real error
|
||||||
|
|
||||||
|
VORBIS_invalid_api_mixing, // can't mix API modes
|
||||||
|
VORBIS_outofmem, // not enough memory
|
||||||
|
VORBIS_feature_not_supported, // uses floor 0
|
||||||
|
VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small
|
||||||
|
VORBIS_file_open_failure, // fopen() failed
|
||||||
|
VORBIS_seek_without_length, // can't seek in unknown-length file
|
||||||
|
|
||||||
|
VORBIS_unexpected_eof=10, // file is truncated?
|
||||||
|
VORBIS_seek_invalid, // seek past EOF
|
||||||
|
|
||||||
|
// decoding errors (corrupt/invalid stream) -- you probably
|
||||||
|
// don't care about the exact details of these
|
||||||
|
|
||||||
|
// vorbis errors:
|
||||||
|
VORBIS_invalid_setup=20,
|
||||||
|
VORBIS_invalid_stream,
|
||||||
|
|
||||||
|
// ogg errors:
|
||||||
|
VORBIS_missing_capture_pattern=30,
|
||||||
|
VORBIS_invalid_stream_structure_version,
|
||||||
|
VORBIS_continued_packet_flag_invalid,
|
||||||
|
VORBIS_incorrect_stream_serial_number,
|
||||||
|
VORBIS_invalid_first_page,
|
||||||
|
VORBIS_bad_packet_type,
|
||||||
|
VORBIS_cant_find_last_page,
|
||||||
|
VORBIS_seek_failed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
//
|
||||||
|
// HEADER ENDS HERE
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
592
raylib/external/tinfl.c
vendored
Normal file
592
raylib/external/tinfl.c
vendored
Normal file
|
@ -0,0 +1,592 @@
|
||||||
|
/* tinfl.c v1.11 - public domain inflate with zlib header parsing/adler32 checking (inflate-only subset of miniz.c)
|
||||||
|
See "unlicense" statement at the end of this file.
|
||||||
|
Rich Geldreich <richgel99@gmail.com>, last updated May 20, 2011
|
||||||
|
Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
|
||||||
|
|
||||||
|
The entire decompressor coroutine is implemented in tinfl_decompress(). The other functions are optional high-level helpers.
|
||||||
|
*/
|
||||||
|
#ifndef TINFL_HEADER_INCLUDED
|
||||||
|
#define TINFL_HEADER_INCLUDED
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef unsigned char mz_uint8;
|
||||||
|
typedef signed short mz_int16;
|
||||||
|
typedef unsigned short mz_uint16;
|
||||||
|
typedef unsigned int mz_uint32;
|
||||||
|
typedef unsigned int mz_uint;
|
||||||
|
typedef unsigned long long mz_uint64;
|
||||||
|
|
||||||
|
#if defined(_M_IX86) || defined(_M_X64)
|
||||||
|
// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 if integer loads and stores to unaligned addresses are acceptable on the target platform (slightly faster).
|
||||||
|
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
|
||||||
|
// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian.
|
||||||
|
#define MINIZ_LITTLE_ENDIAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
|
||||||
|
// Set MINIZ_HAS_64BIT_REGISTERS to 1 if the processor has 64-bit general purpose registers (enables 64-bit bitbuffer in inflator)
|
||||||
|
#define MINIZ_HAS_64BIT_REGISTERS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Works around MSVC's spammy "warning C4127: conditional expression is constant" message.
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define MZ_MACRO_END while (0, 0)
|
||||||
|
#else
|
||||||
|
#define MZ_MACRO_END while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Decompression flags used by tinfl_decompress().
|
||||||
|
// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream.
|
||||||
|
// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input.
|
||||||
|
// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB).
|
||||||
|
// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
|
||||||
|
TINFL_FLAG_HAS_MORE_INPUT = 2,
|
||||||
|
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
|
||||||
|
TINFL_FLAG_COMPUTE_ADLER32 = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
// High level decompression functions:
|
||||||
|
// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc().
|
||||||
|
// On entry:
|
||||||
|
// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress.
|
||||||
|
// On return:
|
||||||
|
// Function returns a pointer to the decompressed data, or NULL on failure.
|
||||||
|
// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data.
|
||||||
|
// The caller must free() the returned block when it's no longer needed.
|
||||||
|
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
|
||||||
|
|
||||||
|
// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory.
|
||||||
|
// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success.
|
||||||
|
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
|
||||||
|
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
|
||||||
|
|
||||||
|
// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer.
|
||||||
|
// Returns 1 on success or 0 on failure.
|
||||||
|
typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
|
||||||
|
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||||
|
|
||||||
|
struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor;
|
||||||
|
|
||||||
|
// Max size of LZ dictionary.
|
||||||
|
#define TINFL_LZ_DICT_SIZE 32768
|
||||||
|
|
||||||
|
// Return status.
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TINFL_STATUS_BAD_PARAM = -3,
|
||||||
|
TINFL_STATUS_ADLER32_MISMATCH = -2,
|
||||||
|
TINFL_STATUS_FAILED = -1,
|
||||||
|
TINFL_STATUS_DONE = 0,
|
||||||
|
TINFL_STATUS_NEEDS_MORE_INPUT = 1,
|
||||||
|
TINFL_STATUS_HAS_MORE_OUTPUT = 2
|
||||||
|
} tinfl_status;
|
||||||
|
|
||||||
|
// Initializes the decompressor to its initial state.
|
||||||
|
#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END
|
||||||
|
#define tinfl_get_adler32(r) (r)->m_check_adler32
|
||||||
|
|
||||||
|
// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability.
|
||||||
|
// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output.
|
||||||
|
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
|
||||||
|
|
||||||
|
// Internal/private bits follow.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19,
|
||||||
|
TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
|
||||||
|
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
|
||||||
|
} tinfl_huff_table;
|
||||||
|
|
||||||
|
#if MINIZ_HAS_64BIT_REGISTERS
|
||||||
|
#define TINFL_USE_64BIT_BITBUF 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TINFL_USE_64BIT_BITBUF
|
||||||
|
typedef mz_uint64 tinfl_bit_buf_t;
|
||||||
|
#define TINFL_BITBUF_SIZE (64)
|
||||||
|
#else
|
||||||
|
typedef mz_uint32 tinfl_bit_buf_t;
|
||||||
|
#define TINFL_BITBUF_SIZE (32)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct tinfl_decompressor_tag
|
||||||
|
{
|
||||||
|
mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
|
||||||
|
tinfl_bit_buf_t m_bit_buf;
|
||||||
|
size_t m_dist_from_out_buf_start;
|
||||||
|
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
|
||||||
|
mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #ifdef TINFL_HEADER_INCLUDED
|
||||||
|
|
||||||
|
// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.)
|
||||||
|
|
||||||
|
#ifndef TINFL_HEADER_FILE_ONLY
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// MZ_MALLOC, etc. are only used by the optional high-level helper functions.
|
||||||
|
#ifdef MINIZ_NO_MALLOC
|
||||||
|
#define MZ_MALLOC(x) NULL
|
||||||
|
#define MZ_FREE(x) x, ((void)0)
|
||||||
|
#define MZ_REALLOC(p, x) NULL
|
||||||
|
#else
|
||||||
|
#define MZ_MALLOC(x) malloc(x)
|
||||||
|
#define MZ_FREE(x) free(x)
|
||||||
|
#define MZ_REALLOC(p, x) realloc(p, x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
|
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
|
||||||
|
|
||||||
|
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
|
||||||
|
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
|
||||||
|
#define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
|
||||||
|
#else
|
||||||
|
#define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
|
||||||
|
#define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
|
||||||
|
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
|
||||||
|
|
||||||
|
#define TINFL_CR_BEGIN switch(r->m_state) { case 0:
|
||||||
|
#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END
|
||||||
|
#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END
|
||||||
|
#define TINFL_CR_FINISH }
|
||||||
|
|
||||||
|
// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never
|
||||||
|
// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario.
|
||||||
|
#define TINFL_GET_BYTE(state_index, c) do { \
|
||||||
|
if (pIn_buf_cur >= pIn_buf_end) { \
|
||||||
|
for ( ; ; ) { \
|
||||||
|
if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \
|
||||||
|
TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \
|
||||||
|
if (pIn_buf_cur < pIn_buf_end) { \
|
||||||
|
c = *pIn_buf_cur++; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
c = 0; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} else c = *pIn_buf_cur++; } MZ_MACRO_END
|
||||||
|
|
||||||
|
#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n))
|
||||||
|
#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
|
||||||
|
#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END
|
||||||
|
|
||||||
|
// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2.
|
||||||
|
// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a
|
||||||
|
// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the
|
||||||
|
// bit buffer contains >=15 bits (deflate's max. Huffman code size).
|
||||||
|
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
|
||||||
|
do { \
|
||||||
|
temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
|
||||||
|
if (temp >= 0) { \
|
||||||
|
code_len = temp >> 9; \
|
||||||
|
if ((code_len) && (num_bits >= code_len)) \
|
||||||
|
break; \
|
||||||
|
} else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
|
||||||
|
code_len = TINFL_FAST_LOOKUP_BITS; \
|
||||||
|
do { \
|
||||||
|
temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
|
||||||
|
} while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
|
||||||
|
} TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
|
||||||
|
} while (num_bits < 15);
|
||||||
|
|
||||||
|
// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read
|
||||||
|
// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully
|
||||||
|
// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32.
|
||||||
|
// The slow path is only executed at the very end of the input buffer.
|
||||||
|
#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \
|
||||||
|
int temp; mz_uint code_len, c; \
|
||||||
|
if (num_bits < 15) { \
|
||||||
|
if ((pIn_buf_end - pIn_buf_cur) < 2) { \
|
||||||
|
TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
|
||||||
|
} else { \
|
||||||
|
bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
|
||||||
|
code_len = temp >> 9, temp &= 511; \
|
||||||
|
else { \
|
||||||
|
code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \
|
||||||
|
} sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END
|
||||||
|
|
||||||
|
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
|
||||||
|
{
|
||||||
|
static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 };
|
||||||
|
static const int s_length_extra[31]= { 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,0,0 };
|
||||||
|
static const int s_dist_base[32] = { 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,0,0};
|
||||||
|
static const int s_dist_extra[32] = { 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};
|
||||||
|
static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
|
||||||
|
static const int s_min_table_sizes[3] = { 257, 1, 4 };
|
||||||
|
|
||||||
|
tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf;
|
||||||
|
const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
|
||||||
|
mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
|
||||||
|
size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
|
||||||
|
|
||||||
|
// Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter).
|
||||||
|
if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; }
|
||||||
|
|
||||||
|
num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start;
|
||||||
|
TINFL_CR_BEGIN
|
||||||
|
|
||||||
|
bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1;
|
||||||
|
if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
|
||||||
|
{
|
||||||
|
TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1);
|
||||||
|
counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
|
||||||
|
if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
|
||||||
|
if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); }
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1;
|
||||||
|
if (r->m_type == 0)
|
||||||
|
{
|
||||||
|
TINFL_SKIP_BITS(5, num_bits & 7);
|
||||||
|
for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); }
|
||||||
|
if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); }
|
||||||
|
while ((counter) && (num_bits))
|
||||||
|
{
|
||||||
|
TINFL_GET_BITS(51, dist, 8);
|
||||||
|
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
||||||
|
*pOut_buf_cur++ = (mz_uint8)dist;
|
||||||
|
counter--;
|
||||||
|
}
|
||||||
|
while (counter)
|
||||||
|
{
|
||||||
|
size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
||||||
|
while (pIn_buf_cur >= pIn_buf_end)
|
||||||
|
{
|
||||||
|
if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
|
||||||
|
TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (r->m_type == 3)
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (r->m_type == 1)
|
||||||
|
{
|
||||||
|
mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i;
|
||||||
|
r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
|
||||||
|
for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
|
||||||
|
MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
|
||||||
|
r->m_table_sizes[2] = 19;
|
||||||
|
}
|
||||||
|
for ( ; (int)r->m_type >= 0; r->m_type--)
|
||||||
|
{
|
||||||
|
int tree_next, tree_cur; tinfl_huff_table *pTable;
|
||||||
|
mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
|
||||||
|
for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
|
||||||
|
used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
|
||||||
|
for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
|
||||||
|
if ((65536 != total) && (used_syms > 1))
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
|
||||||
|
{
|
||||||
|
mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue;
|
||||||
|
cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1);
|
||||||
|
if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; }
|
||||||
|
if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; }
|
||||||
|
rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
|
||||||
|
for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
|
||||||
|
{
|
||||||
|
tree_cur -= ((rev_code >>= 1) & 1);
|
||||||
|
if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1];
|
||||||
|
}
|
||||||
|
tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
|
||||||
|
}
|
||||||
|
if (r->m_type == 2)
|
||||||
|
{
|
||||||
|
for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); )
|
||||||
|
{
|
||||||
|
mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; }
|
||||||
|
if ((dist == 16) && (!counter))
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16];
|
||||||
|
TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s;
|
||||||
|
}
|
||||||
|
if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
mz_uint8 *pSrc;
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
|
||||||
|
{
|
||||||
|
TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
|
||||||
|
if (counter >= 256)
|
||||||
|
break;
|
||||||
|
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
||||||
|
*pOut_buf_cur++ = (mz_uint8)counter;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sym2; mz_uint code_len;
|
||||||
|
#if TINFL_USE_64BIT_BITBUF
|
||||||
|
if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; }
|
||||||
|
#else
|
||||||
|
if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
|
||||||
|
#endif
|
||||||
|
if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
|
||||||
|
code_len = sym2 >> 9;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
|
||||||
|
}
|
||||||
|
counter = sym2; bit_buf >>= code_len; num_bits -= code_len;
|
||||||
|
if (counter & 256)
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if !TINFL_USE_64BIT_BITBUF
|
||||||
|
if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; }
|
||||||
|
#endif
|
||||||
|
if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
|
||||||
|
code_len = sym2 >> 9;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0);
|
||||||
|
}
|
||||||
|
bit_buf >>= code_len; num_bits -= code_len;
|
||||||
|
|
||||||
|
pOut_buf_cur[0] = (mz_uint8)counter;
|
||||||
|
if (sym2 & 256)
|
||||||
|
{
|
||||||
|
pOut_buf_cur++;
|
||||||
|
counter = sym2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pOut_buf_cur[1] = (mz_uint8)sym2;
|
||||||
|
pOut_buf_cur += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((counter &= 511) == 256) break;
|
||||||
|
|
||||||
|
num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257];
|
||||||
|
if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; }
|
||||||
|
|
||||||
|
TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
|
||||||
|
num_extra = s_dist_extra[dist]; dist = s_dist_base[dist];
|
||||||
|
if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; }
|
||||||
|
|
||||||
|
dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
|
||||||
|
if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
|
||||||
|
{
|
||||||
|
TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
|
pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
|
||||||
|
|
||||||
|
if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
|
||||||
|
{
|
||||||
|
while (counter--)
|
||||||
|
{
|
||||||
|
while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); }
|
||||||
|
*pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
|
||||||
|
else if ((counter >= 9) && (counter <= dist))
|
||||||
|
{
|
||||||
|
const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
|
||||||
|
((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
|
||||||
|
pOut_buf_cur += 8;
|
||||||
|
} while ((pSrc += 8) < pSrc_end);
|
||||||
|
if ((counter &= 7) < 3)
|
||||||
|
{
|
||||||
|
if (counter)
|
||||||
|
{
|
||||||
|
pOut_buf_cur[0] = pSrc[0];
|
||||||
|
if (counter > 1)
|
||||||
|
pOut_buf_cur[1] = pSrc[1];
|
||||||
|
pOut_buf_cur += counter;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
do
|
||||||
|
{
|
||||||
|
pOut_buf_cur[0] = pSrc[0];
|
||||||
|
pOut_buf_cur[1] = pSrc[1];
|
||||||
|
pOut_buf_cur[2] = pSrc[2];
|
||||||
|
pOut_buf_cur += 3; pSrc += 3;
|
||||||
|
} while ((int)(counter -= 3) > 2);
|
||||||
|
if ((int)counter > 0)
|
||||||
|
{
|
||||||
|
pOut_buf_cur[0] = pSrc[0];
|
||||||
|
if ((int)counter > 1)
|
||||||
|
pOut_buf_cur[1] = pSrc[1];
|
||||||
|
pOut_buf_cur += counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!(r->m_final & 1));
|
||||||
|
if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
|
||||||
|
{
|
||||||
|
TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; }
|
||||||
|
}
|
||||||
|
TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
|
||||||
|
TINFL_CR_FINISH
|
||||||
|
|
||||||
|
common_exit:
|
||||||
|
r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
|
||||||
|
*pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
|
||||||
|
if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
|
||||||
|
{
|
||||||
|
const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
|
||||||
|
mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
|
||||||
|
while (buf_len)
|
||||||
|
{
|
||||||
|
for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
|
||||||
|
{
|
||||||
|
s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1;
|
||||||
|
s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1;
|
||||||
|
}
|
||||||
|
for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
|
||||||
|
s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
|
||||||
|
}
|
||||||
|
r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Higher level helper functions.
|
||||||
|
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
|
||||||
|
{
|
||||||
|
tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0;
|
||||||
|
*pOut_len = 0;
|
||||||
|
tinfl_init(&decomp);
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
|
||||||
|
tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size,
|
||||||
|
(flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
|
||||||
|
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
|
||||||
|
{
|
||||||
|
MZ_FREE(pBuf); *pOut_len = 0; return NULL;
|
||||||
|
}
|
||||||
|
src_buf_ofs += src_buf_size;
|
||||||
|
*pOut_len += dst_buf_size;
|
||||||
|
if (status == TINFL_STATUS_DONE) break;
|
||||||
|
new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128;
|
||||||
|
pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
|
||||||
|
if (!pNew_buf)
|
||||||
|
{
|
||||||
|
MZ_FREE(pBuf); *pOut_len = 0; return NULL;
|
||||||
|
}
|
||||||
|
pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity;
|
||||||
|
}
|
||||||
|
return pBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
|
||||||
|
{
|
||||||
|
tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp);
|
||||||
|
status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
|
||||||
|
return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
tinfl_decompressor decomp;
|
||||||
|
mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0;
|
||||||
|
if (!pDict)
|
||||||
|
return TINFL_STATUS_FAILED;
|
||||||
|
tinfl_init(&decomp);
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
|
||||||
|
tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
|
||||||
|
(flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
|
||||||
|
in_buf_ofs += in_buf_size;
|
||||||
|
if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
|
||||||
|
break;
|
||||||
|
if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
|
||||||
|
{
|
||||||
|
result = (status == TINFL_STATUS_DONE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
|
||||||
|
}
|
||||||
|
MZ_FREE(pDict);
|
||||||
|
*pIn_buf_size = in_buf_ofs;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // #ifndef TINFL_HEADER_FILE_ONLY
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
*/
|
523
raylib/gestures.h
Normal file
523
raylib/gestures.h
Normal file
|
@ -0,0 +1,523 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse)
|
||||||
|
*
|
||||||
|
* #define GESTURES_IMPLEMENTATION
|
||||||
|
* 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
|
||||||
|
* or source files without problems. But only ONE file should hold the implementation.
|
||||||
|
*
|
||||||
|
* #define GESTURES_STANDALONE
|
||||||
|
* If defined, the library can be used as standalone to process gesture events with
|
||||||
|
* no external dependencies.
|
||||||
|
*
|
||||||
|
* NOTE: Memory footprint of this library is aproximately 128 bytes
|
||||||
|
*
|
||||||
|
* Initial design by Marc Palau (2014)
|
||||||
|
* Redesigned by Albert Martos and Ian Eito (2015)
|
||||||
|
* Reviewed by Ramon Santamaria (2015-2016)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef GESTURES_H
|
||||||
|
#define GESTURES_H
|
||||||
|
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.14159265358979323846
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
// NOTE: Below types are required for GESTURES_STANDALONE usage
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(GESTURES_STANDALONE)
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// Boolean type
|
||||||
|
typedef enum { false, true } bool;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Vector2 type
|
||||||
|
typedef struct Vector2 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} Vector2;
|
||||||
|
|
||||||
|
// Gestures type
|
||||||
|
// NOTE: It could be used as flags to enable only some gestures
|
||||||
|
typedef enum {
|
||||||
|
GESTURE_NONE = 1,
|
||||||
|
GESTURE_TAP = 2,
|
||||||
|
GESTURE_DOUBLETAP = 4,
|
||||||
|
GESTURE_HOLD = 8,
|
||||||
|
GESTURE_DRAG = 16,
|
||||||
|
GESTURE_SWIPE_RIGHT = 32,
|
||||||
|
GESTURE_SWIPE_LEFT = 64,
|
||||||
|
GESTURE_SWIPE_UP = 128,
|
||||||
|
GESTURE_SWIPE_DOWN = 256,
|
||||||
|
GESTURE_PINCH_IN = 512,
|
||||||
|
GESTURE_PINCH_OUT = 1024
|
||||||
|
} Gestures;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction;
|
||||||
|
|
||||||
|
// Gesture events
|
||||||
|
// NOTE: MAX_TOUCH_POINTS fixed to 4
|
||||||
|
typedef struct {
|
||||||
|
int touchAction;
|
||||||
|
int pointCount;
|
||||||
|
int pointerId[4];
|
||||||
|
Vector2 position[4];
|
||||||
|
} GestureEvent;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures
|
||||||
|
void UpdateGestures(void); // Update gestures detected (must be called every frame)
|
||||||
|
|
||||||
|
#if defined(GESTURES_STANDALONE)
|
||||||
|
void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags
|
||||||
|
bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
|
int GetGestureDetected(void); // Get latest detected gesture
|
||||||
|
int GetTouchPointsCount(void); // Get touch points count
|
||||||
|
float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
|
Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
|
float GetGestureDragAngle(void); // Get gesture drag angle
|
||||||
|
Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
||||||
|
float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // GESTURES_H
|
||||||
|
|
||||||
|
/***********************************************************************************
|
||||||
|
*
|
||||||
|
* GESTURES IMPLEMENTATION
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#if defined(GESTURES_IMPLEMENTATION)
|
||||||
|
|
||||||
|
#include <math.h> // Required for: atan2(), sqrt()
|
||||||
|
#include <stdint.h> // Required for: uint64_t
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// Functions required to query time on Windows
|
||||||
|
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
|
||||||
|
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
|
||||||
|
#elif defined(__linux)
|
||||||
|
#include <sys/time.h> // Required for: timespec
|
||||||
|
#include <time.h> // Required for: clock_gettime()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#define FORCE_TO_SWIPE 0.0005f // Measured in normalized screen units/time
|
||||||
|
#define MINIMUM_DRAG 0.015f // Measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
#define MINIMUM_PINCH 0.005f // Measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
#define TAP_TIMEOUT 300 // Time in milliseconds
|
||||||
|
#define PINCH_TIMEOUT 300 // Time in milliseconds
|
||||||
|
#define DOUBLETAP_RANGE 0.03f // Measured in normalized screen units (0.0f to 1.0f)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// ...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Touch gesture variables
|
||||||
|
static Vector2 touchDownPosition = { 0.0f, 0.0f };
|
||||||
|
static Vector2 touchDownPosition2 = { 0.0f, 0.0f };
|
||||||
|
static Vector2 touchDownDragPosition = { 0.0f, 0.0f };
|
||||||
|
static Vector2 touchUpPosition = { 0.0f, 0.0f };
|
||||||
|
static Vector2 moveDownPosition = { 0.0f, 0.0f };
|
||||||
|
static Vector2 moveDownPosition2 = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
static int pointCount = 0; // Touch points counter
|
||||||
|
static int firstTouchId = -1; // Touch id for first touch point
|
||||||
|
static double eventTime = 0.0; // Time stamp when an event happened
|
||||||
|
|
||||||
|
// Tap gesture variables
|
||||||
|
static int tapCounter = 0; // TAP counter (one tap implies TOUCH_DOWN and TOUCH_UP actions)
|
||||||
|
|
||||||
|
// Hold gesture variables
|
||||||
|
static bool resetHold = false; // HOLD reset to get first touch point again
|
||||||
|
static double timeHold = 0.0f; // HOLD duration in milliseconds
|
||||||
|
|
||||||
|
// Drag gesture variables
|
||||||
|
static Vector2 dragVector = { 0.0f , 0.0f }; // DRAG vector (between initial and current position)
|
||||||
|
static float dragAngle = 0.0f; // DRAG angle (relative to x-axis)
|
||||||
|
static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) (normalized [0..1])
|
||||||
|
static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame)
|
||||||
|
|
||||||
|
// Swipe gestures variables
|
||||||
|
static bool startMoving = false; // SWIPE used to define when start measuring swipeTime
|
||||||
|
static double swipeTime = 0.0; // SWIPE time to calculate drag intensity
|
||||||
|
|
||||||
|
// Pinch gesture variables
|
||||||
|
static Vector2 pinchVector = { 0.0f , 0.0f }; // PINCH vector (between first and second touch points)
|
||||||
|
static float pinchAngle = 0.0f; // PINCH angle (relative to x-axis)
|
||||||
|
static float pinchDistance = 0.0f; // PINCH displacement distance (normalized [0..1])
|
||||||
|
|
||||||
|
static int currentGesture = GESTURE_NONE; // Current detected gesture
|
||||||
|
|
||||||
|
// Enabled gestures flags, all gestures enabled by default
|
||||||
|
static unsigned int enabledGestures = 0b0000001111111111;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition);
|
||||||
|
static float Vector2Distance(Vector2 v1, Vector2 v2);
|
||||||
|
static double GetCurrentTime(void);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Enable only desired getures to be detected
|
||||||
|
void SetGesturesEnabled(unsigned int gestureFlags)
|
||||||
|
{
|
||||||
|
enabledGestures = gestureFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a gesture have been detected
|
||||||
|
bool IsGestureDetected(int gesture)
|
||||||
|
{
|
||||||
|
if ((enabledGestures & currentGesture) == gesture) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process gesture event and translate it into gestures
|
||||||
|
void ProcessGestureEvent(GestureEvent event)
|
||||||
|
{
|
||||||
|
// Reset required variables
|
||||||
|
pointCount = event.pointCount; // Required on UpdateGestures()
|
||||||
|
|
||||||
|
if (pointCount < 2)
|
||||||
|
{
|
||||||
|
if (event.touchAction == TOUCH_DOWN)
|
||||||
|
{
|
||||||
|
tapCounter++; // Tap counter
|
||||||
|
|
||||||
|
// Detect GESTURE_DOUBLE_TAP
|
||||||
|
if ((currentGesture == GESTURE_NONE) && (tapCounter >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (Vector2Distance(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE))
|
||||||
|
{
|
||||||
|
currentGesture = GESTURE_DOUBLETAP;
|
||||||
|
tapCounter = 0;
|
||||||
|
}
|
||||||
|
else // Detect GESTURE_TAP
|
||||||
|
{
|
||||||
|
tapCounter = 1;
|
||||||
|
currentGesture = GESTURE_TAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
touchDownPosition = event.position[0];
|
||||||
|
touchDownDragPosition = event.position[0];
|
||||||
|
|
||||||
|
touchUpPosition = touchDownPosition;
|
||||||
|
eventTime = GetCurrentTime();
|
||||||
|
|
||||||
|
firstTouchId = event.pointerId[0];
|
||||||
|
|
||||||
|
dragVector = (Vector2){ 0.0f, 0.0f };
|
||||||
|
}
|
||||||
|
else if (event.touchAction == TOUCH_UP)
|
||||||
|
{
|
||||||
|
if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0];
|
||||||
|
|
||||||
|
// NOTE: dragIntensity dependend on the resolution of the screen
|
||||||
|
dragDistance = Vector2Distance(touchDownPosition, touchUpPosition);
|
||||||
|
dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime));
|
||||||
|
|
||||||
|
startMoving = false;
|
||||||
|
|
||||||
|
// Detect GESTURE_SWIPE
|
||||||
|
if ((dragIntensity > FORCE_TO_SWIPE) && (firstTouchId == event.pointerId[0]))
|
||||||
|
{
|
||||||
|
// NOTE: Angle should be inverted in Y
|
||||||
|
dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);
|
||||||
|
|
||||||
|
if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right
|
||||||
|
else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up
|
||||||
|
else if ((dragAngle > 120) && (dragAngle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left
|
||||||
|
else if ((dragAngle > 210) && (dragAngle < 300)) currentGesture = GESTURE_SWIPE_DOWN; // Down
|
||||||
|
else currentGesture = GESTURE_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dragDistance = 0.0f;
|
||||||
|
dragIntensity = 0.0f;
|
||||||
|
dragAngle = 0.0f;
|
||||||
|
|
||||||
|
currentGesture = GESTURE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
touchDownDragPosition = (Vector2){ 0.0f, 0.0f };
|
||||||
|
pointCount = 0;
|
||||||
|
}
|
||||||
|
else if (event.touchAction == TOUCH_MOVE)
|
||||||
|
{
|
||||||
|
if (currentGesture == GESTURE_DRAG) eventTime = GetCurrentTime();
|
||||||
|
|
||||||
|
if (!startMoving)
|
||||||
|
{
|
||||||
|
swipeTime = GetCurrentTime();
|
||||||
|
startMoving = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveDownPosition = event.position[0];
|
||||||
|
|
||||||
|
if (currentGesture == GESTURE_HOLD)
|
||||||
|
{
|
||||||
|
if (resetHold) touchDownPosition = event.position[0];
|
||||||
|
|
||||||
|
resetHold = false;
|
||||||
|
|
||||||
|
// Detect GESTURE_DRAG
|
||||||
|
if (Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_DRAG)
|
||||||
|
{
|
||||||
|
eventTime = GetCurrentTime();
|
||||||
|
currentGesture = GESTURE_DRAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dragVector.x = moveDownPosition.x - touchDownDragPosition.x;
|
||||||
|
dragVector.y = moveDownPosition.y - touchDownDragPosition.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Two touch points
|
||||||
|
{
|
||||||
|
if (event.touchAction == TOUCH_DOWN)
|
||||||
|
{
|
||||||
|
touchDownPosition = event.position[0];
|
||||||
|
touchDownPosition2 = event.position[1];
|
||||||
|
|
||||||
|
//pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2);
|
||||||
|
|
||||||
|
pinchVector.x = touchDownPosition2.x - touchDownPosition.x;
|
||||||
|
pinchVector.y = touchDownPosition2.y - touchDownPosition.y;
|
||||||
|
|
||||||
|
currentGesture = GESTURE_HOLD;
|
||||||
|
timeHold = GetCurrentTime();
|
||||||
|
}
|
||||||
|
else if (event.touchAction == TOUCH_MOVE)
|
||||||
|
{
|
||||||
|
pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2);
|
||||||
|
|
||||||
|
touchDownPosition = moveDownPosition;
|
||||||
|
touchDownPosition2 = moveDownPosition2;
|
||||||
|
|
||||||
|
moveDownPosition = event.position[0];
|
||||||
|
moveDownPosition2 = event.position[1];
|
||||||
|
|
||||||
|
pinchVector.x = moveDownPosition2.x - moveDownPosition.x;
|
||||||
|
pinchVector.y = moveDownPosition2.y - moveDownPosition.y;
|
||||||
|
|
||||||
|
if ((Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) >= MINIMUM_PINCH))
|
||||||
|
{
|
||||||
|
if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN;
|
||||||
|
else currentGesture = GESTURE_PINCH_OUT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentGesture = GESTURE_HOLD;
|
||||||
|
timeHold = GetCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Angle should be inverted in Y
|
||||||
|
pinchAngle = 360.0f - Vector2Angle(moveDownPosition, moveDownPosition2);
|
||||||
|
}
|
||||||
|
else if (event.touchAction == TOUCH_UP)
|
||||||
|
{
|
||||||
|
pinchDistance = 0.0f;
|
||||||
|
pinchAngle = 0.0f;
|
||||||
|
pinchVector = (Vector2){ 0.0f, 0.0f };
|
||||||
|
pointCount = 0;
|
||||||
|
|
||||||
|
currentGesture = GESTURE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update gestures detected (must be called every frame)
|
||||||
|
void UpdateGestures(void)
|
||||||
|
{
|
||||||
|
// NOTE: Gestures are processed through system callbacks on touch events
|
||||||
|
|
||||||
|
// Detect GESTURE_HOLD
|
||||||
|
if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && (pointCount < 2))
|
||||||
|
{
|
||||||
|
currentGesture = GESTURE_HOLD;
|
||||||
|
timeHold = GetCurrentTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((GetCurrentTime() - eventTime) > TAP_TIMEOUT) && (currentGesture == GESTURE_DRAG) && (pointCount < 2))
|
||||||
|
{
|
||||||
|
currentGesture = GESTURE_HOLD;
|
||||||
|
timeHold = GetCurrentTime();
|
||||||
|
resetHold = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect GESTURE_NONE
|
||||||
|
if ((currentGesture == GESTURE_SWIPE_RIGHT) || (currentGesture == GESTURE_SWIPE_UP) || (currentGesture == GESTURE_SWIPE_LEFT) || (currentGesture == GESTURE_SWIPE_DOWN))
|
||||||
|
{
|
||||||
|
currentGesture = GESTURE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get number of touch points
|
||||||
|
int GetTouchPointsCount(void)
|
||||||
|
{
|
||||||
|
// NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called
|
||||||
|
|
||||||
|
return pointCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get latest detected gesture
|
||||||
|
int GetGestureDetected(void)
|
||||||
|
{
|
||||||
|
// Get current gesture only if enabled
|
||||||
|
return (enabledGestures & currentGesture);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hold time measured in ms
|
||||||
|
float GetGestureHoldDuration(void)
|
||||||
|
{
|
||||||
|
// NOTE: time is calculated on current gesture HOLD
|
||||||
|
|
||||||
|
double time = 0.0;
|
||||||
|
|
||||||
|
if (currentGesture == GESTURE_HOLD) time = GetCurrentTime() - timeHold;
|
||||||
|
|
||||||
|
return (float)time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get drag vector (between initial touch point to current)
|
||||||
|
Vector2 GetGestureDragVector(void)
|
||||||
|
{
|
||||||
|
// NOTE: drag vector is calculated on one touch points TOUCH_MOVE
|
||||||
|
|
||||||
|
return dragVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get drag angle
|
||||||
|
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
|
||||||
|
float GetGestureDragAngle(void)
|
||||||
|
{
|
||||||
|
// NOTE: drag angle is calculated on one touch points TOUCH_UP
|
||||||
|
|
||||||
|
return dragAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get distance between two pinch points
|
||||||
|
Vector2 GetGesturePinchVector(void)
|
||||||
|
{
|
||||||
|
// NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index)
|
||||||
|
// NOTE: pinch distance is calculated on two touch points TOUCH_MOVE
|
||||||
|
|
||||||
|
return pinchVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get angle beween two pinch points
|
||||||
|
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
|
||||||
|
float GetGesturePinchAngle(void)
|
||||||
|
{
|
||||||
|
// NOTE: pinch angle is calculated on two touch points TOUCH_MOVE
|
||||||
|
|
||||||
|
return pinchAngle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Returns angle from two-points vector with X-axis
|
||||||
|
static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition)
|
||||||
|
{
|
||||||
|
float angle;
|
||||||
|
|
||||||
|
angle = atan2f(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x)*(180.0f/PI);
|
||||||
|
|
||||||
|
if (angle < 0) angle += 360.0f;
|
||||||
|
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate distance between two Vector2
|
||||||
|
static float Vector2Distance(Vector2 v1, Vector2 v2)
|
||||||
|
{
|
||||||
|
float result;
|
||||||
|
|
||||||
|
float dx = v2.x - v1.x;
|
||||||
|
float dy = v2.y - v1.y;
|
||||||
|
|
||||||
|
result = (float)sqrt(dx*dx + dy*dy);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time measure returned are milliseconds
|
||||||
|
static double GetCurrentTime(void)
|
||||||
|
{
|
||||||
|
double time = 0;
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
unsigned long long int clockFrequency, currentTime;
|
||||||
|
|
||||||
|
QueryPerformanceFrequency(&clockFrequency);
|
||||||
|
QueryPerformanceCounter(¤tTime);
|
||||||
|
|
||||||
|
time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux)
|
||||||
|
// NOTE: Only for Linux-based systems
|
||||||
|
struct timespec now;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||||
|
uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; // Time in nanoseconds
|
||||||
|
|
||||||
|
time = ((double)nowTime/1000000.0); // Time in miliseconds
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GESTURES_IMPLEMENTATION
|
2001
raylib/models.c
Normal file
2001
raylib/models.c
Normal file
File diff suppressed because it is too large
Load diff
117
raylib/models.go
117
raylib/models.go
|
@ -107,87 +107,6 @@ func NewModelFromPointer(ptr unsafe.Pointer) Model {
|
||||||
return *(*Model)(ptr)
|
return *(*Model)(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Light type
|
|
||||||
type Light struct {
|
|
||||||
// Light unique id
|
|
||||||
Id uint32
|
|
||||||
// Light enabled
|
|
||||||
Enabled uint32
|
|
||||||
// Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
|
|
||||||
Type int32
|
|
||||||
// Light position
|
|
||||||
Position Vector3
|
|
||||||
// Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
|
|
||||||
Target Vector3
|
|
||||||
// Light attenuation radius light intensity reduced with distance (world distance)
|
|
||||||
Radius float32
|
|
||||||
// Light diffuse color
|
|
||||||
Diffuse Color
|
|
||||||
// Light intensity level
|
|
||||||
Intensity float32
|
|
||||||
// Light cone max angle: LIGHT_SPOT
|
|
||||||
ConeAngle float32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Light) cptr() *C.Light {
|
|
||||||
return (*C.Light)(unsafe.Pointer(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns new Light
|
|
||||||
func NewLight(id uint32, enabled uint32, _type int32, position, target Vector3, radius float32, diffuse Color, intensity, coneAngle float32) Light {
|
|
||||||
return Light{id, enabled, _type, position, target, radius, diffuse, intensity, coneAngle}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns new Light from pointer
|
|
||||||
func NewLightFromPointer(ptr unsafe.Pointer) Light {
|
|
||||||
return *(*Light)(ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
type LightType int32
|
|
||||||
|
|
||||||
// Light types
|
|
||||||
const (
|
|
||||||
LightPoint LightType = C.LIGHT_POINT
|
|
||||||
LightDirectional LightType = C.LIGHT_DIRECTIONAL
|
|
||||||
LightSpot LightType = C.LIGHT_SPOT
|
|
||||||
)
|
|
||||||
|
|
||||||
// LightData type
|
|
||||||
type LightData struct {
|
|
||||||
// Light unique id
|
|
||||||
Id uint32
|
|
||||||
// Light enabled
|
|
||||||
Enabled uint32
|
|
||||||
// Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
|
|
||||||
Type int32
|
|
||||||
// Light position
|
|
||||||
Position Vector3
|
|
||||||
// Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
|
|
||||||
Target Vector3
|
|
||||||
// Light attenuation radius light intensity reduced with distance (world distance)
|
|
||||||
Radius float32
|
|
||||||
// Light diffuse color
|
|
||||||
Diffuse Color
|
|
||||||
// Light intensity level
|
|
||||||
Intensity float32
|
|
||||||
// Light cone max angle: LIGHT_SPOT
|
|
||||||
ConeAngle float32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *LightData) cptr() *C.LightData {
|
|
||||||
return (*C.LightData)(unsafe.Pointer(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns new LightData
|
|
||||||
func NewLightData(l Light) LightData {
|
|
||||||
return LightData{l.Id, l.Enabled, l.Type, l.Position, l.Target, l.Radius, l.Diffuse, l.Intensity, l.ConeAngle}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns new Light from pointer
|
|
||||||
func NewLightDataFromPointer(ptr unsafe.Pointer) LightData {
|
|
||||||
return *(*LightData)(ptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ray type (useful for raycast)
|
// Ray type (useful for raycast)
|
||||||
type Ray struct {
|
type Ray struct {
|
||||||
// Ray position (origin)
|
// Ray position (origin)
|
||||||
|
@ -345,12 +264,6 @@ func DrawGizmo(position Vector3) {
|
||||||
C.DrawGizmo(*cposition)
|
C.DrawGizmo(*cposition)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw light in 3D world
|
|
||||||
func DrawLight(light Light) {
|
|
||||||
clightdata := NewLightData(light)
|
|
||||||
C.DrawLight(clightdata.cptr())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a 3d model (.OBJ)
|
// Load a 3d model (.OBJ)
|
||||||
func LoadModel(fileName string) Model {
|
func LoadModel(fileName string) Model {
|
||||||
cfileName := C.CString(fileName)
|
cfileName := C.CString(fileName)
|
||||||
|
@ -360,29 +273,6 @@ func LoadModel(fileName string) Model {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a 3d model (from mesh data)
|
|
||||||
func LoadModelEx(data Mesh, dynamic bool) Model {
|
|
||||||
d := 0
|
|
||||||
if dynamic {
|
|
||||||
d = 1
|
|
||||||
}
|
|
||||||
cdata := data.cptr()
|
|
||||||
cdynamic := (C.bool)(d)
|
|
||||||
ret := C.LoadModelEx(*cdata, cdynamic)
|
|
||||||
v := NewModelFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a 3d model from rRES file (raylib Resource)
|
|
||||||
func LoadModelFromRES(rresName string, resId int32) Model {
|
|
||||||
crresName := C.CString(rresName)
|
|
||||||
defer C.free(unsafe.Pointer(crresName))
|
|
||||||
cresId := (C.int)(resId)
|
|
||||||
ret := C.LoadModelFromRES(crresName, cresId)
|
|
||||||
v := NewModelFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a heightmap image as a 3d model
|
// Load a heightmap image as a 3d model
|
||||||
func LoadHeightmap(heightmap *Image, size Vector3) Model {
|
func LoadHeightmap(heightmap *Image, size Vector3) Model {
|
||||||
cheightmap := heightmap.cptr()
|
cheightmap := heightmap.cptr()
|
||||||
|
@ -422,13 +312,6 @@ func LoadDefaultMaterial() Material {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load standard material (uses material attributes and lighting shader)
|
|
||||||
func LoadStandardMaterial() Material {
|
|
||||||
ret := C.LoadStandardMaterial()
|
|
||||||
v := NewMaterialFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unload material textures from VRAM
|
// Unload material textures from VRAM
|
||||||
func UnloadMaterial(material Material) {
|
func UnloadMaterial(material Material) {
|
||||||
cmaterial := material.cptr()
|
cmaterial := material.cptr()
|
||||||
|
|
990
raylib/raylib.h
Normal file
990
raylib/raylib.h
Normal file
|
@ -0,0 +1,990 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib 1.6.0 (www.raylib.com)
|
||||||
|
*
|
||||||
|
* A simple and easy-to-use library to learn videogames programming
|
||||||
|
*
|
||||||
|
* Features:
|
||||||
|
* Library written in plain C code (C99)
|
||||||
|
* Uses PascalCase/camelCase notation
|
||||||
|
* Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0)
|
||||||
|
* Unique OpenGL abstraction layer (usable as standalone module): [rlgl]
|
||||||
|
* Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF)
|
||||||
|
* Multiple textures support, including compressed formats and mipmaps generation
|
||||||
|
* Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps
|
||||||
|
* Powerful math module for Vector, Matrix and Quaternion operations: [raymath]
|
||||||
|
* Audio loading and playing with streaming support and mixing channels [audio]
|
||||||
|
* VR stereo rendering support with configurable HMD device parameters
|
||||||
|
* Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1
|
||||||
|
* Custom color palette for fancy visuals on raywhite background
|
||||||
|
* Minimal external dependencies (GLFW3, OpenGL, OpenAL)
|
||||||
|
* Complete binding for Lua [rlua]
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* GLFW3 (www.glfw.org) for window/context management and input [core]
|
||||||
|
* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) [rlgl]
|
||||||
|
* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA) [textures]
|
||||||
|
* stb_image_write (Sean Barret) for image writting (PNG) [utils]
|
||||||
|
* stb_truetype (Sean Barret) for ttf fonts loading [text]
|
||||||
|
* stb_vorbis (Sean Barret) for ogg audio loading [audio]
|
||||||
|
* jar_xm (Joshua Reisenauer) for XM audio module loading [audio]
|
||||||
|
* jar_mod (Joshua Reisenauer) for MOD audio module loading [audio]
|
||||||
|
* dr_flac (David Reid) for FLAC audio file loading [audio]
|
||||||
|
* OpenAL Soft for audio device/context management [audio]
|
||||||
|
* tinfl for data decompression (DEFLATE algorithm) [utils]
|
||||||
|
*
|
||||||
|
* Some design decisions:
|
||||||
|
* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte)
|
||||||
|
* One custom default font could be loaded automatically when InitWindow() [core]
|
||||||
|
* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads
|
||||||
|
* If using OpenGL 3.3 or ES2, two default shaders could be loaded automatically (internally defined)
|
||||||
|
*
|
||||||
|
* -- LICENSE --
|
||||||
|
*
|
||||||
|
* raylib is 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) 2013-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RAYLIB_H
|
||||||
|
#define RAYLIB_H
|
||||||
|
|
||||||
|
// Choose your platform here or just define it at compile time: -DPLATFORM_DESKTOP
|
||||||
|
//#define PLATFORM_DESKTOP // Windows, Linux or OSX
|
||||||
|
//#define PLATFORM_ANDROID // Android device
|
||||||
|
//#define PLATFORM_RPI // Raspberry Pi
|
||||||
|
//#define PLATFORM_WEB // HTML5 (emscripten, asm.js)
|
||||||
|
//#define RLGL_OCULUS_SUPPORT // Oculus Rift CV1 (complementary to PLATFORM_DESKTOP)
|
||||||
|
|
||||||
|
// Security check in case no PLATFORM_* defined
|
||||||
|
#if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB)
|
||||||
|
#define PLATFORM_DESKTOP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(BUILDING_DLL)
|
||||||
|
#define RLAPI __declspec(dllexport) // We are building raylib as a Win32 DLL
|
||||||
|
#elif defined(_WIN32) && defined(RAYLIB_DLL)
|
||||||
|
#define RLAPI __declspec(dllimport) // We are using raylib as a Win32 DLL
|
||||||
|
#else
|
||||||
|
#define RLAPI // We are building or using raylib as a static library (or Linux shared library)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Some basic Defines
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#ifndef PI
|
||||||
|
#define PI 3.14159265358979323846f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEG2RAD (PI/180.0f)
|
||||||
|
#define RAD2DEG (180.0f/PI)
|
||||||
|
|
||||||
|
// raylib Config Flags
|
||||||
|
#define FLAG_FULLSCREEN_MODE 1
|
||||||
|
#define FLAG_RESIZABLE_WINDOW 2
|
||||||
|
#define FLAG_SHOW_LOGO 4
|
||||||
|
#define FLAG_SHOW_MOUSE_CURSOR 8
|
||||||
|
#define FLAG_CENTERED_MODE 16
|
||||||
|
#define FLAG_MSAA_4X_HINT 32
|
||||||
|
#define FLAG_VSYNC_HINT 64
|
||||||
|
|
||||||
|
// Keyboard Function Keys
|
||||||
|
#define KEY_SPACE 32
|
||||||
|
#define KEY_ESCAPE 256
|
||||||
|
#define KEY_ENTER 257
|
||||||
|
#define KEY_BACKSPACE 259
|
||||||
|
#define KEY_RIGHT 262
|
||||||
|
#define KEY_LEFT 263
|
||||||
|
#define KEY_DOWN 264
|
||||||
|
#define KEY_UP 265
|
||||||
|
#define KEY_F1 290
|
||||||
|
#define KEY_F2 291
|
||||||
|
#define KEY_F3 292
|
||||||
|
#define KEY_F4 293
|
||||||
|
#define KEY_F5 294
|
||||||
|
#define KEY_F6 295
|
||||||
|
#define KEY_F7 296
|
||||||
|
#define KEY_F8 297
|
||||||
|
#define KEY_F9 298
|
||||||
|
#define KEY_F10 299
|
||||||
|
#define KEY_F11 300
|
||||||
|
#define KEY_F12 301
|
||||||
|
#define KEY_LEFT_SHIFT 340
|
||||||
|
#define KEY_LEFT_CONTROL 341
|
||||||
|
#define KEY_LEFT_ALT 342
|
||||||
|
#define KEY_RIGHT_SHIFT 344
|
||||||
|
#define KEY_RIGHT_CONTROL 345
|
||||||
|
#define KEY_RIGHT_ALT 346
|
||||||
|
|
||||||
|
// Keyboard Alpha Numeric Keys
|
||||||
|
#define KEY_ZERO 48
|
||||||
|
#define KEY_ONE 49
|
||||||
|
#define KEY_TWO 50
|
||||||
|
#define KEY_THREE 51
|
||||||
|
#define KEY_FOUR 52
|
||||||
|
#define KEY_FIVE 53
|
||||||
|
#define KEY_SIX 54
|
||||||
|
#define KEY_SEVEN 55
|
||||||
|
#define KEY_EIGHT 56
|
||||||
|
#define KEY_NINE 57
|
||||||
|
#define KEY_A 65
|
||||||
|
#define KEY_B 66
|
||||||
|
#define KEY_C 67
|
||||||
|
#define KEY_D 68
|
||||||
|
#define KEY_E 69
|
||||||
|
#define KEY_F 70
|
||||||
|
#define KEY_G 71
|
||||||
|
#define KEY_H 72
|
||||||
|
#define KEY_I 73
|
||||||
|
#define KEY_J 74
|
||||||
|
#define KEY_K 75
|
||||||
|
#define KEY_L 76
|
||||||
|
#define KEY_M 77
|
||||||
|
#define KEY_N 78
|
||||||
|
#define KEY_O 79
|
||||||
|
#define KEY_P 80
|
||||||
|
#define KEY_Q 81
|
||||||
|
#define KEY_R 82
|
||||||
|
#define KEY_S 83
|
||||||
|
#define KEY_T 84
|
||||||
|
#define KEY_U 85
|
||||||
|
#define KEY_V 86
|
||||||
|
#define KEY_W 87
|
||||||
|
#define KEY_X 88
|
||||||
|
#define KEY_Y 89
|
||||||
|
#define KEY_Z 90
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
// Android Physical Buttons
|
||||||
|
#define KEY_BACK 4
|
||||||
|
#define KEY_MENU 82
|
||||||
|
#define KEY_VOLUME_UP 24
|
||||||
|
#define KEY_VOLUME_DOWN 25
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Mouse Buttons
|
||||||
|
#define MOUSE_LEFT_BUTTON 0
|
||||||
|
#define MOUSE_RIGHT_BUTTON 1
|
||||||
|
#define MOUSE_MIDDLE_BUTTON 2
|
||||||
|
|
||||||
|
// Touch points registered
|
||||||
|
#define MAX_TOUCH_POINTS 2
|
||||||
|
|
||||||
|
// Gamepad Number
|
||||||
|
#define GAMEPAD_PLAYER1 0
|
||||||
|
#define GAMEPAD_PLAYER2 1
|
||||||
|
#define GAMEPAD_PLAYER3 2
|
||||||
|
#define GAMEPAD_PLAYER4 3
|
||||||
|
|
||||||
|
// Gamepad Buttons/Axis
|
||||||
|
|
||||||
|
// PS3 USB Controller Buttons
|
||||||
|
#define GAMEPAD_PS3_BUTTON_TRIANGLE 0
|
||||||
|
#define GAMEPAD_PS3_BUTTON_CIRCLE 1
|
||||||
|
#define GAMEPAD_PS3_BUTTON_CROSS 2
|
||||||
|
#define GAMEPAD_PS3_BUTTON_SQUARE 3
|
||||||
|
#define GAMEPAD_PS3_BUTTON_L1 6
|
||||||
|
#define GAMEPAD_PS3_BUTTON_R1 7
|
||||||
|
#define GAMEPAD_PS3_BUTTON_L2 4
|
||||||
|
#define GAMEPAD_PS3_BUTTON_R2 5
|
||||||
|
#define GAMEPAD_PS3_BUTTON_START 8
|
||||||
|
#define GAMEPAD_PS3_BUTTON_SELECT 9
|
||||||
|
#define GAMEPAD_PS3_BUTTON_UP 24
|
||||||
|
#define GAMEPAD_PS3_BUTTON_RIGHT 25
|
||||||
|
#define GAMEPAD_PS3_BUTTON_DOWN 26
|
||||||
|
#define GAMEPAD_PS3_BUTTON_LEFT 27
|
||||||
|
#define GAMEPAD_PS3_BUTTON_PS 12
|
||||||
|
|
||||||
|
// PS3 USB Controller Axis
|
||||||
|
#define GAMEPAD_PS3_AXIS_LEFT_X 0
|
||||||
|
#define GAMEPAD_PS3_AXIS_LEFT_Y 1
|
||||||
|
#define GAMEPAD_PS3_AXIS_RIGHT_X 2
|
||||||
|
#define GAMEPAD_PS3_AXIS_RIGHT_Y 5
|
||||||
|
#define GAMEPAD_PS3_AXIS_L2 3 // [1..-1] (pressure-level)
|
||||||
|
#define GAMEPAD_PS3_AXIS_R2 4 // [1..-1] (pressure-level)
|
||||||
|
|
||||||
|
// Xbox360 USB Controller Buttons
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_A 0
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_B 1
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_X 2
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_Y 3
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_LB 4
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_RB 5
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_SELECT 6
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_START 7
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_UP 10
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_RIGHT 11
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_DOWN 12
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_LEFT 13
|
||||||
|
#define GAMEPAD_XBOX_BUTTON_HOME 8
|
||||||
|
|
||||||
|
// Xbox360 USB Controller Axis
|
||||||
|
// NOTE: For Raspberry Pi, axis must be reconfigured
|
||||||
|
#if defined(PLATFORM_RPI)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_LEFT_X 0 // [-1..1] (left->right)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1 // [-1..1] (up->down)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_RIGHT_X 3 // [-1..1] (left->right)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 4 // [-1..1] (up->down)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_LT 2 // [-1..1] (pressure-level)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_RT 5 // [-1..1] (pressure-level)
|
||||||
|
#else
|
||||||
|
#define GAMEPAD_XBOX_AXIS_LEFT_X 0 // [-1..1] (left->right)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_LEFT_Y 1 // [1..-1] (up->down)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_RIGHT_X 2 // [-1..1] (left->right)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_RIGHT_Y 3 // [1..-1] (up->down)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_LT 4 // [-1..1] (pressure-level)
|
||||||
|
#define GAMEPAD_XBOX_AXIS_RT 5 // [-1..1] (pressure-level)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: MSC C++ compiler does not support compound literals (C99 feature)
|
||||||
|
// Plain structures in C++ (without constructors) can be initialized from { } initializers.
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define CLITERAL
|
||||||
|
#else
|
||||||
|
#define CLITERAL (Color)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Some Basic Colors
|
||||||
|
// NOTE: Custom raylib color palette for amazing visuals on WHITE background
|
||||||
|
#define LIGHTGRAY CLITERAL{ 200, 200, 200, 255 } // Light Gray
|
||||||
|
#define GRAY CLITERAL{ 130, 130, 130, 255 } // Gray
|
||||||
|
#define DARKGRAY CLITERAL{ 80, 80, 80, 255 } // Dark Gray
|
||||||
|
#define YELLOW CLITERAL{ 253, 249, 0, 255 } // Yellow
|
||||||
|
#define GOLD CLITERAL{ 255, 203, 0, 255 } // Gold
|
||||||
|
#define ORANGE CLITERAL{ 255, 161, 0, 255 } // Orange
|
||||||
|
#define PINK CLITERAL{ 255, 109, 194, 255 } // Pink
|
||||||
|
#define RED CLITERAL{ 230, 41, 55, 255 } // Red
|
||||||
|
#define MAROON CLITERAL{ 190, 33, 55, 255 } // Maroon
|
||||||
|
#define GREEN CLITERAL{ 0, 228, 48, 255 } // Green
|
||||||
|
#define LIME CLITERAL{ 0, 158, 47, 255 } // Lime
|
||||||
|
#define DARKGREEN CLITERAL{ 0, 117, 44, 255 } // Dark Green
|
||||||
|
#define SKYBLUE CLITERAL{ 102, 191, 255, 255 } // Sky Blue
|
||||||
|
#define BLUE CLITERAL{ 0, 121, 241, 255 } // Blue
|
||||||
|
#define DARKBLUE CLITERAL{ 0, 82, 172, 255 } // Dark Blue
|
||||||
|
#define PURPLE CLITERAL{ 200, 122, 255, 255 } // Purple
|
||||||
|
#define VIOLET CLITERAL{ 135, 60, 190, 255 } // Violet
|
||||||
|
#define DARKPURPLE CLITERAL{ 112, 31, 126, 255 } // Dark Purple
|
||||||
|
#define BEIGE CLITERAL{ 211, 176, 131, 255 } // Beige
|
||||||
|
#define BROWN CLITERAL{ 127, 106, 79, 255 } // Brown
|
||||||
|
#define DARKBROWN CLITERAL{ 76, 63, 47, 255 } // Dark Brown
|
||||||
|
|
||||||
|
#define WHITE CLITERAL{ 255, 255, 255, 255 } // White
|
||||||
|
#define BLACK CLITERAL{ 0, 0, 0, 255 } // Black
|
||||||
|
#define BLANK CLITERAL{ 0, 0, 0, 0 } // Blank (Transparent)
|
||||||
|
#define MAGENTA CLITERAL{ 255, 0, 255, 255 } // Magenta
|
||||||
|
#define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// Boolean type
|
||||||
|
#ifndef __APPLE__
|
||||||
|
#if !defined(_STDBOOL_H)
|
||||||
|
typedef enum { false, true } bool;
|
||||||
|
#define _STDBOOL_H
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Vector2 type
|
||||||
|
typedef struct Vector2 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} Vector2;
|
||||||
|
|
||||||
|
// Vector3 type
|
||||||
|
typedef struct Vector3 {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} Vector3;
|
||||||
|
|
||||||
|
// Matrix type (OpenGL style 4x4 - right handed, column major)
|
||||||
|
typedef struct Matrix {
|
||||||
|
float m0, m4, m8, m12;
|
||||||
|
float m1, m5, m9, m13;
|
||||||
|
float m2, m6, m10, m14;
|
||||||
|
float m3, m7, m11, m15;
|
||||||
|
} Matrix;
|
||||||
|
|
||||||
|
// Color type, RGBA (32bit)
|
||||||
|
typedef struct Color {
|
||||||
|
unsigned char r;
|
||||||
|
unsigned char g;
|
||||||
|
unsigned char b;
|
||||||
|
unsigned char a;
|
||||||
|
} Color;
|
||||||
|
|
||||||
|
// Rectangle type
|
||||||
|
typedef struct Rectangle {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
} Rectangle;
|
||||||
|
|
||||||
|
// Image type, bpp always RGBA (32bit)
|
||||||
|
// NOTE: Data stored in CPU memory (RAM)
|
||||||
|
typedef struct Image {
|
||||||
|
void *data; // Image raw data
|
||||||
|
int width; // Image base width
|
||||||
|
int height; // Image base height
|
||||||
|
int mipmaps; // Mipmap levels, 1 by default
|
||||||
|
int format; // Data format (TextureFormat type)
|
||||||
|
} Image;
|
||||||
|
|
||||||
|
// Texture2D type, bpp always RGBA (32bit)
|
||||||
|
// NOTE: Data stored in GPU memory
|
||||||
|
typedef struct Texture2D {
|
||||||
|
unsigned int id; // OpenGL texture id
|
||||||
|
int width; // Texture base width
|
||||||
|
int height; // Texture base height
|
||||||
|
int mipmaps; // Mipmap levels, 1 by default
|
||||||
|
int format; // Data format (TextureFormat type)
|
||||||
|
} Texture2D;
|
||||||
|
|
||||||
|
// RenderTexture2D type, for texture rendering
|
||||||
|
typedef struct RenderTexture2D {
|
||||||
|
unsigned int id; // OpenGL Framebuffer Object (FBO) id
|
||||||
|
Texture2D texture; // Color buffer attachment texture
|
||||||
|
Texture2D depth; // Depth buffer attachment texture
|
||||||
|
} RenderTexture2D;
|
||||||
|
|
||||||
|
// SpriteFont type, includes texture and charSet array data
|
||||||
|
typedef struct SpriteFont {
|
||||||
|
Texture2D texture; // Font texture
|
||||||
|
int size; // Base size (default chars height)
|
||||||
|
int numChars; // Number of characters
|
||||||
|
int *charValues; // Characters values array
|
||||||
|
Rectangle *charRecs; // Characters rectangles within the texture
|
||||||
|
Vector2 *charOffsets; // Characters offsets (on drawing)
|
||||||
|
int *charAdvanceX; // Characters x advance (on drawing)
|
||||||
|
} SpriteFont;
|
||||||
|
|
||||||
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
|
typedef struct Camera {
|
||||||
|
Vector3 position; // Camera position
|
||||||
|
Vector3 target; // Camera target it looks-at
|
||||||
|
Vector3 up; // Camera up vector (rotation over its axis)
|
||||||
|
float fovy; // Camera field-of-view apperture in Y (degrees)
|
||||||
|
} Camera;
|
||||||
|
|
||||||
|
// Camera2D type, defines a 2d camera
|
||||||
|
typedef struct Camera2D {
|
||||||
|
Vector2 offset; // Camera offset (displacement from target)
|
||||||
|
Vector2 target; // Camera target (rotation and zoom origin)
|
||||||
|
float rotation; // Camera rotation in degrees
|
||||||
|
float zoom; // Camera zoom (scaling), should be 1.0f by default
|
||||||
|
} Camera2D;
|
||||||
|
|
||||||
|
// Bounding box type
|
||||||
|
typedef struct BoundingBox {
|
||||||
|
Vector3 min; // minimum vertex box-corner
|
||||||
|
Vector3 max; // maximum vertex box-corner
|
||||||
|
} BoundingBox;
|
||||||
|
|
||||||
|
// Vertex data definning a mesh
|
||||||
|
typedef struct Mesh {
|
||||||
|
int vertexCount; // number of vertices stored in arrays
|
||||||
|
int triangleCount; // number of triangles stored (indexed or not)
|
||||||
|
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||||
|
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||||
|
float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||||
|
float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||||
|
float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
|
||||||
|
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||||
|
unsigned short *indices;// vertex indices (in case vertex data comes indexed)
|
||||||
|
|
||||||
|
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||||
|
unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
|
||||||
|
} Mesh;
|
||||||
|
|
||||||
|
// Shader type (generic shader)
|
||||||
|
typedef struct Shader {
|
||||||
|
unsigned int id; // Shader program id
|
||||||
|
|
||||||
|
// Vertex attributes locations (default locations)
|
||||||
|
int vertexLoc; // Vertex attribute location point (default-location = 0)
|
||||||
|
int texcoordLoc; // Texcoord attribute location point (default-location = 1)
|
||||||
|
int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5)
|
||||||
|
int normalLoc; // Normal attribute location point (default-location = 2)
|
||||||
|
int tangentLoc; // Tangent attribute location point (default-location = 4)
|
||||||
|
int colorLoc; // Color attibute location point (default-location = 3)
|
||||||
|
|
||||||
|
// Uniform locations
|
||||||
|
int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader)
|
||||||
|
int colDiffuseLoc; // Diffuse color uniform location point (fragment shader)
|
||||||
|
int colAmbientLoc; // Ambient color uniform location point (fragment shader)
|
||||||
|
int colSpecularLoc; // Specular color uniform location point (fragment shader)
|
||||||
|
|
||||||
|
// Texture map locations (generic for any kind of map)
|
||||||
|
int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0)
|
||||||
|
int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1)
|
||||||
|
int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2)
|
||||||
|
} Shader;
|
||||||
|
|
||||||
|
// Material type
|
||||||
|
typedef struct Material {
|
||||||
|
Shader shader; // Standard shader (supports 3 map textures)
|
||||||
|
|
||||||
|
Texture2D texDiffuse; // Diffuse texture (binded to shader mapTexture0Loc)
|
||||||
|
Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc)
|
||||||
|
Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc)
|
||||||
|
|
||||||
|
Color colDiffuse; // Diffuse color
|
||||||
|
Color colAmbient; // Ambient color
|
||||||
|
Color colSpecular; // Specular color
|
||||||
|
|
||||||
|
float glossiness; // Glossiness level (Ranges from 0 to 1000)
|
||||||
|
} Material;
|
||||||
|
|
||||||
|
// Model type
|
||||||
|
typedef struct Model {
|
||||||
|
Mesh mesh; // Vertex data buffers (RAM and VRAM)
|
||||||
|
Matrix transform; // Local transform matrix
|
||||||
|
Material material; // Shader and textures data
|
||||||
|
} Model;
|
||||||
|
|
||||||
|
// Ray type (useful for raycast)
|
||||||
|
typedef struct Ray {
|
||||||
|
Vector3 position; // Ray position (origin)
|
||||||
|
Vector3 direction; // Ray direction
|
||||||
|
} Ray;
|
||||||
|
|
||||||
|
// Information returned from a raycast
|
||||||
|
typedef struct RayHitInfo {
|
||||||
|
bool hit; // Did the ray hit something?
|
||||||
|
float distance; // Distance to nearest hit
|
||||||
|
Vector3 hitPosition; // Position of nearest hit
|
||||||
|
Vector3 hitNormal; // Surface normal of hit
|
||||||
|
} RayHitInfo;
|
||||||
|
|
||||||
|
// Wave type, defines audio wave data
|
||||||
|
typedef struct Wave {
|
||||||
|
unsigned int sampleCount; // Number of samples
|
||||||
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
|
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
||||||
|
void *data; // Buffer data pointer
|
||||||
|
} Wave;
|
||||||
|
|
||||||
|
// Sound source type
|
||||||
|
typedef struct Sound {
|
||||||
|
unsigned int source; // OpenAL audio source id
|
||||||
|
unsigned int buffer; // OpenAL audio buffer id
|
||||||
|
int format; // OpenAL audio format specifier
|
||||||
|
} Sound;
|
||||||
|
|
||||||
|
// Music type (file streaming from memory)
|
||||||
|
// NOTE: Anything longer than ~10 seconds should be streamed
|
||||||
|
typedef struct MusicData *Music;
|
||||||
|
|
||||||
|
// Audio stream type
|
||||||
|
// NOTE: Useful to create custom audio streams not bound to a specific file
|
||||||
|
typedef struct AudioStream {
|
||||||
|
unsigned int sampleRate; // Frequency (samples per second)
|
||||||
|
unsigned int sampleSize; // Bit depth (bits per sample): 8, 16, 32 (24 not supported)
|
||||||
|
unsigned int channels; // Number of channels (1-mono, 2-stereo)
|
||||||
|
|
||||||
|
int format; // OpenAL audio format specifier
|
||||||
|
unsigned int source; // OpenAL audio source id
|
||||||
|
unsigned int buffers[2]; // OpenAL audio buffers (double buffering)
|
||||||
|
} AudioStream;
|
||||||
|
|
||||||
|
// Texture formats
|
||||||
|
// NOTE: Support depends on OpenGL version and platform
|
||||||
|
typedef enum {
|
||||||
|
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||||
|
UNCOMPRESSED_GRAY_ALPHA, // 16 bpp (2 channels)
|
||||||
|
UNCOMPRESSED_R5G6B5, // 16 bpp
|
||||||
|
UNCOMPRESSED_R8G8B8, // 24 bpp
|
||||||
|
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||||
|
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||||
|
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||||
|
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
|
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
|
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_DXT5_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_ETC1_RGB, // 4 bpp
|
||||||
|
COMPRESSED_ETC2_RGB, // 4 bpp
|
||||||
|
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_PVRT_RGB, // 4 bpp
|
||||||
|
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||||
|
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||||
|
} TextureFormat;
|
||||||
|
|
||||||
|
// Texture parameters: filter mode
|
||||||
|
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||||
|
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||||
|
typedef enum {
|
||||||
|
FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||||
|
FILTER_BILINEAR, // Linear filtering
|
||||||
|
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||||
|
FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
|
||||||
|
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
|
||||||
|
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
|
||||||
|
} TextureFilterMode;
|
||||||
|
|
||||||
|
// Texture parameters: wrap mode
|
||||||
|
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
|
||||||
|
|
||||||
|
// Color blending modes (pre-defined)
|
||||||
|
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
|
||||||
|
|
||||||
|
// Gestures type
|
||||||
|
// NOTE: It could be used as flags to enable only some gestures
|
||||||
|
typedef enum {
|
||||||
|
GESTURE_NONE = 0,
|
||||||
|
GESTURE_TAP = 1,
|
||||||
|
GESTURE_DOUBLETAP = 2,
|
||||||
|
GESTURE_HOLD = 4,
|
||||||
|
GESTURE_DRAG = 8,
|
||||||
|
GESTURE_SWIPE_RIGHT = 16,
|
||||||
|
GESTURE_SWIPE_LEFT = 32,
|
||||||
|
GESTURE_SWIPE_UP = 64,
|
||||||
|
GESTURE_SWIPE_DOWN = 128,
|
||||||
|
GESTURE_PINCH_IN = 256,
|
||||||
|
GESTURE_PINCH_OUT = 512
|
||||||
|
} Gestures;
|
||||||
|
|
||||||
|
// Camera system modes
|
||||||
|
typedef enum {
|
||||||
|
CAMERA_CUSTOM = 0,
|
||||||
|
CAMERA_FREE,
|
||||||
|
CAMERA_ORBITAL,
|
||||||
|
CAMERA_FIRST_PERSON,
|
||||||
|
CAMERA_THIRD_PERSON
|
||||||
|
} CameraMode;
|
||||||
|
|
||||||
|
// Head Mounted Display devices
|
||||||
|
typedef enum {
|
||||||
|
HMD_DEFAULT_DEVICE = 0,
|
||||||
|
HMD_OCULUS_RIFT_DK2,
|
||||||
|
HMD_OCULUS_RIFT_CV1,
|
||||||
|
HMD_VALVE_HTC_VIVE,
|
||||||
|
HMD_SAMSUNG_GEAR_VR,
|
||||||
|
HMD_GOOGLE_CARDBOARD,
|
||||||
|
HMD_SONY_PLAYSTATION_VR,
|
||||||
|
HMD_RAZER_OSVR,
|
||||||
|
HMD_FOVE_VR,
|
||||||
|
} VrDevice;
|
||||||
|
|
||||||
|
// rRES data returned when reading a resource, it contains all required data for user (24 byte)
|
||||||
|
typedef struct {
|
||||||
|
unsigned int type; // Resource type (4 byte)
|
||||||
|
|
||||||
|
unsigned int param1; // Resouce parameter 1 (4 byte)
|
||||||
|
unsigned int param2; // Resouce parameter 2 (4 byte)
|
||||||
|
unsigned int param3; // Resouce parameter 3 (4 byte)
|
||||||
|
unsigned int param4; // Resouce parameter 4 (4 byte)
|
||||||
|
|
||||||
|
void *data; // Resource data pointer (4 byte)
|
||||||
|
} RRESData;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RRES_RAW = 0,
|
||||||
|
RRES_IMAGE,
|
||||||
|
RRES_WAVE,
|
||||||
|
RRES_VERTEX,
|
||||||
|
RRES_TEXT
|
||||||
|
} RRESDataType;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// It's lonely here...
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Window and Graphics Device Functions (Module: core)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
RLAPI void InitWindow(int width, int height, void *state); // Init Android Activity and OpenGL Graphics (struct android_app)
|
||||||
|
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||||
|
RLAPI void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RLAPI void CloseWindow(void); // Close Window and Terminate Context
|
||||||
|
RLAPI bool WindowShouldClose(void); // Detect if KEY_ESCAPE pressed or Close icon pressed
|
||||||
|
RLAPI bool IsWindowMinimized(void); // Detect if window has been minimized (or lost focus)
|
||||||
|
RLAPI void ToggleFullscreen(void); // Fullscreen toggle (only PLATFORM_DESKTOP)
|
||||||
|
RLAPI int GetScreenWidth(void); // Get current screen width
|
||||||
|
RLAPI int GetScreenHeight(void); // Get current screen height
|
||||||
|
|
||||||
|
#if !defined(PLATFORM_ANDROID)
|
||||||
|
RLAPI void ShowCursor(void); // Shows cursor
|
||||||
|
RLAPI void HideCursor(void); // Hides cursor
|
||||||
|
RLAPI bool IsCursorHidden(void); // Returns true if cursor is not visible
|
||||||
|
RLAPI void EnableCursor(void); // Enables cursor
|
||||||
|
RLAPI void DisableCursor(void); // Disables cursor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RLAPI void ClearBackground(Color color); // Sets Background Color
|
||||||
|
RLAPI void BeginDrawing(void); // Setup drawing canvas to start drawing
|
||||||
|
RLAPI void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering)
|
||||||
|
|
||||||
|
RLAPI void Begin2dMode(Camera2D camera); // Initialize 2D mode with custom camera
|
||||||
|
RLAPI void End2dMode(void); // Ends 2D mode custom camera usage
|
||||||
|
RLAPI void Begin3dMode(Camera camera); // Initializes 3D mode for drawing (Camera setup)
|
||||||
|
RLAPI void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode
|
||||||
|
RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
|
||||||
|
RLAPI void EndTextureMode(void); // Ends drawing to render texture
|
||||||
|
|
||||||
|
RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
||||||
|
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position
|
||||||
|
RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
|
||||||
|
|
||||||
|
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
|
RLAPI int GetFPS(void); // Returns current FPS (rounded value)
|
||||||
|
RLAPI float GetFrameTime(void); // Returns time in seconds for one frame (rounded value)
|
||||||
|
|
||||||
|
RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
|
||||||
|
RLAPI int GetHexValue(Color color); // Returns hexadecimal value for a Color
|
||||||
|
RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes
|
||||||
|
RLAPI float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array
|
||||||
|
RLAPI float *MatrixToFloat(Matrix mat); // Converts Matrix to float array
|
||||||
|
|
||||||
|
RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
||||||
|
RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
||||||
|
|
||||||
|
RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags
|
||||||
|
RLAPI void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
|
||||||
|
|
||||||
|
RLAPI bool IsFileDropped(void); // Check if a file have been dropped into window
|
||||||
|
RLAPI char **GetDroppedFiles(int *count); // Retrieve dropped files into window
|
||||||
|
RLAPI void ClearDroppedFiles(void); // Clear dropped files paths buffer
|
||||||
|
|
||||||
|
RLAPI void StorageSaveValue(int position, int value); // Storage save integer value (to defined position)
|
||||||
|
RLAPI int StorageLoadValue(int position); // Storage load integer value (from defined position)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Input Handling Functions (Module: core)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI bool IsKeyPressed(int key); // Detect if a key has been pressed once
|
||||||
|
RLAPI bool IsKeyDown(int key); // Detect if a key is being pressed
|
||||||
|
RLAPI bool IsKeyReleased(int key); // Detect if a key has been released once
|
||||||
|
RLAPI bool IsKeyUp(int key); // Detect if a key is NOT being pressed
|
||||||
|
RLAPI int GetKeyPressed(void); // Get latest key pressed
|
||||||
|
RLAPI void SetExitKey(int key); // Set a custom key to exit program (default is ESC)
|
||||||
|
|
||||||
|
RLAPI bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
|
||||||
|
RLAPI bool IsGamepadName(int gamepad, const char *name); // Check gamepad name (if available)
|
||||||
|
RLAPI const char *GetGamepadName(int gamepad); // Return gamepad internal name id
|
||||||
|
RLAPI bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once
|
||||||
|
RLAPI bool IsGamepadButtonDown(int gamepad, int button); // Detect if a gamepad button is being pressed
|
||||||
|
RLAPI bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad button has been released once
|
||||||
|
RLAPI bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed
|
||||||
|
RLAPI int GetGamepadButtonPressed(void); // Get the last gamepad button pressed
|
||||||
|
RLAPI int GetGamepadAxisCount(int gamepad); // Return gamepad axis count for a gamepad
|
||||||
|
RLAPI float GetGamepadAxisMovement(int gamepad, int axis); // Return axis movement value for a gamepad axis
|
||||||
|
|
||||||
|
RLAPI bool IsMouseButtonPressed(int button); // Detect if a mouse button has been pressed once
|
||||||
|
RLAPI bool IsMouseButtonDown(int button); // Detect if a mouse button is being pressed
|
||||||
|
RLAPI bool IsMouseButtonReleased(int button); // Detect if a mouse button has been released once
|
||||||
|
RLAPI bool IsMouseButtonUp(int button); // Detect if a mouse button is NOT being pressed
|
||||||
|
RLAPI int GetMouseX(void); // Returns mouse position X
|
||||||
|
RLAPI int GetMouseY(void); // Returns mouse position Y
|
||||||
|
RLAPI Vector2 GetMousePosition(void); // Returns mouse position XY
|
||||||
|
RLAPI void SetMousePosition(Vector2 position); // Set mouse position XY
|
||||||
|
RLAPI int GetMouseWheelMove(void); // Returns mouse wheel movement Y
|
||||||
|
|
||||||
|
RLAPI int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size)
|
||||||
|
RLAPI int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size)
|
||||||
|
RLAPI Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Gestures and Touch Handling Functions (Module: gestures)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags
|
||||||
|
RLAPI bool IsGestureDetected(int gesture); // Check if a gesture have been detected
|
||||||
|
RLAPI int GetGestureDetected(void); // Get latest detected gesture
|
||||||
|
RLAPI int GetTouchPointsCount(void); // Get touch points count
|
||||||
|
RLAPI float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds
|
||||||
|
RLAPI Vector2 GetGestureDragVector(void); // Get gesture drag vector
|
||||||
|
RLAPI float GetGestureDragAngle(void); // Get gesture drag angle
|
||||||
|
RLAPI Vector2 GetGesturePinchVector(void); // Get gesture pinch delta
|
||||||
|
RLAPI float GetGesturePinchAngle(void); // Get gesture pinch angle
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Camera System Functions (Module: camera)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available)
|
||||||
|
RLAPI void UpdateCamera(Camera *camera); // Update camera position for selected mode
|
||||||
|
|
||||||
|
RLAPI void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera)
|
||||||
|
RLAPI void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera)
|
||||||
|
RLAPI void SetCameraSmoothZoomControl(int szKey); // Set camera smooth zoom key to combine with mouse (free camera)
|
||||||
|
RLAPI void SetCameraMoveControls(int frontKey, int backKey,
|
||||||
|
int rightKey, int leftKey,
|
||||||
|
int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Basic Shapes Drawing Functions (Module: shapes)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI void DrawPixel(int posX, int posY, Color color); // Draw a pixel
|
||||||
|
RLAPI void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version)
|
||||||
|
RLAPI void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
|
||||||
|
RLAPI void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (Vector version)
|
||||||
|
RLAPI void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
|
||||||
|
RLAPI void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
|
||||||
|
RLAPI void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
|
||||||
|
RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
|
||||||
|
RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
|
||||||
|
RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
|
||||||
|
RLAPI void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle
|
||||||
|
RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
|
||||||
|
RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
|
||||||
|
RLAPI void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle
|
||||||
|
RLAPI void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline
|
||||||
|
RLAPI void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color); // Draw a regular polygon (Vector version)
|
||||||
|
RLAPI void DrawPolyEx(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points
|
||||||
|
RLAPI void DrawPolyExLines(Vector2 *points, int numPoints, Color color); // Draw polygon lines
|
||||||
|
|
||||||
|
RLAPI bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); // Check collision between two rectangles
|
||||||
|
RLAPI bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2); // Check collision between two circles
|
||||||
|
RLAPI bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); // Check collision between circle and rectangle
|
||||||
|
RLAPI Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2); // Get collision rectangle for two rectangles collision
|
||||||
|
RLAPI bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle
|
||||||
|
RLAPI bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); // Check if point is inside circle
|
||||||
|
RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3); // Check if point is inside a triangle
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Texture Loading and Drawing Functions (Module: textures)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM)
|
||||||
|
RLAPI Image LoadImageEx(Color *pixels, int width, int height); // Load image from Color array data (RGBA - 32bit)
|
||||||
|
RLAPI Image LoadImagePro(void *data, int width, int height, int format); // Load image from raw data with parameters
|
||||||
|
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
||||||
|
RLAPI Texture2D LoadTexture(const char *fileName); // Load texture from file into GPU memory (VRAM)
|
||||||
|
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
|
||||||
|
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
|
||||||
|
RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||||
|
RLAPI void UnloadTexture(Texture2D texture); // Unload texture from GPU memory (VRAM)
|
||||||
|
RLAPI void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory (VRAM)
|
||||||
|
RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
|
||||||
|
RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
|
||||||
|
RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data
|
||||||
|
RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
||||||
|
RLAPI void ImageFormat(Image *image, int newFormat); // Convert image data to desired format
|
||||||
|
RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image
|
||||||
|
RLAPI void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering)
|
||||||
|
RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations)
|
||||||
|
RLAPI void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle
|
||||||
|
RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering)
|
||||||
|
RLAPI void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm)
|
||||||
|
RLAPI Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font)
|
||||||
|
RLAPI Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing, Color tint); // Create an image from text (custom sprite font)
|
||||||
|
RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image
|
||||||
|
RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color); // Draw text (default font) within an image (destination)
|
||||||
|
RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text,
|
||||||
|
float fontSize, int spacing, Color color); // Draw text (custom sprite font) within an image (destination)
|
||||||
|
RLAPI void ImageFlipVertical(Image *image); // Flip image vertically
|
||||||
|
RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally
|
||||||
|
RLAPI void ImageColorTint(Image *image, Color color); // Modify image color: tint
|
||||||
|
RLAPI void ImageColorInvert(Image *image); // Modify image color: invert
|
||||||
|
RLAPI void ImageColorGrayscale(Image *image); // Modify image color: grayscale
|
||||||
|
RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100)
|
||||||
|
RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255)
|
||||||
|
RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture
|
||||||
|
RLAPI void SetTextureFilter(Texture2D texture, int filterMode); // Set texture scaling filter mode
|
||||||
|
RLAPI void SetTextureWrap(Texture2D texture, int wrapMode); // Set texture wrapping mode
|
||||||
|
|
||||||
|
RLAPI void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
|
||||||
|
RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
|
||||||
|
RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
|
||||||
|
RLAPI void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle
|
||||||
|
RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, // Draw a part of a texture defined by a rectangle with 'pro' parameters
|
||||||
|
float rotation, Color tint);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Font Loading and Text Drawing Functions (Module: text)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont
|
||||||
|
RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM)
|
||||||
|
RLAPI SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars); // Load SpriteFont from TTF font file with generation parameters
|
||||||
|
RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory (VRAM)
|
||||||
|
|
||||||
|
RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font)
|
||||||
|
RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters
|
||||||
|
float fontSize, int spacing, Color tint);
|
||||||
|
RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font
|
||||||
|
RLAPI Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing); // Measure string size for SpriteFont
|
||||||
|
|
||||||
|
RLAPI void DrawFPS(int posX, int posY); // Shows current FPS on top-left corner
|
||||||
|
RLAPI const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
|
||||||
|
RLAPI const char *SubText(const char *text, int position, int length); // Get a piece of a text string
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Basic 3d Shapes Drawing Functions (Module: models)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space
|
||||||
|
RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space
|
||||||
|
RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube
|
||||||
|
RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
|
||||||
|
RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires
|
||||||
|
RLAPI void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color); // Draw cube textured
|
||||||
|
RLAPI void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
|
||||||
|
RLAPI void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
|
||||||
|
RLAPI void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere wires
|
||||||
|
RLAPI void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
|
||||||
|
RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
|
||||||
|
RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ
|
||||||
|
RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line
|
||||||
|
RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
|
||||||
|
RLAPI void DrawGizmo(Vector3 position); // Draw simple gizmo
|
||||||
|
//DrawTorus(), DrawTeapot() could be useful?
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Model 3d Loading and Drawing Functions (Module: models)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file
|
||||||
|
RLAPI Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData); // Load mesh from vertex data
|
||||||
|
RLAPI Model LoadModel(const char *fileName); // Load model from file
|
||||||
|
RLAPI Model LoadModelFromMesh(Mesh data, bool dynamic); // Load model from mesh data
|
||||||
|
RLAPI Model LoadHeightmap(Image heightmap, Vector3 size); // Load heightmap model from image data
|
||||||
|
RLAPI Model LoadCubicmap(Image cubicmap); // Load cubes-based map model from image data
|
||||||
|
RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM)
|
||||||
|
RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM)
|
||||||
|
|
||||||
|
RLAPI Material LoadMaterial(const char *fileName); // Load material from file
|
||||||
|
RLAPI Material LoadMaterialEx(Shader shader, Texture2D diffuse, Color color); // Load material from basic shading data
|
||||||
|
RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
|
||||||
|
RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM)
|
||||||
|
|
||||||
|
RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
|
||||||
|
RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis,
|
||||||
|
float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||||
|
RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set)
|
||||||
|
RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis,
|
||||||
|
float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters
|
||||||
|
RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires)
|
||||||
|
|
||||||
|
RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture
|
||||||
|
RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec,
|
||||||
|
Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
|
||||||
|
|
||||||
|
RLAPI BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits
|
||||||
|
RLAPI bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres
|
||||||
|
RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Detect collision between two bounding boxes
|
||||||
|
RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere
|
||||||
|
RLAPI bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius); // Detect collision between ray and sphere
|
||||||
|
RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius,
|
||||||
|
Vector3 *collisionPoint); // Detect collision between ray and sphere, returns collision point
|
||||||
|
RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box); // Detect collision between ray and box
|
||||||
|
RLAPI RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh); // Get collision info between ray and mesh
|
||||||
|
RLAPI RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle
|
||||||
|
RLAPI RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight); // Get collision info between ray and ground plane (Y-normal plane)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Shaders System Functions (Module: rlgl)
|
||||||
|
// NOTE: This functions are useless when using OpenGL 1.1
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI char *LoadText(const char *fileName); // Load chars array from text file
|
||||||
|
RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Load shader from files and bind default locations
|
||||||
|
RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM)
|
||||||
|
|
||||||
|
RLAPI Shader GetDefaultShader(void); // Get default shader
|
||||||
|
RLAPI Texture2D GetDefaultTexture(void); // Get default texture
|
||||||
|
|
||||||
|
RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
||||||
|
RLAPI void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
|
||||||
|
RLAPI void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
|
||||||
|
RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||||
|
|
||||||
|
RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||||
|
RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||||
|
|
||||||
|
RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
||||||
|
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||||
|
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
||||||
|
RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// VR experience Functions (Module: rlgl)
|
||||||
|
// NOTE: This functions are useless when using OpenGL 1.1
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI void InitVrDevice(int vdDevice); // Init VR device
|
||||||
|
RLAPI void CloseVrDevice(void); // Close VR device
|
||||||
|
RLAPI bool IsVrDeviceReady(void); // Detect if VR device is ready
|
||||||
|
RLAPI bool IsVrSimulator(void); // Detect if VR simulator is running
|
||||||
|
RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||||
|
RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Audio Loading and Playing Functions (Module: audio)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
RLAPI void InitAudioDevice(void); // Initialize audio device and context
|
||||||
|
RLAPI void CloseAudioDevice(void); // Close the audio device and context
|
||||||
|
RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully
|
||||||
|
|
||||||
|
RLAPI Wave LoadWave(const char *fileName); // Load wave data from file
|
||||||
|
RLAPI Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from raw array data
|
||||||
|
RLAPI Sound LoadSound(const char *fileName); // Load sound from file
|
||||||
|
RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound from wave data
|
||||||
|
RLAPI void UpdateSound(Sound sound, const void *data, int numSamples);// Update sound buffer with new data
|
||||||
|
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||||
|
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||||
|
RLAPI void PlaySound(Sound sound); // Play a sound
|
||||||
|
RLAPI void PauseSound(Sound sound); // Pause a sound
|
||||||
|
RLAPI void ResumeSound(Sound sound); // Resume a paused sound
|
||||||
|
RLAPI void StopSound(Sound sound); // Stop playing a sound
|
||||||
|
RLAPI bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
||||||
|
RLAPI void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
||||||
|
RLAPI void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||||
|
RLAPI void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format
|
||||||
|
RLAPI Wave WaveCopy(Wave wave); // Copy a wave to a new wave
|
||||||
|
RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range
|
||||||
|
RLAPI float *GetWaveData(Wave wave); // Get samples data from wave as a floats array
|
||||||
|
RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file
|
||||||
|
RLAPI void UnloadMusicStream(Music music); // Unload music stream
|
||||||
|
RLAPI void PlayMusicStream(Music music); // Start music playing
|
||||||
|
RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming
|
||||||
|
RLAPI void StopMusicStream(Music music); // Stop music playing
|
||||||
|
RLAPI void PauseMusicStream(Music music); // Pause music playing
|
||||||
|
RLAPI void ResumeMusicStream(Music music); // Resume playing paused music
|
||||||
|
RLAPI bool IsMusicPlaying(Music music); // Check if music is playing
|
||||||
|
RLAPI void SetMusicVolume(Music music, float volume); // Set volume for music (1.0 is max level)
|
||||||
|
RLAPI void SetMusicPitch(Music music, float pitch); // Set pitch for a music (1.0 is base level)
|
||||||
|
RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds)
|
||||||
|
RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds)
|
||||||
|
|
||||||
|
RLAPI AudioStream InitAudioStream(unsigned int sampleRate,
|
||||||
|
unsigned int sampleSize,
|
||||||
|
unsigned int channels); // Init audio stream (to stream raw audio pcm data)
|
||||||
|
RLAPI void UpdateAudioStream(AudioStream stream, const void *data, int numSamples); // Update audio stream buffers with data
|
||||||
|
RLAPI void CloseAudioStream(AudioStream stream); // Close audio stream and free memory
|
||||||
|
RLAPI bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
|
||||||
|
RLAPI void PlayAudioStream(AudioStream stream); // Play audio stream
|
||||||
|
RLAPI void PauseAudioStream(AudioStream stream); // Pause audio stream
|
||||||
|
RLAPI void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
||||||
|
RLAPI void StopAudioStream(AudioStream stream); // Stop audio stream
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAYLIB_H
|
1156
raylib/raymath.h
Normal file
1156
raylib/raymath.h
Normal file
File diff suppressed because it is too large
Load diff
4191
raylib/rlgl.c
Normal file
4191
raylib/rlgl.c
Normal file
File diff suppressed because it is too large
Load diff
443
raylib/rlgl.h
Normal file
443
raylib/rlgl.h
Normal file
|
@ -0,0 +1,443 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* rlgl - raylib OpenGL abstraction layer
|
||||||
|
*
|
||||||
|
* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to
|
||||||
|
* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0).
|
||||||
|
*
|
||||||
|
* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal
|
||||||
|
* VBO buffers (and VAOs if available). It requires calling 3 functions:
|
||||||
|
* rlglInit() - Initialize internal buffers and auxiliar resources
|
||||||
|
* rlglDraw() - Process internal buffers and send required draw calls
|
||||||
|
* rlglClose() - De-initialize internal buffers data and other auxiliar resources
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* raymath - 3D math functionality (Vector3, Matrix, Quaternion)
|
||||||
|
* GLAD - OpenGL extensions loading (OpenGL 3.3 Core only)
|
||||||
|
*
|
||||||
|
* Module Configuration Flags:
|
||||||
|
* GRAPHICS_API_OPENGL_11 - Use OpenGL 1.1 backend
|
||||||
|
* GRAPHICS_API_OPENGL_21 - Use OpenGL 2.1 backend
|
||||||
|
* GRAPHICS_API_OPENGL_33 - Use OpenGL 3.3 Core profile backend
|
||||||
|
* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend
|
||||||
|
*
|
||||||
|
* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RLGL_H
|
||||||
|
#define RLGL_H
|
||||||
|
|
||||||
|
//#define RLGL_STANDALONE // NOTE: To use rlgl as standalone lib, just uncomment this line
|
||||||
|
|
||||||
|
#ifndef RLGL_STANDALONE
|
||||||
|
#include "raylib.h" // Required for: Model, Shader, Texture2D
|
||||||
|
#include "utils.h" // Required for: TraceLog()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RLGL_STANDALONE
|
||||||
|
#define RAYMATH_STANDALONE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "raymath.h" // Required for: Vector3, Matrix
|
||||||
|
|
||||||
|
// Select desired OpenGL version
|
||||||
|
// NOTE: Those preprocessor defines are only used on rlgl module,
|
||||||
|
// if OpenGL version is required by any other module, it uses rlGetVersion()
|
||||||
|
|
||||||
|
// Choose opengl version here or just define it at compile time: -DGRAPHICS_API_OPENGL_33
|
||||||
|
//#define GRAPHICS_API_OPENGL_11 // Only available on PLATFORM_DESKTOP
|
||||||
|
//#define GRAPHICS_API_OPENGL_33 // Only available on PLATFORM_DESKTOP and RLGL_OCULUS_SUPPORT
|
||||||
|
//#define GRAPHICS_API_OPENGL_ES2 // Only available on PLATFORM_ANDROID or PLATFORM_RPI or PLATFORM_WEB
|
||||||
|
|
||||||
|
// Security check in case no GRAPHICS_API_OPENGL_* defined
|
||||||
|
#if !defined(GRAPHICS_API_OPENGL_11) && !defined(GRAPHICS_API_OPENGL_21) && !defined(GRAPHICS_API_OPENGL_33) && !defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
#define GRAPHICS_API_OPENGL_11
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Security check in case multiple GRAPHICS_API_OPENGL_* defined
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
#undef GRAPHICS_API_OPENGL_21
|
||||||
|
#endif
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
#undef GRAPHICS_API_OPENGL_33
|
||||||
|
#endif
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
#undef GRAPHICS_API_OPENGL_ES2
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
#define GRAPHICS_API_OPENGL_33
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
// NOTE: This is the maximum amount of lines, triangles and quads per frame, be careful!
|
||||||
|
#define MAX_LINES_BATCH 8192
|
||||||
|
#define MAX_TRIANGLES_BATCH 4096
|
||||||
|
#define MAX_QUADS_BATCH 8192
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
// NOTE: Reduce memory sizes for embedded systems (RPI and HTML5)
|
||||||
|
// NOTE: On HTML5 (emscripten) this is allocated on heap, by default it's only 16MB!...just take care...
|
||||||
|
#define MAX_LINES_BATCH 1024 // Critical for wire shapes (sphere)
|
||||||
|
#define MAX_TRIANGLES_BATCH 2048 // Critical for some shapes (sphere)
|
||||||
|
#define MAX_QUADS_BATCH 1024 // Be careful with text, every letter maps a quad
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Texture parameters (equivalent to OpenGL defines)
|
||||||
|
#define RL_TEXTURE_WRAP_S 0x2802 // GL_TEXTURE_WRAP_S
|
||||||
|
#define RL_TEXTURE_WRAP_T 0x2803 // GL_TEXTURE_WRAP_T
|
||||||
|
#define RL_TEXTURE_MAG_FILTER 0x2800 // GL_TEXTURE_MAG_FILTER
|
||||||
|
#define RL_TEXTURE_MIN_FILTER 0x2801 // GL_TEXTURE_MIN_FILTER
|
||||||
|
#define RL_TEXTURE_ANISOTROPIC_FILTER 0x3000 // Anisotropic filter (custom identifier)
|
||||||
|
|
||||||
|
#define RL_FILTER_NEAREST 0x2600 // GL_NEAREST
|
||||||
|
#define RL_FILTER_LINEAR 0x2601 // GL_LINEAR
|
||||||
|
#define RL_FILTER_MIP_NEAREST 0x2700 // GL_NEAREST_MIPMAP_NEAREST
|
||||||
|
#define RL_FILTER_NEAREST_MIP_LINEAR 0x2702 // GL_NEAREST_MIPMAP_LINEAR
|
||||||
|
#define RL_FILTER_LINEAR_MIP_NEAREST 0x2701 // GL_LINEAR_MIPMAP_NEAREST
|
||||||
|
#define RL_FILTER_MIP_LINEAR 0x2703 // GL_LINEAR_MIPMAP_LINEAR
|
||||||
|
|
||||||
|
#define RL_WRAP_REPEAT 0x2901 // GL_REPEAT
|
||||||
|
#define RL_WRAP_CLAMP 0x812F // GL_CLAMP_TO_EDGE
|
||||||
|
#define RL_WRAP_CLAMP_MIRROR 0x8742 // GL_MIRROR_CLAMP_EXT
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
|
||||||
|
|
||||||
|
typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
|
||||||
|
|
||||||
|
typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
#if defined(RLGL_STANDALONE)
|
||||||
|
#ifndef __cplusplus
|
||||||
|
// Boolean type
|
||||||
|
typedef enum { false, true } bool;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Color type, RGBA (32bit)
|
||||||
|
typedef struct Color {
|
||||||
|
unsigned char r;
|
||||||
|
unsigned char g;
|
||||||
|
unsigned char b;
|
||||||
|
unsigned char a;
|
||||||
|
} Color;
|
||||||
|
|
||||||
|
// Texture formats (support depends on OpenGL version)
|
||||||
|
typedef enum {
|
||||||
|
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||||
|
UNCOMPRESSED_GRAY_ALPHA,
|
||||||
|
UNCOMPRESSED_R5G6B5, // 16 bpp
|
||||||
|
UNCOMPRESSED_R8G8B8, // 24 bpp
|
||||||
|
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||||
|
UNCOMPRESSED_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||||
|
UNCOMPRESSED_R8G8B8A8, // 32 bpp
|
||||||
|
COMPRESSED_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
|
COMPRESSED_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
|
COMPRESSED_DXT3_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_DXT5_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_ETC1_RGB, // 4 bpp
|
||||||
|
COMPRESSED_ETC2_RGB, // 4 bpp
|
||||||
|
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_PVRT_RGB, // 4 bpp
|
||||||
|
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||||
|
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||||
|
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||||
|
} TextureFormat;
|
||||||
|
|
||||||
|
// Vertex data definning a mesh
|
||||||
|
typedef struct Mesh {
|
||||||
|
int vertexCount; // number of vertices stored in arrays
|
||||||
|
int triangleCount; // number of triangles stored (indexed or not)
|
||||||
|
float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||||
|
float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||||
|
float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5)
|
||||||
|
float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||||
|
float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4)
|
||||||
|
unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3)
|
||||||
|
unsigned short *indices;// vertex indices (in case vertex data comes indexed)
|
||||||
|
|
||||||
|
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||||
|
unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data)
|
||||||
|
} Mesh;
|
||||||
|
|
||||||
|
// Shader type (generic shader)
|
||||||
|
typedef struct Shader {
|
||||||
|
unsigned int id; // Shader program id
|
||||||
|
|
||||||
|
// Vertex attributes locations (default locations)
|
||||||
|
int vertexLoc; // Vertex attribute location point (default-location = 0)
|
||||||
|
int texcoordLoc; // Texcoord attribute location point (default-location = 1)
|
||||||
|
int normalLoc; // Normal attribute location point (default-location = 2)
|
||||||
|
int colorLoc; // Color attibute location point (default-location = 3)
|
||||||
|
int tangentLoc; // Tangent attribute location point (default-location = 4)
|
||||||
|
int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5)
|
||||||
|
|
||||||
|
// Uniform locations
|
||||||
|
int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader)
|
||||||
|
int colDiffuseLoc; // Color uniform location point (fragment shader)
|
||||||
|
int colAmbientLoc; // Ambient color uniform location point (fragment shader)
|
||||||
|
int colSpecularLoc; // Specular color uniform location point (fragment shader)
|
||||||
|
|
||||||
|
// Texture map locations (generic for any kind of map)
|
||||||
|
int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0)
|
||||||
|
int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1)
|
||||||
|
int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2)
|
||||||
|
} Shader;
|
||||||
|
|
||||||
|
// Texture2D type
|
||||||
|
// NOTE: Data stored in GPU memory
|
||||||
|
typedef struct Texture2D {
|
||||||
|
unsigned int id; // OpenGL texture id
|
||||||
|
int width; // Texture base width
|
||||||
|
int height; // Texture base height
|
||||||
|
int mipmaps; // Mipmap levels, 1 by default
|
||||||
|
int format; // Data format (TextureFormat)
|
||||||
|
} Texture2D;
|
||||||
|
|
||||||
|
// RenderTexture2D type, for texture rendering
|
||||||
|
typedef struct RenderTexture2D {
|
||||||
|
unsigned int id; // Render texture (fbo) id
|
||||||
|
Texture2D texture; // Color buffer attachment texture
|
||||||
|
Texture2D depth; // Depth buffer attachment texture
|
||||||
|
} RenderTexture2D;
|
||||||
|
|
||||||
|
// Material type
|
||||||
|
typedef struct Material {
|
||||||
|
Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular)
|
||||||
|
|
||||||
|
Texture2D texDiffuse; // Diffuse texture
|
||||||
|
Texture2D texNormal; // Normal texture
|
||||||
|
Texture2D texSpecular; // Specular texture
|
||||||
|
|
||||||
|
Color colDiffuse; // Diffuse color
|
||||||
|
Color colAmbient; // Ambient color
|
||||||
|
Color colSpecular; // Specular color
|
||||||
|
|
||||||
|
float glossiness; // Glossiness level (Ranges from 0 to 1000)
|
||||||
|
} Material;
|
||||||
|
|
||||||
|
// Camera type, defines a camera position/orientation in 3d space
|
||||||
|
typedef struct Camera {
|
||||||
|
Vector3 position; // Camera position
|
||||||
|
Vector3 target; // Camera target it looks-at
|
||||||
|
Vector3 up; // Camera up vector (rotation over its axis)
|
||||||
|
float fovy; // Camera field-of-view apperture in Y (degrees)
|
||||||
|
} Camera;
|
||||||
|
|
||||||
|
// Light type
|
||||||
|
typedef struct LightData {
|
||||||
|
unsigned int id; // Light unique id
|
||||||
|
bool enabled; // Light enabled
|
||||||
|
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
|
||||||
|
|
||||||
|
Vector3 position; // Light position
|
||||||
|
Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
|
||||||
|
float radius; // Light attenuation radius light intensity reduced with distance (world distance)
|
||||||
|
|
||||||
|
Color diffuse; // Light diffuse color
|
||||||
|
float intensity; // Light intensity level
|
||||||
|
|
||||||
|
float coneAngle; // Light cone max angle: LIGHT_SPOT
|
||||||
|
} LightData, *Light;
|
||||||
|
|
||||||
|
// Light types
|
||||||
|
typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
|
||||||
|
|
||||||
|
// Texture parameters: filter mode
|
||||||
|
// NOTE 1: Filtering considers mipmaps if available in the texture
|
||||||
|
// NOTE 2: Filter is accordingly set for minification and magnification
|
||||||
|
typedef enum {
|
||||||
|
FILTER_POINT = 0, // No filter, just pixel aproximation
|
||||||
|
FILTER_BILINEAR, // Linear filtering
|
||||||
|
FILTER_TRILINEAR, // Trilinear filtering (linear with mipmaps)
|
||||||
|
FILTER_ANISOTROPIC_4X, // Anisotropic filtering 4x
|
||||||
|
FILTER_ANISOTROPIC_8X, // Anisotropic filtering 8x
|
||||||
|
FILTER_ANISOTROPIC_16X, // Anisotropic filtering 16x
|
||||||
|
} TextureFilterMode;
|
||||||
|
|
||||||
|
// Texture parameters: wrap mode
|
||||||
|
typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode;
|
||||||
|
|
||||||
|
// Color blending modes (pre-defined)
|
||||||
|
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
|
||||||
|
|
||||||
|
// TraceLog message types
|
||||||
|
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
||||||
|
|
||||||
|
// VR Head Mounted Display devices
|
||||||
|
typedef enum {
|
||||||
|
HMD_DEFAULT_DEVICE = 0,
|
||||||
|
HMD_OCULUS_RIFT_DK2,
|
||||||
|
HMD_OCULUS_RIFT_CV1,
|
||||||
|
HMD_VALVE_HTC_VIVE,
|
||||||
|
HMD_SAMSUNG_GEAR_VR,
|
||||||
|
HMD_GOOGLE_CARDBOARD,
|
||||||
|
HMD_SONY_PLAYSTATION_VR,
|
||||||
|
HMD_RAZER_OSVR,
|
||||||
|
HMD_FOVE_VR,
|
||||||
|
} VrDevice;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - Matrix operations
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlMatrixMode(int mode); // Choose the current matrix to be transformed
|
||||||
|
void rlPushMatrix(void); // Push the current matrix to stack
|
||||||
|
void rlPopMatrix(void); // Pop lattest inserted matrix from stack
|
||||||
|
void rlLoadIdentity(void); // Reset current matrix to identity matrix
|
||||||
|
void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix
|
||||||
|
void rlRotatef(float angleDeg, float x, float y, float z); // Multiply the current matrix by a rotation matrix
|
||||||
|
void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix
|
||||||
|
void rlMultMatrixf(float *mat); // Multiply the current matrix by another matrix
|
||||||
|
void rlFrustum(double left, double right, double bottom, double top, double near, double far);
|
||||||
|
void rlOrtho(double left, double right, double bottom, double top, double near, double far);
|
||||||
|
void rlViewport(int x, int y, int width, int height); // Set the viewport area
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - Vertex level operations
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlBegin(int mode); // Initialize drawing mode (how to organize vertex)
|
||||||
|
void rlEnd(void); // Finish vertex providing
|
||||||
|
void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int
|
||||||
|
void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float
|
||||||
|
void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float
|
||||||
|
void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float
|
||||||
|
void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float
|
||||||
|
void rlColor4ub(byte r, byte g, byte b, byte a); // Define one vertex (color) - 4 byte
|
||||||
|
void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float
|
||||||
|
void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
|
||||||
|
// NOTE: This functions are used to completely abstract raylib code from OpenGL layer
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlEnableTexture(unsigned int id); // Enable texture usage
|
||||||
|
void rlDisableTexture(void); // Disable texture usage
|
||||||
|
void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
|
||||||
|
void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
|
||||||
|
void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
|
||||||
|
void rlEnableDepthTest(void); // Enable depth test
|
||||||
|
void rlDisableDepthTest(void); // Disable depth test
|
||||||
|
void rlEnableWireMode(void); // Enable wire mode
|
||||||
|
void rlDisableWireMode(void); // Disable wire mode
|
||||||
|
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
|
||||||
|
void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU
|
||||||
|
void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
|
||||||
|
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
|
||||||
|
void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
|
||||||
|
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
|
||||||
|
void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
|
||||||
|
int rlGetVersion(void); // Returns current OpenGL version
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Functions Declaration - rlgl functionality
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states)
|
||||||
|
void rlglClose(void); // De-init rlgl
|
||||||
|
void rlglDraw(void); // Draw VAO/VBO
|
||||||
|
void rlglLoadExtensions(void *loader); // Load OpenGL extensions
|
||||||
|
|
||||||
|
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU
|
||||||
|
RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments)
|
||||||
|
void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data
|
||||||
|
void rlglGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture
|
||||||
|
|
||||||
|
void rlglLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids
|
||||||
|
void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer)
|
||||||
|
void rlglDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
|
||||||
|
void rlglUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU
|
||||||
|
|
||||||
|
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
|
||||||
|
|
||||||
|
unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
|
||||||
|
void *rlglReadTexturePixels(Texture2D texture); // Read texture pixel data
|
||||||
|
|
||||||
|
// VR functions exposed to core module but not to raylib users
|
||||||
|
void BeginVrDrawing(void); // Begin VR drawing configuration
|
||||||
|
void EndVrDrawing(void); // End VR drawing process (and desktop mirror)
|
||||||
|
|
||||||
|
// NOTE: There is a set of shader related functions that are available to end user,
|
||||||
|
// to avoid creating function wrappers through core module, they have been directly declared in raylib.h
|
||||||
|
|
||||||
|
#if defined(RLGL_STANDALONE)
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
// Shaders System Functions (Module: rlgl)
|
||||||
|
// NOTE: This functions are useless when using OpenGL 1.1
|
||||||
|
//------------------------------------------------------------------------------------
|
||||||
|
Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
|
||||||
|
void UnloadShader(Shader shader); // Unload a custom shader from memory
|
||||||
|
|
||||||
|
Shader GetDefaultShader(void); // Get default shader
|
||||||
|
Shader GetStandardShader(void); // Get default shader
|
||||||
|
Texture2D GetDefaultTexture(void); // Get default texture
|
||||||
|
|
||||||
|
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
||||||
|
void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
|
||||||
|
void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
|
||||||
|
void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||||
|
|
||||||
|
void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix)
|
||||||
|
void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix)
|
||||||
|
|
||||||
|
void BeginShaderMode(Shader shader); // Begin custom shader drawing
|
||||||
|
void EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||||
|
void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
||||||
|
void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
|
||||||
|
|
||||||
|
Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool
|
||||||
|
void DestroyLight(Light light); // Destroy a light and take it out of the list
|
||||||
|
|
||||||
|
void TraceLog(int msgType, const char *text, ...);
|
||||||
|
float *MatrixToFloat(Matrix mat);
|
||||||
|
|
||||||
|
void InitVrDevice(int vrDevice); // Init VR device
|
||||||
|
void CloseVrDevice(void); // Close VR device
|
||||||
|
bool IsVrDeviceReady(void); // Detect if VR device is ready
|
||||||
|
bool IsVrSimulator(void); // Detect if VR simulator is running
|
||||||
|
void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera
|
||||||
|
void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator)
|
||||||
|
|
||||||
|
// Oculus Rift API for direct access the device (no simulator)
|
||||||
|
bool InitOculusDevice(void); // Initialize Oculus device (returns true if success)
|
||||||
|
void CloseOculusDevice(void); // Close Oculus device
|
||||||
|
void UpdateOculusTracking(Camera *camera); // Update Oculus head position-orientation tracking (and camera)
|
||||||
|
void BeginOculusDrawing(void); // Setup Oculus buffers for drawing
|
||||||
|
void EndOculusDrawing(void); // Finish Oculus drawing and blit framebuffer to mirror
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RLGL_H
|
438
raylib/rres.h
Normal file
438
raylib/rres.h
Normal file
|
@ -0,0 +1,438 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* rres - raylib Resource custom format management functions
|
||||||
|
*
|
||||||
|
* Basic functions to load/save rRES resource files
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* tinfl - DEFLATE decompression functions
|
||||||
|
*
|
||||||
|
* Module Configuration Flags:
|
||||||
|
*
|
||||||
|
* #define RREM_IMPLEMENTATION
|
||||||
|
* Generates the implementation of the library into the included file.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016-2017 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RRES_H
|
||||||
|
#define RRES_H
|
||||||
|
|
||||||
|
#if !defined(RRES_STANDALONE)
|
||||||
|
#include "raylib.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#define RRES_STATIC
|
||||||
|
#ifdef RRES_STATIC
|
||||||
|
#define RRESDEF static // Functions just visible to module including this file
|
||||||
|
#else
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#define RRESDEF extern "C" // Functions visible from other files (no name mangling of functions in C++)
|
||||||
|
#else
|
||||||
|
#define RRESDEF extern // Functions visible from other files
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#define MAX_RESOURCES_SUPPORTED 256
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
// NOTE: Some types are required for RAYGUI_STANDALONE usage
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(RRES_STANDALONE)
|
||||||
|
// rRES data returned when reading a resource, it contains all required data for user (24 byte)
|
||||||
|
// NOTE: Using void *data pointer, so we can load to image.data, wave.data, mesh.*, (unsigned char *)
|
||||||
|
typedef struct {
|
||||||
|
unsigned int type; // Resource type (4 byte)
|
||||||
|
|
||||||
|
unsigned int param1; // Resouce parameter 1 (4 byte)
|
||||||
|
unsigned int param2; // Resouce parameter 2 (4 byte)
|
||||||
|
unsigned int param3; // Resouce parameter 3 (4 byte)
|
||||||
|
unsigned int param4; // Resouce parameter 4 (4 byte)
|
||||||
|
|
||||||
|
void *data; // Resource data pointer (4 byte)
|
||||||
|
} RRESData;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RRES_TYPE_RAW = 0,
|
||||||
|
RRES_TYPE_IMAGE,
|
||||||
|
RRES_TYPE_WAVE,
|
||||||
|
RRES_TYPE_VERTEX,
|
||||||
|
RRES_TYPE_TEXT,
|
||||||
|
RRES_TYPE_FONT_IMAGE,
|
||||||
|
RRES_TYPE_FONT_DATA, // Character { int value, recX, recY, recWidth, recHeight, offsetX, offsetY, xAdvance }
|
||||||
|
RRES_TYPE_DIRECTORY
|
||||||
|
} RRESDataType;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global variables
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
RRESDEF RRESData LoadResource(const char *rresFileName);
|
||||||
|
RRESDEF RRESData LoadResourceById(const char *rresFileName, int rresId);
|
||||||
|
RRESDEF void UnloadResource(RRESData rres);
|
||||||
|
|
||||||
|
#endif // RRES_H
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************************
|
||||||
|
*
|
||||||
|
* RRES IMPLEMENTATION
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#if defined(RRES_IMPLEMENTATION)
|
||||||
|
|
||||||
|
#include <stdio.h> // Required for: FILE, fopen(), fclose()
|
||||||
|
|
||||||
|
// Check if custom malloc/free functions defined, if not, using standard ones
|
||||||
|
#if !defined(RRES_MALLOC)
|
||||||
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
|
|
||||||
|
#define RRES_MALLOC(size) malloc(size)
|
||||||
|
#define RRES_FREE(ptr) free(ptr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "external/tinfl.c" // Required for: tinfl_decompress_mem_to_mem()
|
||||||
|
// NOTE: DEFLATE algorythm data decompression
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// rRES file header (8 byte)
|
||||||
|
typedef struct {
|
||||||
|
char id[4]; // File identifier: rRES (4 byte)
|
||||||
|
unsigned short version; // File version and subversion (2 byte)
|
||||||
|
unsigned short count; // Number of resources in this file (2 byte)
|
||||||
|
} RRESFileHeader;
|
||||||
|
|
||||||
|
// rRES info header, every resource includes this header (16 byte + 16 byte)
|
||||||
|
typedef struct {
|
||||||
|
unsigned int id; // Resource unique identifier (4 byte)
|
||||||
|
unsigned char dataType; // Resource data type (1 byte)
|
||||||
|
unsigned char compType; // Resource data compression type (1 byte)
|
||||||
|
unsigned char cryptoType; // Resource data encryption type (1 byte)
|
||||||
|
unsigned char partsCount; // Resource data parts count, used for splitted data (1 byte)
|
||||||
|
unsigned int dataSize; // Resource data size (compressed or not, only DATA) (4 byte)
|
||||||
|
unsigned int uncompSize; // Resource data size (uncompressed, only DATA) (4 byte)
|
||||||
|
|
||||||
|
unsigned int param1; // Resouce parameter 1 (4 byte)
|
||||||
|
unsigned int param2; // Resouce parameter 2 (4 byte)
|
||||||
|
unsigned int param3; // Resouce parameter 3 (4 byte)
|
||||||
|
unsigned int param4; // Resouce parameter 4 (4 byte)
|
||||||
|
} RRESInfoHeader;
|
||||||
|
|
||||||
|
// Compression types
|
||||||
|
typedef enum {
|
||||||
|
RRES_COMP_NONE = 0, // No data compression
|
||||||
|
RRES_COMP_DEFLATE, // DEFLATE compression
|
||||||
|
RRES_COMP_LZ4, // LZ4 compression
|
||||||
|
RRES_COMP_LZMA, // LZMA compression
|
||||||
|
RRES_COMP_BROTLI, // BROTLI compression
|
||||||
|
// gzip, zopfli, lzo, zstd // Other compression algorythms...
|
||||||
|
} RRESCompressionType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RRES_CRYPTO_NONE = 0, // No data encryption
|
||||||
|
RRES_CRYPTO_XOR, // XOR (128 bit) encryption
|
||||||
|
RRES_CRYPTO_AES, // RIJNDAEL (128 bit) encryption (AES)
|
||||||
|
RRES_CRYPTO_TDES, // Triple DES encryption
|
||||||
|
RRES_CRYPTO_BLOWFISH, // BLOWFISH encryption
|
||||||
|
RRES_CRYPTO_XTEA, // XTEA encryption
|
||||||
|
// twofish, RC5, RC6 // Other encryption algorythm...
|
||||||
|
} RRESEncryptionType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RRES_IM_UNCOMP_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||||
|
RRES_IM_UNCOMP_GRAY_ALPHA, // 16 bpp (2 channels)
|
||||||
|
RRES_IM_UNCOMP_R5G6B5, // 16 bpp
|
||||||
|
RRES_IM_UNCOMP_R8G8B8, // 24 bpp
|
||||||
|
RRES_IM_UNCOMP_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||||
|
RRES_IM_UNCOMP_R4G4B4A4, // 16 bpp (4 bit alpha)
|
||||||
|
RRES_IM_UNCOMP_R8G8B8A8, // 32 bpp
|
||||||
|
RRES_IM_COMP_DXT1_RGB, // 4 bpp (no alpha)
|
||||||
|
RRES_IM_COMP_DXT1_RGBA, // 4 bpp (1 bit alpha)
|
||||||
|
RRES_IM_COMP_DXT3_RGBA, // 8 bpp
|
||||||
|
RRES_IM_COMP_DXT5_RGBA, // 8 bpp
|
||||||
|
RRES_IM_COMP_ETC1_RGB, // 4 bpp
|
||||||
|
RRES_IM_COMP_ETC2_RGB, // 4 bpp
|
||||||
|
RRES_IM_COMP_ETC2_EAC_RGBA, // 8 bpp
|
||||||
|
RRES_IM_COMP_PVRT_RGB, // 4 bpp
|
||||||
|
RRES_IM_COMP_PVRT_RGBA, // 4 bpp
|
||||||
|
RRES_IM_COMP_ASTC_4x4_RGBA, // 8 bpp
|
||||||
|
RRES_IM_COMP_ASTC_8x8_RGBA // 2 bpp
|
||||||
|
//...
|
||||||
|
} RRESImageFormat;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RRES_VERT_POSITION,
|
||||||
|
RRES_VERT_TEXCOORD1,
|
||||||
|
RRES_VERT_TEXCOORD2,
|
||||||
|
RRES_VERT_TEXCOORD3,
|
||||||
|
RRES_VERT_TEXCOORD4,
|
||||||
|
RRES_VERT_NORMAL,
|
||||||
|
RRES_VERT_TANGENT,
|
||||||
|
RRES_VERT_COLOR,
|
||||||
|
RRES_VERT_INDEX,
|
||||||
|
//...
|
||||||
|
} RRESVertexType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RRES_VERT_BYTE,
|
||||||
|
RRES_VERT_SHORT,
|
||||||
|
RRES_VERT_INT,
|
||||||
|
RRES_VERT_HFLOAT,
|
||||||
|
RRES_VERT_FLOAT,
|
||||||
|
//...
|
||||||
|
} RRESVertexFormat;
|
||||||
|
|
||||||
|
#if defined(RRES_STANDALONE)
|
||||||
|
typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static void *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Load resource from file (only one)
|
||||||
|
// NOTE: Returns uncompressed data with parameters, only first resource found
|
||||||
|
RRESDEF RRESData LoadResource(const char *fileName)
|
||||||
|
{
|
||||||
|
// Force loading first resource available
|
||||||
|
RRESData rres = { 0 };
|
||||||
|
|
||||||
|
rres = LoadResourceById(fileName, 0);
|
||||||
|
|
||||||
|
return rres;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load resource from file by id
|
||||||
|
// NOTE: Returns uncompressed data with parameters, search resource by id
|
||||||
|
RRESDEF RRESData LoadResourceById(const char *fileName, int rresId)
|
||||||
|
{
|
||||||
|
RRESData rres = { 0 };
|
||||||
|
|
||||||
|
RRESFileHeader fileHeader;
|
||||||
|
RRESInfoHeader infoHeader;
|
||||||
|
|
||||||
|
FILE *rresFile = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (rresFile == NULL) TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", fileName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Read rres file info header
|
||||||
|
fread(&fileHeader.id[0], sizeof(char), 1, rresFile);
|
||||||
|
fread(&fileHeader.id[1], sizeof(char), 1, rresFile);
|
||||||
|
fread(&fileHeader.id[2], sizeof(char), 1, rresFile);
|
||||||
|
fread(&fileHeader.id[3], sizeof(char), 1, rresFile);
|
||||||
|
fread(&fileHeader.version, sizeof(short), 1, rresFile);
|
||||||
|
fread(&fileHeader.count, sizeof(short), 1, rresFile);
|
||||||
|
|
||||||
|
// Verify "rRES" identifier
|
||||||
|
if ((fileHeader.id[0] != 'r') && (fileHeader.id[1] != 'R') && (fileHeader.id[2] != 'E') && (fileHeader.id[3] != 'S'))
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] This is not a valid raylib resource file", fileName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fileHeader.count; i++)
|
||||||
|
{
|
||||||
|
// Read resource info and parameters
|
||||||
|
fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile);
|
||||||
|
|
||||||
|
if (infoHeader.id == rresId)
|
||||||
|
{
|
||||||
|
// Register data type and parameters
|
||||||
|
rres.type = infoHeader.dataType;
|
||||||
|
rres.param1 = infoHeader.param1;
|
||||||
|
rres.param2 = infoHeader.param2;
|
||||||
|
rres.param3 = infoHeader.param3;
|
||||||
|
rres.param4 = infoHeader.param4;
|
||||||
|
|
||||||
|
// Read resource data block
|
||||||
|
void *data = RRES_MALLOC(infoHeader.dataSize);
|
||||||
|
fread(data, infoHeader.dataSize, 1, rresFile);
|
||||||
|
|
||||||
|
if (infoHeader.compType == RRES_COMP_DEFLATE)
|
||||||
|
{
|
||||||
|
void *uncompData = DecompressData(data, infoHeader.dataSize, infoHeader.uncompSize);
|
||||||
|
|
||||||
|
rres.data = uncompData;
|
||||||
|
|
||||||
|
RRES_FREE(data);
|
||||||
|
}
|
||||||
|
else rres.data = data;
|
||||||
|
|
||||||
|
if (rres.data != NULL) TraceLog(INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id);
|
||||||
|
|
||||||
|
if (rresId == 0) break; // Break for loop, do not check next resource
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Skip required data to read next resource infoHeader
|
||||||
|
fseek(rresFile, infoHeader.dataSize, SEEK_CUR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rres.data == NULL) TraceLog(WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(rresFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rres;
|
||||||
|
}
|
||||||
|
|
||||||
|
RRESDEF void UnloadResource(RRESData rres)
|
||||||
|
{
|
||||||
|
if (rres.data != NULL) free(rres.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Data decompression function
|
||||||
|
// NOTE: Allocated data MUST be freed by user
|
||||||
|
static void *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize)
|
||||||
|
{
|
||||||
|
int tempUncompSize;
|
||||||
|
void *uncompData;
|
||||||
|
|
||||||
|
// Allocate buffer to hold decompressed data
|
||||||
|
uncompData = (mz_uint8 *)RRES_MALLOC((size_t)uncompSize);
|
||||||
|
|
||||||
|
// Check correct memory allocation
|
||||||
|
if (uncompData == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "Out of memory while decompressing data");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Decompress data
|
||||||
|
tempUncompSize = tinfl_decompress_mem_to_mem(uncompData, (size_t)uncompSize, data, compSize, 1);
|
||||||
|
|
||||||
|
if (tempUncompSize == -1)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "Data decompression failed");
|
||||||
|
RRES_FREE(uncompData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uncompSize != (int)tempUncompSize)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted");
|
||||||
|
TraceLog(WARNING, " -- Expected uncompressed size: %i", uncompSize);
|
||||||
|
TraceLog(WARNING, " -- Returned uncompressed size: %i", tempUncompSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uncompData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Some required functions for rres standalone module version
|
||||||
|
#if defined(RRES_STANDALONE)
|
||||||
|
// Outputs a trace log message (INFO, ERROR, WARNING)
|
||||||
|
// NOTE: If a file has been init, output log is written there
|
||||||
|
void TraceLog(int logType, const char *text, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int traceDebugMsgs = 0;
|
||||||
|
|
||||||
|
#ifdef DO_NOT_TRACE_DEBUG_MSGS
|
||||||
|
traceDebugMsgs = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (msgType)
|
||||||
|
{
|
||||||
|
case LOG_INFO: fprintf(stdout, "INFO: "); break;
|
||||||
|
case LOG_ERROR: fprintf(stdout, "ERROR: "); break;
|
||||||
|
case LOG_WARNING: fprintf(stdout, "WARNING: "); break;
|
||||||
|
case LOG_DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs)))
|
||||||
|
{
|
||||||
|
va_start(args, text);
|
||||||
|
vfprintf(stdout, text, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msgType == ERROR) exit(1); // If ERROR message, exit program
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // RAYGUI_IMPLEMENTATION
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData);
|
||||||
|
Mesh LoadMeshEx(rres.param1, rres.data, rres.data + offset, rres.data + offset*2, rres.data + offset*3);
|
||||||
|
|
||||||
|
Shader LoadShader(const char *vsText, int vsLength);
|
||||||
|
Shader LoadShaderV(rres.data, rres.param1);
|
||||||
|
|
||||||
|
// Parameters information depending on resource type (IMAGE, WAVE, MESH, TEXT)
|
||||||
|
|
||||||
|
// Image data params
|
||||||
|
int imgWidth, imgHeight;
|
||||||
|
char colorFormat, mipmaps;
|
||||||
|
|
||||||
|
// Wave data params
|
||||||
|
int sampleCount,
|
||||||
|
short sampleRate, bps;
|
||||||
|
char channels, reserved;
|
||||||
|
|
||||||
|
// Mesh data params
|
||||||
|
int vertexCount, reserved;
|
||||||
|
short vertexTypesMask, vertexFormatsMask;
|
||||||
|
|
||||||
|
// Text data params
|
||||||
|
int charsCount;
|
||||||
|
int cultureCode;
|
||||||
|
*/
|
106
raylib/shader_distortion.h
Normal file
106
raylib/shader_distortion.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
|
||||||
|
// Vertex shader definition to embed, no external file required
|
||||||
|
static const char vDistortionShaderStr[] =
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
"#version 120 \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
"#version 100 \n"
|
||||||
|
#endif
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
"attribute vec3 vertexPosition; \n"
|
||||||
|
"attribute vec2 vertexTexCoord; \n"
|
||||||
|
"attribute vec4 vertexColor; \n"
|
||||||
|
"varying vec2 fragTexCoord; \n"
|
||||||
|
"varying vec4 fragColor; \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
"#version 330 \n"
|
||||||
|
"in vec3 vertexPosition; \n"
|
||||||
|
"in vec2 vertexTexCoord; \n"
|
||||||
|
"in vec4 vertexColor; \n"
|
||||||
|
"out vec2 fragTexCoord; \n"
|
||||||
|
"out vec4 fragColor; \n"
|
||||||
|
#endif
|
||||||
|
"uniform mat4 mvpMatrix; \n"
|
||||||
|
"void main() \n"
|
||||||
|
"{ \n"
|
||||||
|
" fragTexCoord = vertexTexCoord; \n"
|
||||||
|
" fragColor = vertexColor; \n"
|
||||||
|
" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
|
||||||
|
"} \n";
|
||||||
|
|
||||||
|
// Fragment shader definition to embed, no external file required
|
||||||
|
static const char fDistortionShaderStr[] =
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
"#version 120 \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
"#version 100 \n"
|
||||||
|
"precision mediump float; \n" // precision required for OpenGL ES2 (WebGL)
|
||||||
|
#endif
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
"varying vec2 fragTexCoord; \n"
|
||||||
|
"varying vec4 fragColor; \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
"#version 330 \n"
|
||||||
|
"in vec2 fragTexCoord; \n"
|
||||||
|
"in vec4 fragColor; \n"
|
||||||
|
"out vec4 finalColor; \n"
|
||||||
|
#endif
|
||||||
|
"uniform sampler2D texture0; \n"
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
"uniform vec2 leftLensCenter; \n"
|
||||||
|
"uniform vec2 rightLensCenter; \n"
|
||||||
|
"uniform vec2 leftScreenCenter; \n"
|
||||||
|
"uniform vec2 rightScreenCenter; \n"
|
||||||
|
"uniform vec2 scale; \n"
|
||||||
|
"uniform vec2 scaleIn; \n"
|
||||||
|
"uniform vec4 hmdWarpParam; \n"
|
||||||
|
"uniform vec4 chromaAbParam; \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
"uniform vec2 leftLensCenter = vec2(0.288, 0.5); \n"
|
||||||
|
"uniform vec2 rightLensCenter = vec2(0.712, 0.5); \n"
|
||||||
|
"uniform vec2 leftScreenCenter = vec2(0.25, 0.5); \n"
|
||||||
|
"uniform vec2 rightScreenCenter = vec2(0.75, 0.5); \n"
|
||||||
|
"uniform vec2 scale = vec2(0.25, 0.45); \n"
|
||||||
|
"uniform vec2 scaleIn = vec2(4, 2.2222); \n"
|
||||||
|
"uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0); \n"
|
||||||
|
"uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0); \n"
|
||||||
|
#endif
|
||||||
|
"void main() \n"
|
||||||
|
"{ \n"
|
||||||
|
" vec2 lensCenter = fragTexCoord.x < 0.5 ? leftLensCenter : rightLensCenter; \n"
|
||||||
|
" vec2 screenCenter = fragTexCoord.x < 0.5 ? leftScreenCenter : rightScreenCenter; \n"
|
||||||
|
" vec2 theta = (fragTexCoord - lensCenter)*scaleIn; \n"
|
||||||
|
" float rSq = theta.x*theta.x + theta.y*theta.y; \n"
|
||||||
|
" vec2 theta1 = theta*(hmdWarpParam.x + hmdWarpParam.y*rSq + hmdWarpParam.z*rSq*rSq + hmdWarpParam.w*rSq*rSq*rSq); \n"
|
||||||
|
" vec2 thetaBlue = theta1*(chromaAbParam.z + chromaAbParam.w*rSq); \n"
|
||||||
|
" vec2 tcBlue = lensCenter + scale*thetaBlue; \n"
|
||||||
|
" if (any(bvec2(clamp(tcBlue, screenCenter - vec2(0.25, 0.5), screenCenter + vec2(0.25, 0.5)) - tcBlue))) \n"
|
||||||
|
" { \n"
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
" gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
" finalColor = vec4(0.0, 0.0, 0.0, 1.0); \n"
|
||||||
|
#endif
|
||||||
|
" } \n"
|
||||||
|
" else \n"
|
||||||
|
" { \n"
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
" float blue = texture2D(texture0, tcBlue).b; \n"
|
||||||
|
" vec2 tcGreen = lensCenter + scale*theta1; \n"
|
||||||
|
" float green = texture2D(texture0, tcGreen).g; \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
" float blue = texture(texture0, tcBlue).b; \n"
|
||||||
|
" vec2 tcGreen = lensCenter + scale*theta1; \n"
|
||||||
|
" float green = texture(texture0, tcGreen).g; \n"
|
||||||
|
#endif
|
||||||
|
" vec2 thetaRed = theta1*(chromaAbParam.x + chromaAbParam.y*rSq); \n"
|
||||||
|
" vec2 tcRed = lensCenter + scale*thetaRed; \n"
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21)
|
||||||
|
" float red = texture2D(texture0, tcRed).r; \n"
|
||||||
|
" gl_FragColor = vec4(red, green, blue, 1.0); \n"
|
||||||
|
#elif defined(GRAPHICS_API_OPENGL_33)
|
||||||
|
" float red = texture(texture0, tcRed).r; \n"
|
||||||
|
" finalColor = vec4(red, green, blue, 1.0); \n"
|
||||||
|
#endif
|
||||||
|
" } \n"
|
||||||
|
"} \n";
|
|
@ -103,13 +103,6 @@ func GetDefaultShader() Shader {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get standard shader
|
|
||||||
func GetStandardShader() Shader {
|
|
||||||
ret := C.GetStandardShader()
|
|
||||||
v := NewShaderFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get default texture
|
// Get default texture
|
||||||
func GetDefaultTexture() *Texture2D {
|
func GetDefaultTexture() *Texture2D {
|
||||||
ret := C.GetDefaultTexture()
|
ret := C.GetDefaultTexture()
|
||||||
|
@ -187,22 +180,6 @@ func EndBlendMode() {
|
||||||
C.EndBlendMode()
|
C.EndBlendMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new light, initialize it and add to pool
|
|
||||||
func CreateLight(_type LightType, position Vector3, diffuse Color) Light {
|
|
||||||
c_type := (C.int)(_type)
|
|
||||||
cposition := position.cptr()
|
|
||||||
cdiffuse := diffuse.cptr()
|
|
||||||
ret := C.CreateLight(c_type, *cposition, *cdiffuse)
|
|
||||||
v := NewLightFromPointer(unsafe.Pointer(ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy a light and take it out of the list
|
|
||||||
func DestroyLight(light Light) {
|
|
||||||
clightdata := NewLightData(light)
|
|
||||||
C.DestroyLight(clightdata.cptr())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init VR device
|
// Init VR device
|
||||||
func InitVrDevice(vdDevice VrDevice) {
|
func InitVrDevice(vdDevice VrDevice) {
|
||||||
cvdDevice := (C.int)(vdDevice)
|
cvdDevice := (C.int)(vdDevice)
|
||||||
|
|
536
raylib/shapes.c
Normal file
536
raylib/shapes.c
Normal file
|
@ -0,0 +1,536 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib.shapes
|
||||||
|
*
|
||||||
|
* Basic functions to draw 2d Shapes and check collisions
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* rlgl - raylib OpenGL abstraction layer
|
||||||
|
*
|
||||||
|
* Module Configuration Flags:
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||||
|
|
||||||
|
#include <stdlib.h> // Required for: abs()
|
||||||
|
#include <math.h> // Required for: sinf(), cosf(), sqrtf()
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Nop...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Not here...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// ...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// No private (static) functions in this module (.c file)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw a pixel
|
||||||
|
void DrawPixel(int posX, int posY, Color color)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2i(posX, posY);
|
||||||
|
rlVertex2i(posX + 1, posY + 1);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a pixel (Vector version)
|
||||||
|
void DrawPixelV(Vector2 position, Color color)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2f(position.x, position.y);
|
||||||
|
rlVertex2f(position.x + 1.0f, position.y + 1.0f);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a line
|
||||||
|
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2i(startPosX, startPosY);
|
||||||
|
rlVertex2i(endPosX, endPosY);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a line (Vector version)
|
||||||
|
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2f(startPos.x, startPos.y);
|
||||||
|
rlVertex2f(endPos.x, endPos.y);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled circle
|
||||||
|
void DrawCircle(int centerX, int centerY, float radius, Color color)
|
||||||
|
{
|
||||||
|
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a gradient-filled circle
|
||||||
|
// NOTE: Gradient goes from center (color1) to border (color2)
|
||||||
|
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
for (int i = 0; i < 360; i += 10)
|
||||||
|
{
|
||||||
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
||||||
|
rlVertex2i(centerX, centerY);
|
||||||
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
|
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
||||||
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
||||||
|
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled circle (Vector version)
|
||||||
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
||||||
|
void DrawCircleV(Vector2 center, float radius, Color color)
|
||||||
|
{
|
||||||
|
if (rlGetVersion() == OPENGL_11)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
for (int i = 0; i < 360; i += 10)
|
||||||
|
{
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
rlVertex2f(center.x, center.y);
|
||||||
|
rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius);
|
||||||
|
rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||||
|
{
|
||||||
|
rlEnableTexture(GetDefaultTexture().id); // Default white texture
|
||||||
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
|
for (int i = 0; i < 360; i += 20)
|
||||||
|
{
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
rlVertex2f(center.x, center.y);
|
||||||
|
rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius);
|
||||||
|
rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius);
|
||||||
|
rlVertex2f(center.x + sinf(DEG2RAD*(i + 20))*radius, center.y + cosf(DEG2RAD*(i + 20))*radius);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlDisableTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw circle outline
|
||||||
|
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
||||||
|
for (int i = 0; i < 360; i += 10)
|
||||||
|
{
|
||||||
|
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
||||||
|
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled rectangle
|
||||||
|
void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
||||||
|
{
|
||||||
|
Vector2 position = { (float)posX, (float)posY };
|
||||||
|
Vector2 size = { (float)width, (float)height };
|
||||||
|
|
||||||
|
DrawRectangleV(position, size, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled rectangle
|
||||||
|
void DrawRectangleRec(Rectangle rec, Color color)
|
||||||
|
{
|
||||||
|
DrawRectangle(rec.x, rec.y, rec.width, rec.height, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a gradient-filled rectangle
|
||||||
|
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
||||||
|
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX, posY);
|
||||||
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX, posY + height);
|
||||||
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
|
||||||
|
|
||||||
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX, posY);
|
||||||
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX + width, posY + height);
|
||||||
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(posX + width, posY);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a color-filled rectangle (Vector version)
|
||||||
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
||||||
|
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
||||||
|
{
|
||||||
|
if (rlGetVersion() == OPENGL_11)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
rlVertex2i(position.x, position.y);
|
||||||
|
rlVertex2i(position.x, position.y + size.y);
|
||||||
|
rlVertex2i(position.x + size.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlVertex2i(position.x, position.y);
|
||||||
|
rlVertex2i(position.x + size.x, position.y + size.y);
|
||||||
|
rlVertex2i(position.x + size.x, position.y);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||||
|
{
|
||||||
|
rlEnableTexture(GetDefaultTexture().id); // Default white texture
|
||||||
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
rlTexCoord2f(0.0f, 0.0f);
|
||||||
|
rlVertex2f(position.x, position.y);
|
||||||
|
|
||||||
|
rlTexCoord2f(0.0f, 1.0f);
|
||||||
|
rlVertex2f(position.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlTexCoord2f(1.0f, 1.0f);
|
||||||
|
rlVertex2f(position.x + size.x, position.y + size.y);
|
||||||
|
|
||||||
|
rlTexCoord2f(1.0f, 0.0f);
|
||||||
|
rlVertex2f(position.x + size.x, position.y);
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlDisableTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw rectangle outline
|
||||||
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
||||||
|
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
||||||
|
{
|
||||||
|
if (rlGetVersion() == OPENGL_11)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2i(posX + 1, posY + 1);
|
||||||
|
rlVertex2i(posX + width, posY + 1);
|
||||||
|
|
||||||
|
rlVertex2i(posX + width, posY + 1);
|
||||||
|
rlVertex2i(posX + width, posY + height);
|
||||||
|
|
||||||
|
rlVertex2i(posX + width, posY + height);
|
||||||
|
rlVertex2i(posX + 1, posY + height);
|
||||||
|
|
||||||
|
rlVertex2i(posX + 1, posY + height);
|
||||||
|
rlVertex2i(posX + 1, posY + 1);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||||
|
{
|
||||||
|
DrawRectangle(posX, posY, width, 1, color);
|
||||||
|
DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
|
||||||
|
DrawRectangle(posX, posY + height - 1, width, 1, color);
|
||||||
|
DrawRectangle(posX, posY + 1, 1, height - 2, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a triangle
|
||||||
|
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
|
{
|
||||||
|
if (rlGetVersion() == OPENGL_11)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20))
|
||||||
|
{
|
||||||
|
rlEnableTexture(GetDefaultTexture().id); // Default white texture
|
||||||
|
|
||||||
|
rlBegin(RL_QUADS);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
rlEnd();
|
||||||
|
|
||||||
|
rlDisableTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
|
||||||
|
rlVertex2f(v2.x, v2.y);
|
||||||
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
|
||||||
|
rlVertex2f(v3.x, v3.y);
|
||||||
|
rlVertex2f(v1.x, v1.y);
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a regular polygon of n sides (Vector version)
|
||||||
|
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
||||||
|
{
|
||||||
|
if (sides < 3) sides = 3;
|
||||||
|
|
||||||
|
rlPushMatrix();
|
||||||
|
rlTranslatef(center.x, center.y, 0.0);
|
||||||
|
rlRotatef(rotation, 0, 0, 1);
|
||||||
|
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
for (int i = 0; i < 360; i += 360/sides)
|
||||||
|
{
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
rlVertex2f(0, 0);
|
||||||
|
rlVertex2f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius);
|
||||||
|
rlVertex2f(sinf(DEG2RAD*(i + 360/sides))*radius, cosf(DEG2RAD*(i + 360/sides))*radius);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
rlPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a closed polygon defined by points
|
||||||
|
// NOTE: Array num elements MUST be passed as parameter to function
|
||||||
|
void DrawPolyEx(Vector2 *points, int numPoints, Color color)
|
||||||
|
{
|
||||||
|
if (numPoints >= 3)
|
||||||
|
{
|
||||||
|
rlBegin(RL_TRIANGLES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
for (int i = 1; i < numPoints - 1; i++)
|
||||||
|
{
|
||||||
|
rlVertex2f(points[0].x, points[0].y);
|
||||||
|
rlVertex2f(points[i].x, points[i].y);
|
||||||
|
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw polygon lines
|
||||||
|
// NOTE: Array num elements MUST be passed as parameter to function
|
||||||
|
void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
|
||||||
|
{
|
||||||
|
if (numPoints >= 2)
|
||||||
|
{
|
||||||
|
rlBegin(RL_LINES);
|
||||||
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
for (int i = 0; i < numPoints - 1; i++)
|
||||||
|
{
|
||||||
|
rlVertex2f(points[i].x, points[i].y);
|
||||||
|
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
||||||
|
}
|
||||||
|
rlEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition - Collision Detection functions
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Check if point is inside rectangle
|
||||||
|
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
||||||
|
{
|
||||||
|
bool collision = false;
|
||||||
|
|
||||||
|
if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
|
||||||
|
|
||||||
|
return collision;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if point is inside circle
|
||||||
|
bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
|
||||||
|
{
|
||||||
|
return CheckCollisionCircles(point, 0, center, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if point is inside a triangle defined by three points (p1, p2, p3)
|
||||||
|
bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3)
|
||||||
|
{
|
||||||
|
bool collision = false;
|
||||||
|
|
||||||
|
float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) /
|
||||||
|
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
|
||||||
|
|
||||||
|
float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) /
|
||||||
|
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
|
||||||
|
|
||||||
|
float gamma = 1.0f - alpha - beta;
|
||||||
|
|
||||||
|
if ((alpha > 0) && (beta > 0) & (gamma > 0)) collision = true;
|
||||||
|
|
||||||
|
return collision;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check collision between two rectangles
|
||||||
|
bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
|
||||||
|
{
|
||||||
|
bool collision = false;
|
||||||
|
|
||||||
|
int dx = abs((rec1.x + rec1.width/2) - (rec2.x + rec2.width/2));
|
||||||
|
int dy = abs((rec1.y + rec1.height/2) - (rec2.y + rec2.height/2));
|
||||||
|
|
||||||
|
if ((dx <= (rec1.width/2 + rec2.width/2)) && ((dy <= (rec1.height/2 + rec2.height/2)))) collision = true;
|
||||||
|
|
||||||
|
return collision;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check collision between two circles
|
||||||
|
bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
|
||||||
|
{
|
||||||
|
bool collision = false;
|
||||||
|
|
||||||
|
float dx = center2.x - center1.x; // X distance between centers
|
||||||
|
float dy = center2.y - center1.y; // Y distance between centers
|
||||||
|
|
||||||
|
float distance = sqrtf(dx*dx + dy*dy); // Distance between centers
|
||||||
|
|
||||||
|
if (distance <= (radius1 + radius2)) collision = true;
|
||||||
|
|
||||||
|
return collision;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check collision between circle and rectangle
|
||||||
|
// NOTE: Reviewed version to take into account corner limit case
|
||||||
|
bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
||||||
|
{
|
||||||
|
int recCenterX = rec.x + rec.width/2;
|
||||||
|
int recCenterY = rec.y + rec.height/2;
|
||||||
|
|
||||||
|
float dx = fabsf(center.x - recCenterX);
|
||||||
|
float dy = fabsf(center.y - recCenterY);
|
||||||
|
|
||||||
|
if (dx > ((float)rec.width/2.0f + radius)) { return false; }
|
||||||
|
if (dy > ((float)rec.height/2.0f + radius)) { return false; }
|
||||||
|
|
||||||
|
if (dx <= ((float)rec.width/2.0f)) { return true; }
|
||||||
|
if (dy <= ((float)rec.height/2.0f)) { return true; }
|
||||||
|
|
||||||
|
float cornerDistanceSq = (dx - (float)rec.width/2.0f)*(dx - (float)rec.width/2.0f) +
|
||||||
|
(dy - (float)rec.height/2.0f)*(dy - (float)rec.height/2.0f);
|
||||||
|
|
||||||
|
return (cornerDistanceSq <= (radius*radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get collision rectangle for two rectangles collision
|
||||||
|
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
||||||
|
{
|
||||||
|
Rectangle retRec = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
if (CheckCollisionRecs(rec1, rec2))
|
||||||
|
{
|
||||||
|
int dxx = abs(rec1.x - rec2.x);
|
||||||
|
int dyy = abs(rec1.y - rec2.y);
|
||||||
|
|
||||||
|
if (rec1.x <= rec2.x)
|
||||||
|
{
|
||||||
|
if (rec1.y <= rec2.y)
|
||||||
|
{
|
||||||
|
retRec.x = rec2.x;
|
||||||
|
retRec.y = rec2.y;
|
||||||
|
retRec.width = rec1.width - dxx;
|
||||||
|
retRec.height = rec1.height - dyy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retRec.x = rec2.x;
|
||||||
|
retRec.y = rec1.y;
|
||||||
|
retRec.width = rec1.width - dxx;
|
||||||
|
retRec.height = rec2.height - dyy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (rec1.y <= rec2.y)
|
||||||
|
{
|
||||||
|
retRec.x = rec1.x;
|
||||||
|
retRec.y = rec2.y;
|
||||||
|
retRec.width = rec2.width - dxx;
|
||||||
|
retRec.height = rec1.height - dyy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retRec.x = rec1.x;
|
||||||
|
retRec.y = rec1.y;
|
||||||
|
retRec.width = rec2.width - dxx;
|
||||||
|
retRec.height = rec2.height - dyy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec1.width > rec2.width)
|
||||||
|
{
|
||||||
|
if (retRec.width >= rec2.width) retRec.width = rec2.width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (retRec.width >= rec1.width) retRec.width = rec1.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec1.height > rec2.height)
|
||||||
|
{
|
||||||
|
if (retRec.height >= rec2.height) retRec.height = rec2.height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (retRec.height >= rec1.height) retRec.height = rec1.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retRec;
|
||||||
|
}
|
5010
raylib/stb_vorbis.c
Normal file
5010
raylib/stb_vorbis.c
Normal file
File diff suppressed because it is too large
Load diff
393
raylib/stb_vorbis.h
Normal file
393
raylib/stb_vorbis.h
Normal file
|
@ -0,0 +1,393 @@
|
||||||
|
// Ogg Vorbis audio decoder - v1.09 - public domain
|
||||||
|
// http://nothings.org/stb_vorbis/
|
||||||
|
//
|
||||||
|
// Original version written by Sean Barrett in 2007.
|
||||||
|
//
|
||||||
|
// Originally sponsored by RAD Game Tools. Seeking sponsored
|
||||||
|
// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
|
||||||
|
// Aras Pranckevicius, and Sean Barrett.
|
||||||
|
//
|
||||||
|
// LICENSE
|
||||||
|
//
|
||||||
|
// This software is dual-licensed to the public domain and under the following
|
||||||
|
// license: you are granted a perpetual, irrevocable license to copy, modify,
|
||||||
|
// publish, and distribute this file as you see fit.
|
||||||
|
//
|
||||||
|
// No warranty for any purpose is expressed or implied by the author (nor
|
||||||
|
// by RAD Game Tools). Report bugs and send enhancements to the author.
|
||||||
|
//
|
||||||
|
// Limitations:
|
||||||
|
//
|
||||||
|
// - floor 0 not supported (used in old ogg vorbis files pre-2004)
|
||||||
|
// - lossless sample-truncation at beginning ignored
|
||||||
|
// - cannot concatenate multiple vorbis streams
|
||||||
|
// - sample positions are 32-bit, limiting seekable 192Khz
|
||||||
|
// files to around 6 hours (Ogg supports 64-bit)
|
||||||
|
//
|
||||||
|
// Feature contributors:
|
||||||
|
// Dougall Johnson (sample-exact seeking)
|
||||||
|
//
|
||||||
|
// Bugfix/warning contributors:
|
||||||
|
// Terje Mathisen Niklas Frykholm Andy Hill
|
||||||
|
// Casey Muratori John Bolton Gargaj
|
||||||
|
// Laurent Gomila Marc LeBlanc Ronny Chevalier
|
||||||
|
// Bernhard Wodo Evan Balster alxprd@github
|
||||||
|
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
|
||||||
|
// Phillip Bennefall Rohit Thiago Goulart
|
||||||
|
// manxorist@github saga musix
|
||||||
|
//
|
||||||
|
// Partial history:
|
||||||
|
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
|
||||||
|
// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
|
||||||
|
// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
|
||||||
|
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
|
||||||
|
// some crash fixes when out of memory or with corrupt files
|
||||||
|
// fix some inappropriately signed shifts
|
||||||
|
// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
|
||||||
|
// 1.04 - 2014/08/27 - fix missing const-correct case in API
|
||||||
|
// 1.03 - 2014/08/07 - warning fixes
|
||||||
|
// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows
|
||||||
|
// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
|
||||||
|
// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
|
||||||
|
// (API change) report sample rate for decode-full-file funcs
|
||||||
|
//
|
||||||
|
// See end of file for full version history.
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// HEADER BEGINS HERE
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
|
||||||
|
#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
|
||||||
|
#define STB_VORBIS_NO_STDIO 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_STDIO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: Added to work with raylib on Android
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
#include "utils.h" // Android fopen function map
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/////////// THREAD SAFETY
|
||||||
|
|
||||||
|
// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
|
||||||
|
// them from multiple threads at the same time. However, you can have multiple
|
||||||
|
// stb_vorbis* handles and decode from them independently in multiple thrads.
|
||||||
|
|
||||||
|
|
||||||
|
/////////// MEMORY ALLOCATION
|
||||||
|
|
||||||
|
// normally stb_vorbis uses malloc() to allocate memory at startup,
|
||||||
|
// and alloca() to allocate temporary memory during a frame on the
|
||||||
|
// stack. (Memory consumption will depend on the amount of setup
|
||||||
|
// data in the file and how you set the compile flags for speed
|
||||||
|
// vs. size. In my test files the maximal-size usage is ~150KB.)
|
||||||
|
//
|
||||||
|
// You can modify the wrapper functions in the source (setup_malloc,
|
||||||
|
// setup_temp_malloc, temp_malloc) to change this behavior, or you
|
||||||
|
// can use a simpler allocation model: you pass in a buffer from
|
||||||
|
// which stb_vorbis will allocate _all_ its memory (including the
|
||||||
|
// temp memory). "open" may fail with a VORBIS_outofmem if you
|
||||||
|
// do not pass in enough data; there is no way to determine how
|
||||||
|
// much you do need except to succeed (at which point you can
|
||||||
|
// query get_info to find the exact amount required. yes I know
|
||||||
|
// this is lame).
|
||||||
|
//
|
||||||
|
// If you pass in a non-NULL buffer of the type below, allocation
|
||||||
|
// will occur from it as described above. Otherwise just pass NULL
|
||||||
|
// to use malloc()/alloca()
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *alloc_buffer;
|
||||||
|
int alloc_buffer_length_in_bytes;
|
||||||
|
} stb_vorbis_alloc;
|
||||||
|
|
||||||
|
|
||||||
|
/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES
|
||||||
|
|
||||||
|
typedef struct stb_vorbis stb_vorbis;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int sample_rate;
|
||||||
|
int channels;
|
||||||
|
|
||||||
|
unsigned int setup_memory_required;
|
||||||
|
unsigned int setup_temp_memory_required;
|
||||||
|
unsigned int temp_memory_required;
|
||||||
|
|
||||||
|
int max_frame_size;
|
||||||
|
} stb_vorbis_info;
|
||||||
|
|
||||||
|
// get general information about the file
|
||||||
|
extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
|
||||||
|
|
||||||
|
// get the last error detected (clears it, too)
|
||||||
|
extern int stb_vorbis_get_error(stb_vorbis *f);
|
||||||
|
|
||||||
|
// close an ogg vorbis file and free all memory in use
|
||||||
|
extern void stb_vorbis_close(stb_vorbis *f);
|
||||||
|
|
||||||
|
// this function returns the offset (in samples) from the beginning of the
|
||||||
|
// file that will be returned by the next decode, if it is known, or -1
|
||||||
|
// otherwise. after a flush_pushdata() call, this may take a while before
|
||||||
|
// it becomes valid again.
|
||||||
|
// NOT WORKING YET after a seek with PULLDATA API
|
||||||
|
extern int stb_vorbis_get_sample_offset(stb_vorbis *f);
|
||||||
|
|
||||||
|
// returns the current seek point within the file, or offset from the beginning
|
||||||
|
// of the memory buffer. In pushdata mode it returns 0.
|
||||||
|
extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
|
||||||
|
|
||||||
|
/////////// PUSHDATA API
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_PUSHDATA_API
|
||||||
|
|
||||||
|
// this API allows you to get blocks of data from any source and hand
|
||||||
|
// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
|
||||||
|
// you how much it used, and you have to give it the rest next time;
|
||||||
|
// and stb_vorbis may not have enough data to work with and you will
|
||||||
|
// need to give it the same data again PLUS more. Note that the Vorbis
|
||||||
|
// specification does not bound the size of an individual frame.
|
||||||
|
|
||||||
|
extern stb_vorbis *stb_vorbis_open_pushdata(
|
||||||
|
const unsigned char * datablock, int datablock_length_in_bytes,
|
||||||
|
int *datablock_memory_consumed_in_bytes,
|
||||||
|
int *error,
|
||||||
|
const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create a vorbis decoder by passing in the initial data block containing
|
||||||
|
// the ogg&vorbis headers (you don't need to do parse them, just provide
|
||||||
|
// the first N bytes of the file--you're told if it's not enough, see below)
|
||||||
|
// on success, returns an stb_vorbis *, does not set error, returns the amount of
|
||||||
|
// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
|
||||||
|
// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
|
||||||
|
// if returns NULL and *error is VORBIS_need_more_data, then the input block was
|
||||||
|
// incomplete and you need to pass in a larger block from the start of the file
|
||||||
|
|
||||||
|
extern int stb_vorbis_decode_frame_pushdata(
|
||||||
|
stb_vorbis *f,
|
||||||
|
const unsigned char *datablock, int datablock_length_in_bytes,
|
||||||
|
int *channels, // place to write number of float * buffers
|
||||||
|
float ***output, // place to write float ** array of float * buffers
|
||||||
|
int *samples // place to write number of output samples
|
||||||
|
);
|
||||||
|
// decode a frame of audio sample data if possible from the passed-in data block
|
||||||
|
//
|
||||||
|
// return value: number of bytes we used from datablock
|
||||||
|
//
|
||||||
|
// possible cases:
|
||||||
|
// 0 bytes used, 0 samples output (need more data)
|
||||||
|
// N bytes used, 0 samples output (resynching the stream, keep going)
|
||||||
|
// N bytes used, M samples output (one frame of data)
|
||||||
|
// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
|
||||||
|
// frame, because Vorbis always "discards" the first frame.
|
||||||
|
//
|
||||||
|
// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
|
||||||
|
// instead only datablock_length_in_bytes-3 or less. This is because it wants
|
||||||
|
// to avoid missing parts of a page header if they cross a datablock boundary,
|
||||||
|
// without writing state-machiney code to record a partial detection.
|
||||||
|
//
|
||||||
|
// The number of channels returned are stored in *channels (which can be
|
||||||
|
// NULL--it is always the same as the number of channels reported by
|
||||||
|
// get_info). *output will contain an array of float* buffers, one per
|
||||||
|
// channel. In other words, (*output)[0][0] contains the first sample from
|
||||||
|
// the first channel, and (*output)[1][0] contains the first sample from
|
||||||
|
// the second channel.
|
||||||
|
|
||||||
|
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
|
||||||
|
// inform stb_vorbis that your next datablock will not be contiguous with
|
||||||
|
// previous ones (e.g. you've seeked in the data); future attempts to decode
|
||||||
|
// frames will cause stb_vorbis to resynchronize (as noted above), and
|
||||||
|
// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
|
||||||
|
// will begin decoding the _next_ frame.
|
||||||
|
//
|
||||||
|
// if you want to seek using pushdata, you need to seek in your file, then
|
||||||
|
// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
|
||||||
|
// decoding is returning you data, call stb_vorbis_get_sample_offset, and
|
||||||
|
// if you don't like the result, seek your file again and repeat.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
////////// PULLING INPUT API
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_PULLDATA_API
|
||||||
|
// This API assumes stb_vorbis is allowed to pull data from a source--
|
||||||
|
// either a block of memory containing the _entire_ vorbis stream, or a
|
||||||
|
// FILE * that you or it create, or possibly some other reading mechanism
|
||||||
|
// if you go modify the source to replace the FILE * case with some kind
|
||||||
|
// of callback to your code. (But if you don't support seeking, you may
|
||||||
|
// just want to go ahead and use pushdata.)
|
||||||
|
|
||||||
|
#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
|
||||||
|
extern int stb_vorbis_decode_filename(const char *filename, int *channels, int *sample_rate, short **output);
|
||||||
|
#endif
|
||||||
|
#if !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
|
||||||
|
extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *channels, int *sample_rate, short **output);
|
||||||
|
#endif
|
||||||
|
// decode an entire file and output the data interleaved into a malloc()ed
|
||||||
|
// buffer stored in *output. The return value is the number of samples
|
||||||
|
// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
|
||||||
|
// When you're done with it, just free() the pointer returned in *output.
|
||||||
|
|
||||||
|
extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
|
||||||
|
// this must be the entire stream!). on failure, returns NULL and sets *error
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_STDIO
|
||||||
|
extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create an ogg vorbis decoder from a filename via fopen(). on failure,
|
||||||
|
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
|
||||||
|
|
||||||
|
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer);
|
||||||
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||||
|
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
||||||
|
// note that stb_vorbis must "own" this stream; if you seek it in between
|
||||||
|
// calls to stb_vorbis, it will become confused. Morever, if you attempt to
|
||||||
|
// perform stb_vorbis_seek_*() operations on this file, it will assume it
|
||||||
|
// owns the _entire_ rest of the file after the start point. Use the next
|
||||||
|
// function, stb_vorbis_open_file_section(), to limit it.
|
||||||
|
|
||||||
|
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
|
||||||
|
int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);
|
||||||
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
||||||
|
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
|
||||||
|
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
|
||||||
|
// this stream; if you seek it in between calls to stb_vorbis, it will become
|
||||||
|
// confused.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
|
||||||
|
extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
|
||||||
|
// these functions seek in the Vorbis file to (approximately) 'sample_number'.
|
||||||
|
// after calling seek_frame(), the next call to get_frame_*() will include
|
||||||
|
// the specified sample. after calling stb_vorbis_seek(), the next call to
|
||||||
|
// stb_vorbis_get_samples_* will start with the specified sample. If you
|
||||||
|
// do not need to seek to EXACTLY the target sample when using get_samples_*,
|
||||||
|
// you can also use seek_frame().
|
||||||
|
|
||||||
|
extern void stb_vorbis_seek_start(stb_vorbis *f);
|
||||||
|
// this function is equivalent to stb_vorbis_seek(f,0)
|
||||||
|
|
||||||
|
extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
|
||||||
|
extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
|
||||||
|
// these functions return the total length of the vorbis stream
|
||||||
|
|
||||||
|
extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);
|
||||||
|
// decode the next frame and return the number of samples. the number of
|
||||||
|
// channels returned are stored in *channels (which can be NULL--it is always
|
||||||
|
// the same as the number of channels reported by get_info). *output will
|
||||||
|
// contain an array of float* buffers, one per channel. These outputs will
|
||||||
|
// be overwritten on the next call to stb_vorbis_get_frame_*.
|
||||||
|
//
|
||||||
|
// You generally should not intermix calls to stb_vorbis_get_frame_*()
|
||||||
|
// and stb_vorbis_get_samples_*(), since the latter calls the former.
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
|
||||||
|
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
|
||||||
|
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
|
||||||
|
#endif
|
||||||
|
// decode the next frame and return the number of *samples* per channel.
|
||||||
|
// Note that for interleaved data, you pass in the number of shorts (the
|
||||||
|
// size of your array), but the return value is the number of samples per
|
||||||
|
// channel, not the total number of samples.
|
||||||
|
//
|
||||||
|
// The data is coerced to the number of channels you request according to the
|
||||||
|
// channel coercion rules (see below). You must pass in the size of your
|
||||||
|
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
|
||||||
|
// The maximum buffer size needed can be gotten from get_info(); however,
|
||||||
|
// the Vorbis I specification implies an absolute maximum of 4096 samples
|
||||||
|
// per channel.
|
||||||
|
|
||||||
|
// Channel coercion rules:
|
||||||
|
// Let M be the number of channels requested, and N the number of channels present,
|
||||||
|
// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
|
||||||
|
// and stereo R be the sum of all R and center channels (channel assignment from the
|
||||||
|
// vorbis spec).
|
||||||
|
// M N output
|
||||||
|
// 1 k sum(Ck) for all k
|
||||||
|
// 2 * stereo L, stereo R
|
||||||
|
// k l k > l, the first l channels, then 0s
|
||||||
|
// k l k <= l, the first k channels
|
||||||
|
// Note that this is not _good_ surround etc. mixing at all! It's just so
|
||||||
|
// you get something useful.
|
||||||
|
|
||||||
|
extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);
|
||||||
|
extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);
|
||||||
|
// gets num_samples samples, not necessarily on a frame boundary--this requires
|
||||||
|
// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
|
||||||
|
// Returns the number of samples stored per channel; it may be less than requested
|
||||||
|
// at the end of the file. If there are no more samples in the file, returns 0.
|
||||||
|
|
||||||
|
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
|
||||||
|
extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);
|
||||||
|
extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);
|
||||||
|
#endif
|
||||||
|
// gets num_samples samples, not necessarily on a frame boundary--this requires
|
||||||
|
// buffering so you have to supply the buffers. Applies the coercion rules above
|
||||||
|
// to produce 'channels' channels. Returns the number of samples stored per channel;
|
||||||
|
// it may be less than requested at the end of the file. If there are no more
|
||||||
|
// samples in the file, returns 0.
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////// ERROR CODES
|
||||||
|
|
||||||
|
enum STBVorbisError
|
||||||
|
{
|
||||||
|
VORBIS__no_error,
|
||||||
|
|
||||||
|
VORBIS_need_more_data=1, // not a real error
|
||||||
|
|
||||||
|
VORBIS_invalid_api_mixing, // can't mix API modes
|
||||||
|
VORBIS_outofmem, // not enough memory
|
||||||
|
VORBIS_feature_not_supported, // uses floor 0
|
||||||
|
VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small
|
||||||
|
VORBIS_file_open_failure, // fopen() failed
|
||||||
|
VORBIS_seek_without_length, // can't seek in unknown-length file
|
||||||
|
|
||||||
|
VORBIS_unexpected_eof=10, // file is truncated?
|
||||||
|
VORBIS_seek_invalid, // seek past EOF
|
||||||
|
|
||||||
|
// decoding errors (corrupt/invalid stream) -- you probably
|
||||||
|
// don't care about the exact details of these
|
||||||
|
|
||||||
|
// vorbis errors:
|
||||||
|
VORBIS_invalid_setup=20,
|
||||||
|
VORBIS_invalid_stream,
|
||||||
|
|
||||||
|
// ogg errors:
|
||||||
|
VORBIS_missing_capture_pattern=30,
|
||||||
|
VORBIS_invalid_stream_structure_version,
|
||||||
|
VORBIS_continued_packet_flag_invalid,
|
||||||
|
VORBIS_incorrect_stream_serial_number,
|
||||||
|
VORBIS_invalid_first_page,
|
||||||
|
VORBIS_bad_packet_type,
|
||||||
|
VORBIS_cant_find_last_page,
|
||||||
|
VORBIS_seek_failed
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H
|
||||||
|
//
|
||||||
|
// HEADER ENDS HERE
|
||||||
|
//
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
999
raylib/text.c
Normal file
999
raylib/text.c
Normal file
|
@ -0,0 +1,999 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib.text
|
||||||
|
*
|
||||||
|
* Basic functions to load SpriteFonts and draw Text
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* stb_truetype - Load TTF file and rasterize characters data
|
||||||
|
*
|
||||||
|
* Module Configuration Flags:
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#include "raylib.h"
|
||||||
|
|
||||||
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
|
#include <string.h> // Required for: strlen()
|
||||||
|
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
|
||||||
|
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
|
||||||
|
|
||||||
|
#include "utils.h" // Required for: GetExtension()
|
||||||
|
|
||||||
|
// Following libs are used on LoadTTF()
|
||||||
|
#define STBTT_STATIC // Define stb_truetype functions static to this module
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap()
|
||||||
|
|
||||||
|
// Rectangle packing functions (not used at the moment)
|
||||||
|
//#define STB_RECT_PACK_IMPLEMENTATION
|
||||||
|
//#include "stb_rect_pack.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Defines and Macros
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#define MAX_FORMATTEXT_LENGTH 64
|
||||||
|
#define MAX_SUBTEXT_LENGTH 64
|
||||||
|
|
||||||
|
#define BIT_CHECK(a,b) ((a) & (1 << (b)))
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// ...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global variables
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static SpriteFont defaultFont; // Default font provided by raylib
|
||||||
|
// NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core]
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Other Modules Functions Declaration (required by text)
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
static int GetCharIndex(SpriteFont font, int letter);
|
||||||
|
|
||||||
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
||||||
|
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
|
||||||
|
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||||
|
static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int *fontChars); // Load spritefont from TTF data
|
||||||
|
|
||||||
|
extern void LoadDefaultFont(void);
|
||||||
|
extern void UnloadDefaultFont(void);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
extern void LoadDefaultFont(void)
|
||||||
|
{
|
||||||
|
// NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement
|
||||||
|
// http://www.utf8-chartable.de/unicode-utf8-table.pl
|
||||||
|
|
||||||
|
defaultFont.numChars = 224; // Number of chars included in our default font
|
||||||
|
|
||||||
|
// Default font is directly defined here (data generated from a sprite font image)
|
||||||
|
// This way, we reconstruct SpriteFont without creating large global variables
|
||||||
|
// This data is automatically allocated to Stack and automatically deallocated at the end of this function
|
||||||
|
int defaultFontData[512] = {
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200020, 0x0001b000, 0x00000000, 0x00000000, 0x8ef92520, 0x00020a00, 0x7dbe8000, 0x1f7df45f,
|
||||||
|
0x4a2bf2a0, 0x0852091e, 0x41224000, 0x10041450, 0x2e292020, 0x08220812, 0x41222000, 0x10041450, 0x10f92020, 0x3efa084c, 0x7d22103c, 0x107df7de,
|
||||||
|
0xe8a12020, 0x08220832, 0x05220800, 0x10450410, 0xa4a3f000, 0x08520832, 0x05220400, 0x10450410, 0xe2f92020, 0x0002085e, 0x7d3e0281, 0x107df41f,
|
||||||
|
0x00200000, 0x8001b000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0000fbe, 0xfbf7e00f, 0x5fbf7e7d, 0x0050bee8, 0x440808a2, 0x0a142fe8, 0x50810285, 0x0050a048,
|
||||||
|
0x49e428a2, 0x0a142828, 0x40810284, 0x0048a048, 0x10020fbe, 0x09f7ebaf, 0xd89f3e84, 0x0047a04f, 0x09e48822, 0x0a142aa1, 0x50810284, 0x0048a048,
|
||||||
|
0x04082822, 0x0a142fa0, 0x50810285, 0x0050a248, 0x00008fbe, 0xfbf42021, 0x5f817e7d, 0x07d09ce8, 0x00008000, 0x00000fe0, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000c0180,
|
||||||
|
0xdfbf4282, 0x0bfbf7ef, 0x42850505, 0x004804bf, 0x50a142c6, 0x08401428, 0x42852505, 0x00a808a0, 0x50a146aa, 0x08401428, 0x42852505, 0x00081090,
|
||||||
|
0x5fa14a92, 0x0843f7e8, 0x7e792505, 0x00082088, 0x40a15282, 0x08420128, 0x40852489, 0x00084084, 0x40a16282, 0x0842022a, 0x40852451, 0x00088082,
|
||||||
|
0xc0bf4282, 0xf843f42f, 0x7e85fc21, 0x3e0900bf, 0x00000000, 0x00000004, 0x00000000, 0x000c0180, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000402, 0x41482000, 0x00000000, 0x00000800,
|
||||||
|
0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820,
|
||||||
|
0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0,
|
||||||
|
0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000,
|
||||||
|
0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000,
|
||||||
|
0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000,
|
||||||
|
0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03,
|
||||||
|
0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202,
|
||||||
|
0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002,
|
||||||
|
0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00800702, 0x1848a0c2, 0x84010000, 0x02920921, 0x01042642, 0x00005121, 0x42023f7f, 0x00291002,
|
||||||
|
0xefc01422, 0x7efdfbf7, 0xefdfa109, 0x03bbbbf7, 0x28440f12, 0x42850a14, 0x20408109, 0x01111010, 0x28440408, 0x42850a14, 0x2040817f, 0x01111010,
|
||||||
|
0xefc78204, 0x7efdfbf7, 0xe7cf8109, 0x011111f3, 0x2850a932, 0x42850a14, 0x2040a109, 0x01111010, 0x2850b840, 0x42850a14, 0xefdfbf79, 0x03bbbbf7,
|
||||||
|
0x001fa020, 0x00000000, 0x00001000, 0x00000000, 0x00002070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x08022800, 0x00012283, 0x02430802, 0x01010001, 0x8404147c, 0x20000144, 0x80048404, 0x00823f08, 0xdfbf4284, 0x7e03f7ef, 0x142850a1, 0x0000210a,
|
||||||
|
0x50a14684, 0x528a1428, 0x142850a1, 0x03efa17a, 0x50a14a9e, 0x52521428, 0x142850a1, 0x02081f4a, 0x50a15284, 0x4a221428, 0xf42850a1, 0x03efa14b,
|
||||||
|
0x50a16284, 0x4a521428, 0x042850a1, 0x0228a17a, 0xdfbf427c, 0x7e8bf7ef, 0xf7efdfbf, 0x03efbd0b, 0x00000000, 0x04000000, 0x00000000, 0x00000008,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200508, 0x00840400, 0x11458122, 0x00014210,
|
||||||
|
0x00514294, 0x51420800, 0x20a22a94, 0x0050a508, 0x00200000, 0x00000000, 0x00050000, 0x08000000, 0xfefbefbe, 0xfbefbefb, 0xfbeb9114, 0x00fbefbe,
|
||||||
|
0x20820820, 0x8a28a20a, 0x8a289114, 0x3e8a28a2, 0xfefbefbe, 0xfbefbe0b, 0x8a289114, 0x008a28a2, 0x228a28a2, 0x08208208, 0x8a289114, 0x088a28a2,
|
||||||
|
0xfefbefbe, 0xfbefbefb, 0xfa2f9114, 0x00fbefbe, 0x00000000, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00210100, 0x00000004, 0x00000000, 0x00000000, 0x14508200, 0x00001402, 0x00000000, 0x00000000,
|
||||||
|
0x00000010, 0x00000020, 0x00000000, 0x00000000, 0xa28a28be, 0x00002228, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000,
|
||||||
|
0xa28a28aa, 0x000022a8, 0x00000000, 0x00000000, 0xa28a28aa, 0x000022e8, 0x00000000, 0x00000000, 0xbefbefbe, 0x00003e2f, 0x00000000, 0x00000000,
|
||||||
|
0x00000004, 0x00002028, 0x00000000, 0x00000000, 0x80000000, 0x00003e0f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||||
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
|
||||||
|
|
||||||
|
int charsHeight = 10;
|
||||||
|
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
|
||||||
|
|
||||||
|
int charsWidth[224] = { 3, 1, 4, 6, 5, 7, 6, 2, 3, 3, 5, 5, 2, 4, 1, 7, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 3, 4, 3, 6,
|
||||||
|
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
|
||||||
|
2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, 1, 5, 5, 5, 7, 1, 5, 3, 7, 3, 5, 4, 1, 7, 4, 3, 5, 3, 3, 2, 5, 6, 1, 2, 2, 3, 5, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 7, 6, 6, 6, 6, 6, 3, 3, 3, 3, 7, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 6, 6, 6, 4, 6,
|
||||||
|
5, 5, 5, 5, 5, 5, 9, 5, 5, 5, 5, 5, 2, 2, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5 };
|
||||||
|
|
||||||
|
// Re-construct image from defaultFontData and generate OpenGL texture
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
int imWidth = 128;
|
||||||
|
int imHeight = 128;
|
||||||
|
|
||||||
|
Color *imagePixels = (Color *)malloc(imWidth*imHeight*sizeof(Color));
|
||||||
|
|
||||||
|
for (int i = 0; i < imWidth*imHeight; i++) imagePixels[i] = BLANK; // Initialize array
|
||||||
|
|
||||||
|
int counter = 0; // Font data elements counter
|
||||||
|
|
||||||
|
// Fill imgData with defaultFontData (convert from bit to pixel!)
|
||||||
|
for (int i = 0; i < imWidth*imHeight; i += 32)
|
||||||
|
{
|
||||||
|
for (int j = 31; j >= 0; j--)
|
||||||
|
{
|
||||||
|
if (BIT_CHECK(defaultFontData[counter], j)) imagePixels[i+j] = WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
if (counter > 512) counter = 0; // Security check...
|
||||||
|
}
|
||||||
|
|
||||||
|
//FILE *myimage = fopen("default_font.raw", "wb");
|
||||||
|
//fwrite(image.pixels, 1, 128*128*4, myimage);
|
||||||
|
//fclose(myimage);
|
||||||
|
|
||||||
|
Image image = LoadImageEx(imagePixels, imWidth, imHeight);
|
||||||
|
ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
|
||||||
|
|
||||||
|
free(imagePixels);
|
||||||
|
|
||||||
|
defaultFont.texture = LoadTextureFromImage(image);
|
||||||
|
UnloadImage(image);
|
||||||
|
|
||||||
|
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int));
|
||||||
|
defaultFont.charRecs = (Rectangle *)malloc(defaultFont.numChars*sizeof(Rectangle)); // Allocate space for our character rectangle data
|
||||||
|
// This memory should be freed at end! --> Done on CloseWindow()
|
||||||
|
|
||||||
|
defaultFont.charOffsets = (Vector2 *)malloc(defaultFont.numChars*sizeof(Vector2));
|
||||||
|
defaultFont.charAdvanceX = (int *)malloc(defaultFont.numChars*sizeof(int));
|
||||||
|
|
||||||
|
int currentLine = 0;
|
||||||
|
int currentPosX = charsDivisor;
|
||||||
|
int testPosX = charsDivisor;
|
||||||
|
|
||||||
|
for (int i = 0; i < defaultFont.numChars; i++)
|
||||||
|
{
|
||||||
|
defaultFont.charValues[i] = 32 + i; // First char is 32
|
||||||
|
|
||||||
|
defaultFont.charRecs[i].x = currentPosX;
|
||||||
|
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
|
||||||
|
defaultFont.charRecs[i].width = charsWidth[i];
|
||||||
|
defaultFont.charRecs[i].height = charsHeight;
|
||||||
|
|
||||||
|
testPosX += (defaultFont.charRecs[i].width + charsDivisor);
|
||||||
|
|
||||||
|
if (testPosX >= defaultFont.texture.width)
|
||||||
|
{
|
||||||
|
currentLine++;
|
||||||
|
currentPosX = 2*charsDivisor + charsWidth[i];
|
||||||
|
testPosX = currentPosX;
|
||||||
|
|
||||||
|
defaultFont.charRecs[i].x = charsDivisor;
|
||||||
|
defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor);
|
||||||
|
}
|
||||||
|
else currentPosX = testPosX;
|
||||||
|
|
||||||
|
// NOTE: On default font character offsets and xAdvance are not required
|
||||||
|
defaultFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
|
||||||
|
defaultFont.charAdvanceX[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultFont.size = defaultFont.charRecs[0].height;
|
||||||
|
|
||||||
|
TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void UnloadDefaultFont(void)
|
||||||
|
{
|
||||||
|
UnloadTexture(defaultFont.texture);
|
||||||
|
free(defaultFont.charValues);
|
||||||
|
free(defaultFont.charRecs);
|
||||||
|
free(defaultFont.charOffsets);
|
||||||
|
free(defaultFont.charAdvanceX);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the default font, useful to be used with extended parameters
|
||||||
|
SpriteFont GetDefaultFont()
|
||||||
|
{
|
||||||
|
return defaultFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load SpriteFont from file into GPU memory (VRAM)
|
||||||
|
SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
|
{
|
||||||
|
// Default hardcoded values for ttf file loading
|
||||||
|
#define DEFAULT_TTF_FONTSIZE 32 // Font first character (32 - space)
|
||||||
|
#define DEFAULT_TTF_NUMCHARS 95 // ASCII 32..126 is 95 glyphs
|
||||||
|
#define DEFAULT_FIRST_CHAR 32 // Expected first char for image spritefont
|
||||||
|
|
||||||
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
|
// Check file extension
|
||||||
|
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
||||||
|
else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadSpriteFontTTF(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL);
|
||||||
|
else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Image image = LoadImage(fileName);
|
||||||
|
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, DEFAULT_FIRST_CHAR);
|
||||||
|
UnloadImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spriteFont.texture.id == 0)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
||||||
|
spriteFont = GetDefaultFont();
|
||||||
|
}
|
||||||
|
else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance)
|
||||||
|
|
||||||
|
return spriteFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load SpriteFont from TTF font file with generation parameters
|
||||||
|
// NOTE: You can pass an array with desired characters, those characters should be available in the font
|
||||||
|
// if array is NULL, default char set is selected 32..126
|
||||||
|
SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
|
||||||
|
{
|
||||||
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
|
if (strcmp(GetExtension(fileName),"ttf") == 0)
|
||||||
|
{
|
||||||
|
if ((fontChars == NULL) || (numChars == 0))
|
||||||
|
{
|
||||||
|
int totalChars = 95; // Default charset [32..126]
|
||||||
|
|
||||||
|
int *defaultFontChars = (int *)malloc(totalChars*sizeof(int));
|
||||||
|
|
||||||
|
for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32]
|
||||||
|
|
||||||
|
spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars);
|
||||||
|
}
|
||||||
|
else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spriteFont.texture.id == 0)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName);
|
||||||
|
spriteFont = GetDefaultFont();
|
||||||
|
}
|
||||||
|
|
||||||
|
return spriteFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload SpriteFont from GPU memory (VRAM)
|
||||||
|
void UnloadSpriteFont(SpriteFont spriteFont)
|
||||||
|
{
|
||||||
|
// NOTE: Make sure spriteFont is not default font (fallback)
|
||||||
|
if (spriteFont.texture.id != defaultFont.texture.id)
|
||||||
|
{
|
||||||
|
UnloadTexture(spriteFont.texture);
|
||||||
|
free(spriteFont.charValues);
|
||||||
|
free(spriteFont.charRecs);
|
||||||
|
free(spriteFont.charOffsets);
|
||||||
|
free(spriteFont.charAdvanceX);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "Unloaded sprite font data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text (using default font)
|
||||||
|
// NOTE: fontSize work like in any drawing program but if fontSize is lower than font-base-size, then font-base-size is used
|
||||||
|
// NOTE: chars spacing is proportional to fontSize
|
||||||
|
void DrawText(const char *text, int posX, int posY, int fontSize, Color color)
|
||||||
|
{
|
||||||
|
// Check if default font has been loaded
|
||||||
|
if (defaultFont.texture.id != 0)
|
||||||
|
{
|
||||||
|
Vector2 position = { (float)posX, (float)posY };
|
||||||
|
|
||||||
|
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||||
|
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||||
|
int spacing = fontSize/defaultFontSize;
|
||||||
|
|
||||||
|
DrawTextEx(GetDefaultFont(), text, position, (float)fontSize, spacing, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text using SpriteFont
|
||||||
|
// NOTE: chars spacing is NOT proportional to fontSize
|
||||||
|
void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float fontSize, int spacing, Color tint)
|
||||||
|
{
|
||||||
|
int length = strlen(text);
|
||||||
|
int textOffsetX = 0; // Offset between characters
|
||||||
|
int textOffsetY = 0; // Required for line break!
|
||||||
|
float scaleFactor;
|
||||||
|
|
||||||
|
unsigned char letter; // Current character
|
||||||
|
int index; // Index position in sprite font
|
||||||
|
|
||||||
|
scaleFactor = fontSize/spriteFont.size;
|
||||||
|
|
||||||
|
// NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly
|
||||||
|
// written in C code files (codified by default as UTF-8)
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
if ((unsigned char)text[i] == '\n')
|
||||||
|
{
|
||||||
|
// NOTE: Fixed line spacing of 1.5 lines
|
||||||
|
textOffsetY += (int)((spriteFont.size + spriteFont.size/2)*scaleFactor);
|
||||||
|
textOffsetX = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK!
|
||||||
|
{
|
||||||
|
// Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿)
|
||||||
|
letter = (unsigned char)text[i + 1];
|
||||||
|
index = GetCharIndex(spriteFont, (int)letter);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else if ((unsigned char)text[i] == 0xc3) // UTF-8 encoding identification HACK!
|
||||||
|
{
|
||||||
|
// Support UTF-8 encoded values from [0xc3 0x80](À) -> [0xc3 0xbf](ÿ)
|
||||||
|
letter = (unsigned char)text[i + 1];
|
||||||
|
index = GetCharIndex(spriteFont, (int)letter + 64);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else index = GetCharIndex(spriteFont, (int)text[i]);
|
||||||
|
|
||||||
|
DrawTexturePro(spriteFont.texture, spriteFont.charRecs[index],
|
||||||
|
(Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor,
|
||||||
|
position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor,
|
||||||
|
spriteFont.charRecs[index].width*scaleFactor,
|
||||||
|
spriteFont.charRecs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint);
|
||||||
|
|
||||||
|
if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (int)(spriteFont.charRecs[index].width*scaleFactor + spacing);
|
||||||
|
else textOffsetX += (int)(spriteFont.charAdvanceX[index]*scaleFactor + spacing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formatting of text with variables to 'embed'
|
||||||
|
const char *FormatText(const char *text, ...)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_FORMATTEXT_LENGTH];
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, text);
|
||||||
|
vsprintf(buffer, text, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a piece of a text string
|
||||||
|
const char *SubText(const char *text, int position, int length)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_SUBTEXT_LENGTH];
|
||||||
|
int textLength = strlen(text);
|
||||||
|
|
||||||
|
if (position >= textLength)
|
||||||
|
{
|
||||||
|
position = textLength - 1;
|
||||||
|
length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length >= textLength) length = textLength;
|
||||||
|
|
||||||
|
for (int c = 0 ; c < length ; c++)
|
||||||
|
{
|
||||||
|
*(buffer+c) = *(text+position);
|
||||||
|
text++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(buffer+length) = '\0';
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measure string width for default font
|
||||||
|
int MeasureText(const char *text, int fontSize)
|
||||||
|
{
|
||||||
|
Vector2 vec = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
// Check if default font has been loaded
|
||||||
|
if (defaultFont.texture.id != 0)
|
||||||
|
{
|
||||||
|
int defaultFontSize = 10; // Default Font chars height in pixel
|
||||||
|
if (fontSize < defaultFontSize) fontSize = defaultFontSize;
|
||||||
|
int spacing = fontSize/defaultFontSize;
|
||||||
|
|
||||||
|
vec = MeasureTextEx(GetDefaultFont(), text, (float)fontSize, spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int)vec.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Measure string size for SpriteFont
|
||||||
|
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing)
|
||||||
|
{
|
||||||
|
int len = strlen(text);
|
||||||
|
int tempLen = 0; // Used to count longer text line num chars
|
||||||
|
int lenCounter = 0;
|
||||||
|
|
||||||
|
float textWidth = 0;
|
||||||
|
float tempTextWidth = 0; // Used to count longer text line width
|
||||||
|
|
||||||
|
float textHeight = (float)spriteFont.size;
|
||||||
|
float scaleFactor = fontSize/(float)spriteFont.size;
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
lenCounter++;
|
||||||
|
|
||||||
|
if (text[i] != '\n')
|
||||||
|
{
|
||||||
|
int index = GetCharIndex(spriteFont, (int)text[i]);
|
||||||
|
|
||||||
|
if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index];
|
||||||
|
else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
|
lenCounter = 0;
|
||||||
|
textWidth = 0;
|
||||||
|
textHeight += ((float)spriteFont.size*1.5f); // NOTE: Fixed line spacing of 1.5 lines
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempLen < lenCounter) tempLen = lenCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempTextWidth < textWidth) tempTextWidth = textWidth;
|
||||||
|
|
||||||
|
Vector2 vec;
|
||||||
|
vec.x = tempTextWidth*scaleFactor + (float)((tempLen - 1)*spacing); // Adds chars spacing to measure
|
||||||
|
vec.y = textHeight*scaleFactor;
|
||||||
|
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows current FPS on top-left corner
|
||||||
|
// NOTE: Uses default font
|
||||||
|
void DrawFPS(int posX, int posY)
|
||||||
|
{
|
||||||
|
// NOTE: We have rounding errors every frame, so it oscillates a lot
|
||||||
|
DrawText(FormatText("%2i FPS", GetFPS()), posX, posY, 20, LIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static int GetCharIndex(SpriteFont font, int letter)
|
||||||
|
{
|
||||||
|
#define UNORDERED_CHARSET
|
||||||
|
#if defined(UNORDERED_CHARSET)
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < font.numChars; i++)
|
||||||
|
{
|
||||||
|
if (font.charValues[i] == letter)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
#else
|
||||||
|
return (letter - 32);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load an Image font file (XNA style)
|
||||||
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||||
|
{
|
||||||
|
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
|
||||||
|
|
||||||
|
int charSpacing = 0;
|
||||||
|
int lineSpacing = 0;
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
// Default number of characters supported
|
||||||
|
#define MAX_FONTCHARS 256
|
||||||
|
|
||||||
|
// We allocate a temporal arrays for chars data measures,
|
||||||
|
// once we get the actual number of chars, we copy data to a sized arrays
|
||||||
|
int tempCharValues[MAX_FONTCHARS];
|
||||||
|
Rectangle tempCharRecs[MAX_FONTCHARS];
|
||||||
|
|
||||||
|
Color *pixels = GetImageData(image);
|
||||||
|
|
||||||
|
// Parse image data to get charSpacing and lineSpacing
|
||||||
|
for (y = 0; y < image.height; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < image.width; x++)
|
||||||
|
{
|
||||||
|
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||||
|
}
|
||||||
|
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
charSpacing = x;
|
||||||
|
lineSpacing = y;
|
||||||
|
|
||||||
|
int charHeight = 0;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
while (!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++;
|
||||||
|
|
||||||
|
charHeight = j;
|
||||||
|
|
||||||
|
// Check array values to get characters: value, x, y, w, h
|
||||||
|
int index = 0;
|
||||||
|
int lineToRead = 0;
|
||||||
|
int xPosToRead = charSpacing;
|
||||||
|
|
||||||
|
// Parse image data to get rectangle sizes
|
||||||
|
while ((lineSpacing + lineToRead*(charHeight + lineSpacing)) < image.height)
|
||||||
|
{
|
||||||
|
while ((xPosToRead < image.width) &&
|
||||||
|
!COLOR_EQUAL((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead]), key))
|
||||||
|
{
|
||||||
|
tempCharValues[index] = firstChar + index;
|
||||||
|
|
||||||
|
tempCharRecs[index].x = xPosToRead;
|
||||||
|
tempCharRecs[index].y = lineSpacing + lineToRead*(charHeight + lineSpacing);
|
||||||
|
tempCharRecs[index].height = charHeight;
|
||||||
|
|
||||||
|
int charWidth = 0;
|
||||||
|
|
||||||
|
while (!COLOR_EQUAL(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth], key)) charWidth++;
|
||||||
|
|
||||||
|
tempCharRecs[index].width = charWidth;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
xPosToRead += (charWidth + charSpacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineToRead++;
|
||||||
|
xPosToRead = charSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
|
||||||
|
|
||||||
|
// NOTE: We need to remove key color borders from image to avoid weird
|
||||||
|
// artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR
|
||||||
|
for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK;
|
||||||
|
|
||||||
|
// Create a new image with the processed color data (key color replaced by BLANK)
|
||||||
|
Image fontClear = LoadImageEx(pixels, image.width, image.height);
|
||||||
|
|
||||||
|
free(pixels); // Free pixels array memory
|
||||||
|
|
||||||
|
// Create spritefont with all data parsed from image
|
||||||
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
|
spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture
|
||||||
|
spriteFont.numChars = index;
|
||||||
|
|
||||||
|
UnloadImage(fontClear); // Unload processed image once converted to texture
|
||||||
|
|
||||||
|
// We got tempCharValues and tempCharsRecs populated with chars data
|
||||||
|
// Now we move temp data to sized charValues and charRecs arrays
|
||||||
|
spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle));
|
||||||
|
spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int));
|
||||||
|
spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2));
|
||||||
|
spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int));
|
||||||
|
|
||||||
|
for (int i = 0; i < spriteFont.numChars; i++)
|
||||||
|
{
|
||||||
|
spriteFont.charValues[i] = tempCharValues[i];
|
||||||
|
spriteFont.charRecs[i] = tempCharRecs[i];
|
||||||
|
|
||||||
|
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
|
||||||
|
spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
|
||||||
|
spriteFont.charAdvanceX[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteFont.size = spriteFont.charRecs[0].height;
|
||||||
|
|
||||||
|
TraceLog(INFO, "Image file loaded correctly as SpriteFont");
|
||||||
|
|
||||||
|
return spriteFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load a rBMF font file (raylib BitMap Font)
|
||||||
|
static SpriteFont LoadRBMF(const char *fileName)
|
||||||
|
{
|
||||||
|
// rBMF Info Header (16 bytes)
|
||||||
|
typedef struct {
|
||||||
|
char id[4]; // rBMF file identifier
|
||||||
|
char version; // rBMF file version
|
||||||
|
// 4 MSB --> main version
|
||||||
|
// 4 LSB --> subversion
|
||||||
|
char firstChar; // First character in the font
|
||||||
|
// NOTE: Depending on charDataType, it could be useless
|
||||||
|
short imgWidth; // Image width - always POT (power-of-two)
|
||||||
|
short imgHeight; // Image height - always POT (power-of-two)
|
||||||
|
short numChars; // Number of characters contained
|
||||||
|
short charHeight; // Characters height - the same for all characters
|
||||||
|
char compType; // Compression type:
|
||||||
|
// 4 MSB --> image data compression
|
||||||
|
// 4 LSB --> chars data compression
|
||||||
|
char charsDataType; // Char data type provided
|
||||||
|
} rbmfInfoHeader;
|
||||||
|
|
||||||
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
|
rbmfInfoHeader rbmfHeader;
|
||||||
|
unsigned int *rbmfFileData = NULL;
|
||||||
|
unsigned char *rbmfCharWidthData = NULL;
|
||||||
|
|
||||||
|
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
|
||||||
|
|
||||||
|
FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode
|
||||||
|
|
||||||
|
if (rbmfFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] rBMF font file could not be opened, using default font", fileName);
|
||||||
|
|
||||||
|
spriteFont = GetDefaultFont();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight);
|
||||||
|
|
||||||
|
spriteFont.numChars = (int)rbmfHeader.numChars;
|
||||||
|
|
||||||
|
int numPixelBits = rbmfHeader.imgWidth*rbmfHeader.imgHeight/32;
|
||||||
|
|
||||||
|
rbmfFileData = (unsigned int *)malloc(numPixelBits*sizeof(unsigned int));
|
||||||
|
|
||||||
|
for (int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile);
|
||||||
|
|
||||||
|
rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars*sizeof(unsigned char));
|
||||||
|
|
||||||
|
for (int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile);
|
||||||
|
|
||||||
|
// Re-construct image from rbmfFileData
|
||||||
|
//-----------------------------------------
|
||||||
|
Color *imagePixels = (Color *)malloc(rbmfHeader.imgWidth*rbmfHeader.imgHeight*sizeof(Color));
|
||||||
|
|
||||||
|
for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i++) imagePixels[i] = BLANK; // Initialize array
|
||||||
|
|
||||||
|
int counter = 0; // Font data elements counter
|
||||||
|
|
||||||
|
// Fill image data (convert from bit to pixel!)
|
||||||
|
for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i += 32)
|
||||||
|
{
|
||||||
|
for (int j = 31; j >= 0; j--)
|
||||||
|
{
|
||||||
|
if (BIT_CHECK(rbmfFileData[counter], j)) imagePixels[i+j] = WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight);
|
||||||
|
ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
|
||||||
|
|
||||||
|
free(imagePixels);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
||||||
|
|
||||||
|
// Create spritefont with all data read from rbmf file
|
||||||
|
spriteFont.texture = LoadTextureFromImage(image);
|
||||||
|
UnloadImage(image); // Unload image data
|
||||||
|
|
||||||
|
//TraceLog(INFO, "[%s] Starting chars set reconstruction", fileName);
|
||||||
|
|
||||||
|
// Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars
|
||||||
|
spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int));
|
||||||
|
spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle));
|
||||||
|
spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2));
|
||||||
|
spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int));
|
||||||
|
|
||||||
|
int currentLine = 0;
|
||||||
|
int currentPosX = charsDivisor;
|
||||||
|
int testPosX = charsDivisor;
|
||||||
|
|
||||||
|
for (int i = 0; i < spriteFont.numChars; i++)
|
||||||
|
{
|
||||||
|
spriteFont.charValues[i] = (int)rbmfHeader.firstChar + i;
|
||||||
|
|
||||||
|
spriteFont.charRecs[i].x = currentPosX;
|
||||||
|
spriteFont.charRecs[i].y = charsDivisor + currentLine*((int)rbmfHeader.charHeight + charsDivisor);
|
||||||
|
spriteFont.charRecs[i].width = (int)rbmfCharWidthData[i];
|
||||||
|
spriteFont.charRecs[i].height = (int)rbmfHeader.charHeight;
|
||||||
|
|
||||||
|
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
|
||||||
|
spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
|
||||||
|
spriteFont.charAdvanceX[i] = 0;
|
||||||
|
|
||||||
|
testPosX += (spriteFont.charRecs[i].width + charsDivisor);
|
||||||
|
|
||||||
|
if (testPosX > spriteFont.texture.width)
|
||||||
|
{
|
||||||
|
currentLine++;
|
||||||
|
currentPosX = 2*charsDivisor + (int)rbmfCharWidthData[i];
|
||||||
|
testPosX = currentPosX;
|
||||||
|
|
||||||
|
spriteFont.charRecs[i].x = charsDivisor;
|
||||||
|
spriteFont.charRecs[i].y = charsDivisor + currentLine*(rbmfHeader.charHeight + charsDivisor);
|
||||||
|
}
|
||||||
|
else currentPosX = testPosX;
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteFont.size = spriteFont.charRecs[0].height;
|
||||||
|
|
||||||
|
TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(rbmfFile);
|
||||||
|
|
||||||
|
free(rbmfFileData); // Now we can free loaded data from RAM memory
|
||||||
|
free(rbmfCharWidthData);
|
||||||
|
|
||||||
|
return spriteFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load a BMFont file (AngelCode font file)
|
||||||
|
static SpriteFont LoadBMFont(const char *fileName)
|
||||||
|
{
|
||||||
|
#define MAX_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
SpriteFont font = { 0 };
|
||||||
|
font.texture.id = 0;
|
||||||
|
|
||||||
|
char buffer[MAX_BUFFER_SIZE];
|
||||||
|
char *searchPoint = NULL;
|
||||||
|
|
||||||
|
int fontSize = 0;
|
||||||
|
int texWidth, texHeight;
|
||||||
|
char texFileName[128];
|
||||||
|
int numChars = 0;
|
||||||
|
|
||||||
|
int base; // Useless data
|
||||||
|
|
||||||
|
FILE *fntFile;
|
||||||
|
|
||||||
|
fntFile = fopen(fileName, "rt");
|
||||||
|
|
||||||
|
if (fntFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] FNT file could not be opened", fileName);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: We skip first line, it contains no useful information
|
||||||
|
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||||
|
//searchPoint = strstr(buffer, "size");
|
||||||
|
//sscanf(searchPoint, "size=%i", &fontSize);
|
||||||
|
|
||||||
|
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||||
|
searchPoint = strstr(buffer, "lineHeight");
|
||||||
|
sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize);
|
||||||
|
TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight);
|
||||||
|
|
||||||
|
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||||
|
searchPoint = strstr(buffer, "file");
|
||||||
|
sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName);
|
||||||
|
|
||||||
|
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||||
|
searchPoint = strstr(buffer, "count");
|
||||||
|
sscanf(searchPoint, "count=%i", &numChars);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, numChars);
|
||||||
|
|
||||||
|
// Compose correct path using route of .fnt file (fileName) and texFileName
|
||||||
|
char *texPath = NULL;
|
||||||
|
char *lastSlash = NULL;
|
||||||
|
|
||||||
|
lastSlash = strrchr(fileName, '/');
|
||||||
|
|
||||||
|
// NOTE: We need some extra space to avoid memory corruption on next allocations!
|
||||||
|
texPath = malloc(strlen(fileName) - strlen(lastSlash) + strlen(texFileName) + 4);
|
||||||
|
|
||||||
|
// NOTE: strcat() and strncat() required a '\0' terminated string to work!
|
||||||
|
*texPath = '\0';
|
||||||
|
strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1);
|
||||||
|
strncat(texPath, texFileName, strlen(texFileName));
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath);
|
||||||
|
|
||||||
|
Image imFont = LoadImage(texPath);
|
||||||
|
|
||||||
|
if (imFont.format == UNCOMPRESSED_GRAYSCALE)
|
||||||
|
{
|
||||||
|
Image imCopy = ImageCopy(imFont);
|
||||||
|
|
||||||
|
for (int i = 0; i < imCopy.width*imCopy.height; i++) ((unsigned char *)imCopy.data)[i] = 0xff; // WHITE pixel
|
||||||
|
|
||||||
|
ImageAlphaMask(&imCopy, imFont);
|
||||||
|
font.texture = LoadTextureFromImage(imCopy);
|
||||||
|
UnloadImage(imCopy);
|
||||||
|
}
|
||||||
|
else font.texture = LoadTextureFromImage(imFont);
|
||||||
|
|
||||||
|
font.size = fontSize;
|
||||||
|
font.numChars = numChars;
|
||||||
|
font.charValues = (int *)malloc(numChars*sizeof(int));
|
||||||
|
font.charRecs = (Rectangle *)malloc(numChars*sizeof(Rectangle));
|
||||||
|
font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2));
|
||||||
|
font.charAdvanceX = (int *)malloc(numChars*sizeof(int));
|
||||||
|
|
||||||
|
UnloadImage(imFont);
|
||||||
|
|
||||||
|
free(texPath);
|
||||||
|
|
||||||
|
int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX;
|
||||||
|
|
||||||
|
for (int i = 0; i < numChars; i++)
|
||||||
|
{
|
||||||
|
fgets(buffer, MAX_BUFFER_SIZE, fntFile);
|
||||||
|
sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i",
|
||||||
|
&charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX);
|
||||||
|
|
||||||
|
// Save data properly in sprite font
|
||||||
|
font.charValues[i] = charId;
|
||||||
|
font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight };
|
||||||
|
font.charOffsets[i] = (Vector2){ (float)charOffsetX, (float)charOffsetY };
|
||||||
|
font.charAdvanceX[i] = charAdvanceX;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fntFile);
|
||||||
|
|
||||||
|
if (font.texture.id == 0)
|
||||||
|
{
|
||||||
|
UnloadSpriteFont(font);
|
||||||
|
font = GetDefaultFont();
|
||||||
|
}
|
||||||
|
else TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName);
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a sprite font from TTF file data (font size required)
|
||||||
|
// TODO: Review texture packing method and generation (use oversampling)
|
||||||
|
static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int *fontChars)
|
||||||
|
{
|
||||||
|
// NOTE: Font texture size is predicted (being as much conservative as possible)
|
||||||
|
// Predictive method consist of supposing same number of chars by line-column (sqrtf)
|
||||||
|
// and a maximum character width of 3/4 of fontSize... it worked ok with all my tests...
|
||||||
|
|
||||||
|
// Calculate next power-of-two value
|
||||||
|
float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)numChars));
|
||||||
|
int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||||
|
|
||||||
|
TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize);
|
||||||
|
|
||||||
|
unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25);
|
||||||
|
unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned!
|
||||||
|
stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars);
|
||||||
|
|
||||||
|
SpriteFont font = { 0 };
|
||||||
|
|
||||||
|
FILE *ttfFile = fopen(fileName, "rb");
|
||||||
|
|
||||||
|
if (ttfFile == NULL)
|
||||||
|
{
|
||||||
|
TraceLog(WARNING, "[%s] TTF file could not be opened", fileName);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(ttfBuffer, 1, 1 << 25, ttfFile);
|
||||||
|
|
||||||
|
if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character");
|
||||||
|
|
||||||
|
// NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image...
|
||||||
|
// TODO: Replace this function by a proper packing method and support random chars order,
|
||||||
|
// we already receive a list (fontChars) with the ordered expected characters
|
||||||
|
int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], numChars, charData);
|
||||||
|
|
||||||
|
//if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result);
|
||||||
|
if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font");
|
||||||
|
|
||||||
|
free(ttfBuffer);
|
||||||
|
|
||||||
|
// Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA
|
||||||
|
unsigned char *dataGrayAlpha = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)*2); // Two channels
|
||||||
|
|
||||||
|
for (int i = 0, k = 0; i < textureSize*textureSize; i++, k += 2)
|
||||||
|
{
|
||||||
|
dataGrayAlpha[k] = 255;
|
||||||
|
dataGrayAlpha[k + 1] = dataBitmap[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dataBitmap);
|
||||||
|
|
||||||
|
// Sprite font generation from TTF extracted data
|
||||||
|
Image image;
|
||||||
|
image.width = textureSize;
|
||||||
|
image.height = textureSize;
|
||||||
|
image.mipmaps = 1;
|
||||||
|
image.format = UNCOMPRESSED_GRAY_ALPHA;
|
||||||
|
image.data = dataGrayAlpha;
|
||||||
|
|
||||||
|
font.texture = LoadTextureFromImage(image);
|
||||||
|
|
||||||
|
//SavePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2);
|
||||||
|
|
||||||
|
UnloadImage(image); // Unloads dataGrayAlpha
|
||||||
|
|
||||||
|
font.size = fontSize;
|
||||||
|
font.numChars = numChars;
|
||||||
|
font.charValues = (int *)malloc(font.numChars*sizeof(int));
|
||||||
|
font.charRecs = (Rectangle *)malloc(font.numChars*sizeof(Rectangle));
|
||||||
|
font.charOffsets = (Vector2 *)malloc(font.numChars*sizeof(Vector2));
|
||||||
|
font.charAdvanceX = (int *)malloc(font.numChars*sizeof(int));
|
||||||
|
|
||||||
|
for (int i = 0; i < font.numChars; i++)
|
||||||
|
{
|
||||||
|
font.charValues[i] = fontChars[i];
|
||||||
|
|
||||||
|
font.charRecs[i].x = (int)charData[i].x0;
|
||||||
|
font.charRecs[i].y = (int)charData[i].y0;
|
||||||
|
font.charRecs[i].width = (int)charData[i].x1 - (int)charData[i].x0;
|
||||||
|
font.charRecs[i].height = (int)charData[i].y1 - (int)charData[i].y0;
|
||||||
|
|
||||||
|
font.charOffsets[i] = (Vector2){ charData[i].xoff, charData[i].yoff };
|
||||||
|
font.charAdvanceX[i] = (int)charData[i].xadvance;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(charData);
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
2151
raylib/textures.c
Normal file
2151
raylib/textures.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -193,16 +193,6 @@ func LoadImageRaw(fileName string, width int32, height int32, format TextureForm
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load an image from rRES file (raylib Resource)
|
|
||||||
func LoadImageFromRES(rresName string, resId int32) *Image {
|
|
||||||
crresName := C.CString(rresName)
|
|
||||||
defer C.free(unsafe.Pointer(crresName))
|
|
||||||
cresId := (C.int)(resId)
|
|
||||||
ret := C.LoadImageFromRES(crresName, cresId)
|
|
||||||
v := NewImageFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load an image as texture into GPU memory
|
// Load an image as texture into GPU memory
|
||||||
func LoadTexture(fileName string) Texture2D {
|
func LoadTexture(fileName string) Texture2D {
|
||||||
cfileName := C.CString(fileName)
|
cfileName := C.CString(fileName)
|
||||||
|
@ -212,27 +202,6 @@ func LoadTexture(fileName string) Texture2D {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a texture from raw data into GPU memory
|
|
||||||
func LoadTextureEx(data unsafe.Pointer, width int32, height int32, textureFormat TextureFormat) Texture2D {
|
|
||||||
cdata := (unsafe.Pointer)(unsafe.Pointer(data))
|
|
||||||
cwidth := (C.int)(width)
|
|
||||||
cheight := (C.int)(height)
|
|
||||||
ctextureFormat := (C.int)(textureFormat)
|
|
||||||
ret := C.LoadTextureEx(cdata, cwidth, cheight, ctextureFormat)
|
|
||||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load an image as texture from rRES file (raylib Resource)
|
|
||||||
func LoadTextureFromRES(rresName string, resId int32) Texture2D {
|
|
||||||
crresName := C.CString(rresName)
|
|
||||||
defer C.free(unsafe.Pointer(crresName))
|
|
||||||
cresId := (C.int)(resId)
|
|
||||||
ret := C.LoadTextureFromRES(crresName, cresId)
|
|
||||||
v := NewTexture2DFromPointer(unsafe.Pointer(&ret))
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a texture from image data
|
// Load a texture from image data
|
||||||
func LoadTextureFromImage(image *Image) Texture2D {
|
func LoadTextureFromImage(image *Image) Texture2D {
|
||||||
cimage := image.cptr()
|
cimage := image.cptr()
|
||||||
|
|
202
raylib/utils.c
Normal file
202
raylib/utils.c
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib.utils
|
||||||
|
*
|
||||||
|
* Some utility functions
|
||||||
|
*
|
||||||
|
* External libs:
|
||||||
|
* tinfl - zlib DEFLATE algorithm decompression
|
||||||
|
* stb_image_write - PNG writting functions
|
||||||
|
*
|
||||||
|
* Module Configuration Flags:
|
||||||
|
* DO_NOT_TRACE_DEBUG_MSGS - Avoid showing DEBUG TraceLog() messages
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
#include <errno.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/asset_manager.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h> // Required for: malloc(), free()
|
||||||
|
#include <stdio.h> // Required for: fopen(), fclose(), fputc(), fwrite(), printf(), fprintf(), funopen()
|
||||||
|
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
|
||||||
|
#include <string.h> // Required for: strlen(), strrchr(), strcmp()
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include "external/stb_image_write.h" // Required for: stbi_write_bmp(), stbi_write_png()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RRES_IMPLEMENTATION
|
||||||
|
#include "rres.h"
|
||||||
|
|
||||||
|
//#define NO_TRACELOG // Avoid TraceLog() output (any type)
|
||||||
|
#define DO_NOT_TRACE_DEBUG_MSGS // Avoid DEBUG messages tracing
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
AAssetManager *assetManager;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
static int android_read(void *cookie, char *buf, int size);
|
||||||
|
static int android_write(void *cookie, const char *buf, int size);
|
||||||
|
static fpos_t android_seek(void *cookie, fpos_t offset, int whence);
|
||||||
|
static int android_close(void *cookie);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Definition - Utilities
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Outputs a trace log message
|
||||||
|
void TraceLog(int msgType, const char *text, ...)
|
||||||
|
{
|
||||||
|
#if !defined(NO_TRACELOG)
|
||||||
|
static char buffer[128];
|
||||||
|
int traceDebugMsgs = 1;
|
||||||
|
|
||||||
|
#ifdef DO_NOT_TRACE_DEBUG_MSGS
|
||||||
|
traceDebugMsgs = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(msgType)
|
||||||
|
{
|
||||||
|
case INFO: strcpy(buffer, "INFO: "); break;
|
||||||
|
case ERROR: strcpy(buffer, "ERROR: "); break;
|
||||||
|
case WARNING: strcpy(buffer, "WARNING: "); break;
|
||||||
|
case DEBUG: strcpy(buffer, "DEBUG: "); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(buffer, text);
|
||||||
|
strcat(buffer, "\n");
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, text);
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
switch(msgType)
|
||||||
|
{
|
||||||
|
case INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break;
|
||||||
|
case ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break;
|
||||||
|
case WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break;
|
||||||
|
case DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs))) vprintf(buffer, args);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (msgType == ERROR) exit(1); // If ERROR message, exit program
|
||||||
|
|
||||||
|
#endif // NO_TRACELOG
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||||
|
// Creates a BMP image file from an array of pixel data
|
||||||
|
void SaveBMP(const char *fileName, unsigned char *imgData, int width, int height, int compSize)
|
||||||
|
{
|
||||||
|
stbi_write_bmp(fileName, width, height, compSize, imgData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a PNG image file from an array of pixel data
|
||||||
|
void SavePNG(const char *fileName, unsigned char *imgData, int width, int height, int compSize)
|
||||||
|
{
|
||||||
|
stbi_write_png(fileName, width, height, compSize, imgData, width*compSize);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
// Initialize asset manager from android app
|
||||||
|
void InitAssetManager(AAssetManager *manager)
|
||||||
|
{
|
||||||
|
assetManager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replacement for fopen
|
||||||
|
FILE *android_fopen(const char *fileName, const char *mode)
|
||||||
|
{
|
||||||
|
if (mode[0] == 'w') return NULL;
|
||||||
|
|
||||||
|
AAsset *asset = AAssetManager_open(assetManager, fileName, 0);
|
||||||
|
|
||||||
|
if (!asset) return NULL;
|
||||||
|
|
||||||
|
return funopen(asset, android_read, android_write, android_seek, android_close);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Keep track of memory allocated
|
||||||
|
// NOTE: mallocType defines the type of data allocated
|
||||||
|
/*
|
||||||
|
void RecordMalloc(int mallocType, int mallocSize, const char *msg)
|
||||||
|
{
|
||||||
|
// TODO: Investigate how to record memory allocation data...
|
||||||
|
// Maybe creating my own malloc function...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Get the extension for a filename
|
||||||
|
const char *GetExtension(const char *fileName)
|
||||||
|
{
|
||||||
|
const char *dot = strrchr(fileName, '.');
|
||||||
|
if (!dot || dot == fileName) return "";
|
||||||
|
return (dot + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module specific Functions Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
static int android_read(void *cookie, char *buf, int size)
|
||||||
|
{
|
||||||
|
return AAsset_read((AAsset *)cookie, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int android_write(void *cookie, const char *buf, int size)
|
||||||
|
{
|
||||||
|
TraceLog(ERROR, "Can't provide write access to the APK");
|
||||||
|
|
||||||
|
return EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fpos_t android_seek(void *cookie, fpos_t offset, int whence)
|
||||||
|
{
|
||||||
|
return AAsset_seek((AAsset *)cookie, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int android_close(void *cookie)
|
||||||
|
{
|
||||||
|
AAsset_close((AAsset *)cookie);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
77
raylib/utils.h
Normal file
77
raylib/utils.h
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/**********************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib.utils
|
||||||
|
*
|
||||||
|
* Some utility functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
|
*
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||||
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||||
|
*
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||||
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||||
|
* in the product documentation would be appreciated but is not required.
|
||||||
|
*
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||||
|
* as being the original software.
|
||||||
|
*
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*
|
||||||
|
**********************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
#include <stdio.h> // Required for: FILE
|
||||||
|
#include <android/asset_manager.h> // Required for: AAssetManager
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "rres.h"
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Some basic Defines
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
#define fopen(name, mode) android_fopen(name, mode)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Types and Structures Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" { // Prevents name mangling of functions
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Global Variables Definition
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Nop...
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
// Module Functions Declaration
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message
|
||||||
|
const char *GetExtension(const char *fileName); // Returns extension of a filename
|
||||||
|
|
||||||
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||||
|
void SaveBMP(const char *fileName, unsigned char *imgData, int width, int height, int compSize);
|
||||||
|
void SavePNG(const char *fileName, unsigned char *imgData, int width, int height, int compSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PLATFORM_ANDROID)
|
||||||
|
void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app
|
||||||
|
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // UTILS_H
|
Loading…
Add table
Add a link
Reference in a new issue