LoadBufferFormatted, SetBufferData and CopyBufferData. Compressed resource file example.

This commit is contained in:
jussi
2024-08-27 21:41:31 +03:00
parent af2bf6f7a2
commit 35e73465ac
9 changed files with 304 additions and 43 deletions

32
API.md
View File

@@ -2286,6 +2286,12 @@ Pi
---
> EPSILON = 9.9999999747524e-07
Epsilon
---
> DEG2RAD = 0.017453292384744
Degrees to radians
@@ -5464,7 +5470,15 @@ Load Buffer. Type should be one of the Buffer types. Empty buffer will set data
---
> buffer = RL.LoadBufferFromFile( string path, type int )
> buffer = RL.LoadBufferFormatted( int length, int type, int value )
Load formatted buffer with all values set to 'value'
- Success return Buffer
---
> buffer = RL.LoadBufferFromFile( string path, int type )
Read buffer data from binary file
@@ -5488,6 +5502,18 @@ Unload buffer data
---
> RL.CopyBufferData( Buffer dst, Buffer src, int posDst, int posSrc, int length )
Copy buffer data to another buffer. src element size is used for length
---
> RL.SetBufferData( Buffer buffer, int position, any value )
Set buffer data value
---
> data = RL.GetBufferData( Buffer buffer, int position, int length )
Get buffer data as table in the format it was stored
@@ -6734,7 +6760,7 @@ Get Color structure from hexadecimal value
---
> size = RL.GetPixelDataSize( int width, int height, int format )
> size = RL.GetPixelDataSize( Vector2 size, int format )
Get pixel data size in bytes for certain format
@@ -7983,7 +8009,7 @@ Get collision info between ray and triangle
> rayCollision = RL.GetRayCollisionQuad( Ray ray, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4 )
Get collision info between ray and quad
Get collision info between ray and quad. NOTE: The points are expected to be in counter-clockwise winding
- Success return RayCollision

View File

@@ -739,6 +739,8 @@ RL.RAYWHITE={245,245,245,255}
---Pi
RL.PI=3.1415927410126
---Epsilon
RL.EPSILON=9.9999999747524e-07
---Degrees to radians
RL.DEG2RAD=0.017453292384744
---Radians to degrees
@@ -2630,13 +2632,21 @@ function RL.UpdateCamera3DPro( camera, movement, rotation, zoom ) end
---@return any buffer
function RL.LoadBuffer( buffer, type ) end
---Load formatted buffer with all values set to 'value'
---- Success return Buffer
---@param length integer
---@param type integer
---@param value integer
---@return any buffer
function RL.LoadBufferFormatted( length, type, value ) end
---Read buffer data from binary file
---- Failure return nil
---- Success return Buffer
---@param path string
---@param int any
---@param type integer
---@return any buffer
function RL.LoadBufferFromFile( path, int ) end
function RL.LoadBufferFromFile( path, type ) end
---Read buffer data from string
---- Failure return nil
@@ -2650,6 +2660,22 @@ function RL.LoadBufferFromString( buffer ) end
---@return any RL.UnloadBuffer
function RL.UnloadBuffer( buffer ) end
---Copy buffer data to another buffer. src element size is used for length
---@param dst any
---@param src any
---@param posDst integer
---@param posSrc integer
---@param length integer
---@return any RL.CopyBufferData
function RL.CopyBufferData( dst, src, posDst, posSrc, length ) end
---Set buffer data value
---@param buffer any
---@param position integer
---@param value any
---@return any RL.SetBufferData
function RL.SetBufferData( buffer, position, value ) end
---Get buffer data as table in the format it was stored
---- Success return data{}
---@param buffer any
@@ -3909,11 +3935,10 @@ function RL.GetColor( hexValue ) end
---Get pixel data size in bytes for certain format
---- Success return int
---@param width integer
---@param height integer
---@param size table
---@param format integer
---@return any size
function RL.GetPixelDataSize( width, height, format ) end
function RL.GetPixelDataSize( size, format ) end
-- Text - Font loading/unloading functions
@@ -5127,7 +5152,7 @@ function RL.GetRayCollisionMesh( ray, mesh, transform ) end
---@return any rayCollision
function RL.GetRayCollisionTriangle( ray, p1, p2, p3 ) end
---Get collision info between ray and quad
---Get collision info between ray and quad. NOTE: The points are expected to be in counter-clockwise winding
---- Success return RayCollision
---@param ray any
---@param p1 table

View File

@@ -68,6 +68,8 @@ DETAILED CHANGES:
- ADDED: DrawGridEx.
- ADDED: GetRayBoxCells.
- FIXED: GenImageColor color was also argument 1.
- CHANGE: GetPixelDataSize takes Vector2 instead of width and height.
- ADDED: LoadBufferFormatted, SetBufferData and CopyBufferData. Compressed resource file example.
------------------------------------------------------------------------
Release: ReiLua version 0.7.0 Using Raylib 5.0 and Forked Raygui 4.0

View File

@@ -0,0 +1,94 @@
-- Simple example to store compressed image to file.
-- To store multiple assets, some sort of addressing would be required.
package.path = package.path..";"..RL.GetBasePath().."../resources/lib/?.lua"
Vector2 = require( "vector2" )
local texture = nil
local dataFileName = "data"
local compress = true
-- local compress = false
local function writeDataFile( path )
local image = RL.LoadImage( RL.GetBasePath().."../resources/images/arcade_platformerV2.png" )
if not image then
return
end
local imgData = {
size = Vector2:newT( RL.GetImageSize( image ) ),
mipmaps = RL.GetImageMipmaps( image ),
format = RL.GetImageFormat( image ),
data = RL.GetImageData( image ),
}
-- Header and image data. We devide imgData.data by 4 since we use unsigned ints as buffer type.
local totalLength = 4 + RL.GetBufferLength( imgData.data ) / 4
local buffer = RL.LoadBufferFormatted( totalLength, RL.BUFFER_UNSIGNED_INT, 0 )
RL.SetBufferData( buffer, 0, imgData.size.x )
RL.SetBufferData( buffer, 1, imgData.size.y )
RL.SetBufferData( buffer, 2, imgData.mipmaps )
RL.SetBufferData( buffer, 3, imgData.format )
RL.CopyBufferData( buffer, imgData.data, 4, 0, RL.GetBufferLength( imgData.data ) )
if compress then
RL.ExportBuffer( RL.CompressData( buffer ), path )
else
RL.ExportBuffer( buffer, path )
end
end
local function loadDataFile( path )
local buffer = RL.LoadBufferFromFile( path, RL.BUFFER_UNSIGNED_INT )
if not buffer then
return
end
if compress then
buffer = RL.DecompressData( buffer )
end
local imgData = {
size = Vector2:newT( RL.GetBufferData( buffer, 0, 2 ) ),
mipmaps = RL.GetBufferData( buffer, 2, 1 )[1],
format = RL.GetBufferData( buffer, 3, 1 )[1],
data = nil,
}
local imageDataSize = RL.GetPixelDataSize( imgData.size, imgData.format )
imgData.data = RL.LoadBufferFormatted( imageDataSize, RL.BUFFER_UNSIGNED_CHAR, 0 )
RL.CopyBufferData( imgData.data, buffer, 0, 4, imageDataSize / 4 )
local image = RL.LoadImageFromData(
imgData.data,
imgData.size,
imgData.mipmaps,
imgData.format
)
texture = RL.LoadTextureFromImage( image )
end
function RL.init()
RL.SetWindowTitle( "Compressed resource file" )
RL.SetWindowState( RL.FLAG_VSYNC_HINT )
local path = RL.GetBasePath()..dataFileName
writeDataFile( path )
loadDataFile( path )
end
function RL.update( delta )
end
function RL.draw()
RL.ClearBackground( RL.RAYWHITE )
if texture then
RL.DrawTextureEx( texture, { 0, 0 }, 0, 2, RL.WHITE )
end
end

View File

@@ -1,11 +1,11 @@
package.path = package.path..";"..RL.GetBasePath().."../resources/lib/?.lua"
Util = require( "utillib" )
Vec2 = require( "vector2" )
Rect = require( "rectangle" )
Vector2 = require( "vector2" )
Rectangle = require( "rectangle" )
-- Defines
local RESOLUTION = Vec2:new( 128, 128 )
local RESOLUTION = Vector2:new( 128, 128 )
local TILE_SIZE = 8
local LEVEL_SIZE = RESOLUTION.x / TILE_SIZE
local STATE = { TITLE = 0, GAME = 1, OVER = 2 } -- Enum.
@@ -13,10 +13,10 @@ local STATE = { TITLE = 0, GAME = 1, OVER = 2 } -- Enum.
-- Resources
local framebuffer = nil
local monitor = 0
local monitorPos = Vec2:newT( RL.GetMonitorPosition( monitor ) )
local monitorSize = Vec2:newT( RL.GetMonitorSize( monitor ) )
local monitorPos = Vector2:newT( RL.GetMonitorPosition( monitor ) )
local monitorSize = Vector2:newT( RL.GetMonitorSize( monitor ) )
local winScale = 6
local winSize = Vec2:new( RESOLUTION.x * winScale, RESOLUTION.y * winScale )
local winSize = Vector2:new( RESOLUTION.x * winScale, RESOLUTION.y * winScale )
local gameState = STATE.GAME
local grassTexture = nil
local snakeTexture = nil
@@ -28,10 +28,10 @@ local applePos = {}
local function setSnake()
snake = {
heading = Vec2:new( 1, 0 ),
control = Vec2:new( 1, 0 ),
headPos = Vec2:new( LEVEL_SIZE / 2, LEVEL_SIZE / 2 ),
segments = {}, -- { pos Vec2, heading Vec2 }
heading = Vector2:new( 1, 0 ),
control = Vector2:new( 1, 0 ),
headPos = Vector2:new( LEVEL_SIZE / 2, LEVEL_SIZE / 2 ),
segments = {}, -- { pos Vector2, heading Vector2 }
grow = 2,
}
end
@@ -52,7 +52,7 @@ local function addSegment()
end
local function setApplePos()
applePos = Vec2:new( math.random( 0, LEVEL_SIZE - 1 ), math.random( 0, LEVEL_SIZE - 1 ) )
applePos = Vector2:new( math.random( 0, LEVEL_SIZE - 1 ), math.random( 0, LEVEL_SIZE - 1 ) )
local search = true
while search do
@@ -167,16 +167,16 @@ end
--[[ Check if next segment is on left side. There are more mathematically elegant solution to this, but there is
only four possibilities so we can just check them all. ]]--
local function onLeft( this, nextSeg )
return ( this == Vec2:temp( 0, -1 ) and nextSeg == Vec2:temp( -1, 0 ) )
or ( this == Vec2:temp( -1, 0 ) and nextSeg == Vec2:temp( 0, 1 ) )
or ( this == Vec2:temp( 0, 1 ) and nextSeg == Vec2:temp( 1, 0 ) )
or ( this == Vec2:temp( 1, 0 ) and nextSeg == Vec2:temp( 0, -1 ) )
return ( this == Vector2:temp( 0, -1 ) and nextSeg == Vector2:temp( -1, 0 ) )
or ( this == Vector2:temp( -1, 0 ) and nextSeg == Vector2:temp( 0, 1 ) )
or ( this == Vector2:temp( 0, 1 ) and nextSeg == Vector2:temp( 1, 0 ) )
or ( this == Vector2:temp( 1, 0 ) and nextSeg == Vector2:temp( 0, -1 ) )
end
local function drawSnake()
for i, seg in ipairs( snake.segments ) do
local angle = seg.heading:atan2()
local source = Rect:temp( 16, 0, 8, 8 )
local source = Rectangle:temp( 16, 0, 8, 8 )
if i == 1 then -- Tail segment. Yes tail is actually the 'first' segment.
source.x = 8

View File

@@ -249,9 +249,12 @@ int lcoreUpdateCamera3D( lua_State* L );
int lcoreUpdateCamera3DPro( lua_State* L );
/* Buffer management functions. */
int lcoreLoadBuffer( lua_State* L );
int lcoreLoadBufferFormatted( lua_State* L );
int lcoreLoadBufferFromFile( lua_State* L );
int lcoreLoadBufferFromString( lua_State* L );
int lcoreUnloadBuffer( lua_State* L );
int lcoreCopyBufferData( lua_State* L );
int lcoreSetBufferData( lua_State* L );
int lcoreGetBufferData( lua_State* L );
int lcoreGetBufferType( lua_State* L );
int lcoreGetBufferSize( lua_State* L );

View File

@@ -4,7 +4,7 @@
#include "textures.h"
#include "lua_core.h"
static int getBufferElementSize( Buffer* buffer ) {
static size_t getBufferElementSize( Buffer* buffer ) {
switch ( buffer->type ) {
case BUFFER_UNSIGNED_CHAR: return sizeof( unsigned char );
case BUFFER_UNSIGNED_SHORT: return sizeof( unsigned short );
@@ -2141,7 +2141,7 @@ int lcoreGetAutomationEvent( lua_State* L ) {
lua_pushlightuserdata( L, &list->events[ index ] );
}
else {
TraceLog( LOG_WARNING, "GetAutomationEvent index %d out of bounds", index );
TraceLog( state->logLevelInvalid, "GetAutomationEvent index %d out of bounds", index );
lua_pushnil( L );
}
@@ -3388,10 +3388,10 @@ int lcoreLoadBuffer( lua_State* L ) {
int t = 1;
int i = 0;
unsigned char* ucp = buffer.data;
unsigned short *usp = buffer.data;
unsigned short* usp = buffer.data;
unsigned int* uip = buffer.data;
char* cp = buffer.data;
short *sp = buffer.data;
short* sp = buffer.data;
int* ip = buffer.data;
float* fp = buffer.data;
double* dp = buffer.data;
@@ -3444,7 +3444,32 @@ int lcoreLoadBuffer( lua_State* L ) {
}
/*
> buffer = RL.LoadBufferFromFile( string path, type int )
> buffer = RL.LoadBufferFormatted( int length, int type, int value )
Load formatted buffer with all values set to 'value'
- Success return Buffer
*/
int lcoreLoadBufferFormatted( lua_State* L ) {
int len = luaL_checkinteger( L, 1 );
int type = luaL_checkinteger( L, 2 );
int value = luaL_checkinteger( L, 3 );
Buffer buffer = {
.type = type
};
buffer.size = len * getBufferElementSize( &buffer );
buffer.data = malloc( buffer.size );
memset( buffer.data, value, buffer.size );
uluaPushBuffer( L, buffer );
return 1;
}
/*
> buffer = RL.LoadBufferFromFile( string path, int type )
Read buffer data from binary file
@@ -3461,16 +3486,15 @@ int lcoreLoadBufferFromFile( lua_State* L ) {
.size = fileLen,
.data = malloc( fileLen )
};
size_t elementSize = getBufferElementSize( &buffer );
FILE* file;
file = fopen( path, "rb" );
if ( file == NULL ) {
TraceLog( LOG_WARNING, "Invalid file %s\n", path );
TraceLog( state->logLevelInvalid, "Invalid file %s\n", path );
lua_pushnil( L );
return 1;
}
fread( buffer.data, elementSize, buffer.size / elementSize, file );
fread( buffer.data, buffer.size, 1, file );
fclose( file );
uluaPushBuffer( L, buffer );
@@ -3516,6 +3540,92 @@ int lcoreUnloadBuffer( lua_State* L ) {
return 0;
}
/*
> RL.CopyBufferData( Buffer dst, Buffer src, int posDst, int posSrc, int length )
Copy buffer data to another buffer. src element size is used for length
*/
int lcoreCopyBufferData( lua_State* L ) {
Buffer* dst = uluaGetBuffer( L, 1 );
Buffer* src = uluaGetBuffer( L, 2 );
int posDst = luaL_checkinteger( L, 3 );
int posSrc = luaL_checkinteger( L, 4 );
int length = luaL_checkinteger( L, 5 );
void* dstP = dst->data + posDst * getBufferElementSize( dst );
void* srcP = src->data + posSrc * getBufferElementSize( src );
size_t size = length * getBufferElementSize( src );
/* Note that we use src element size for dst length. */
if ( posDst < 0 || dst->size < posDst * getBufferElementSize( dst ) + size ) {
TraceLog( state->logLevelInvalid, "CopyBufferData. posDst %d with length %d out of bounds", posDst, length );
return 0;
}
if ( posSrc < 0 || src->size < posSrc * getBufferElementSize( src ) + size ) {
TraceLog( state->logLevelInvalid, "CopyBufferData. posSrc %d with length %d out of bounds", posSrc, length );
return 0;
}
memcpy( dstP, srcP, size );
return 0;
}
/*
> RL.SetBufferData( Buffer buffer, int position, any value )
Set buffer data value
*/
int lcoreSetBufferData( lua_State* L ) {
Buffer* buffer = uluaGetBuffer( L, 1 );
size_t position = luaL_checkinteger( L, 2 );
if ( position < 0 || buffer->size / getBufferElementSize( buffer ) <= position ) {
TraceLog( state->logLevelInvalid, "SetBufferData. position %d out of bounds", position );
return 0;
}
size_t offset = position * getBufferElementSize( buffer );
unsigned char* ucp = buffer->data + offset;
unsigned short* usp = buffer->data + offset;
unsigned int* uip = buffer->data + offset;
char* cp = buffer->data + offset;
short* sp = buffer->data + offset;
int* ip = buffer->data + offset;
float* fp = buffer->data + offset;
double* dp = buffer->data + offset;
switch ( buffer->type ) {
case BUFFER_UNSIGNED_CHAR:
*ucp = (unsigned char)lua_tointeger( L, -1 );
break;
case BUFFER_UNSIGNED_SHORT:
*usp = (unsigned short)lua_tointeger( L, -1 );
break;
case BUFFER_UNSIGNED_INT:
*uip = (unsigned int)lua_tointeger( L, -1 );
break;
case BUFFER_CHAR:
*cp = (char)lua_tointeger( L, -1 );
break;
case BUFFER_SHORT:
*sp = (short)lua_tointeger( L, -1 );
break;
case BUFFER_INT:
*ip = (int)lua_tointeger( L, -1 );
break;
case BUFFER_FLOAT:
*fp = (float)lua_tonumber( L, -1 );
break;
case BUFFER_DOUBLE:
*dp = (double)lua_tonumber( L, -1 );
break;
default:
break;
}
return 0;
}
/*
> data = RL.GetBufferData( Buffer buffer, int position, int length )
@@ -3696,11 +3806,10 @@ int lcoreExportBuffer( lua_State* L ) {
Buffer* buffer = uluaGetBuffer( L, 1 );
const char* path = luaL_checkstring( L, 2 );
size_t elementSize = getBufferElementSize( buffer );
FILE* file;
file = fopen( path, "wb" );
fwrite( buffer->data, elementSize, buffer->size / elementSize, file );
fwrite( buffer->data, buffer->size, 1, file );
fclose( file );
return 0;

View File

@@ -1512,9 +1512,12 @@ void luaRegister() {
assingGlobalFunction( "UpdateCamera3DPro", lcoreUpdateCamera3DPro );
/* Buffer management functions. */
assingGlobalFunction( "LoadBuffer", lcoreLoadBuffer );
assingGlobalFunction( "LoadBufferFormatted", lcoreLoadBufferFormatted );
assingGlobalFunction( "LoadBufferFromFile", lcoreLoadBufferFromFile );
assingGlobalFunction( "LoadBufferFromString", lcoreLoadBufferFromString );
assingGlobalFunction( "UnloadBuffer", lcoreUnloadBuffer );
assingGlobalFunction( "CopyBufferData", lcoreCopyBufferData );
assingGlobalFunction( "SetBufferData", lcoreSetBufferData );
assingGlobalFunction( "GetBufferData", lcoreGetBufferData );
assingGlobalFunction( "GetBufferType", lcoreGetBufferType );
assingGlobalFunction( "GetBufferSize", lcoreGetBufferSize );

View File

@@ -1071,13 +1071,13 @@ int ltexturesImageDrawRectangleLines( lua_State* L ) {
Draw a source image within a destination image (Tint applied to source)
*/
int ltexturesImageDraw( lua_State* L ) {
Image* imageDstId = uluaGetImage( L, 1 );
Image* imageSrcId = uluaGetImage( L, 2 );
Image* imageDst = uluaGetImage( L, 1 );
Image* imageSrc = uluaGetImage( L, 2 );
Rectangle srcRec = uluaGetRectangle( L, 3 );
Rectangle dstRec = uluaGetRectangle( L, 4 );
Color tint = uluaGetColor( L, 5 );
ImageDraw( imageDstId, *imageSrcId, srcRec, dstRec, tint );
ImageDraw( imageDst, *imageSrc, srcRec, dstRec, tint );
return 0;
}
@@ -2061,18 +2061,17 @@ int ltexturesGetColor( lua_State* L ) {
}
/*
> size = RL.GetPixelDataSize( int width, int height, int format )
> size = RL.GetPixelDataSize( Vector2 size, int format )
Get pixel data size in bytes for certain format
- Success return int
*/
int ltexturesGetPixelDataSize( lua_State* L ) {
int width = luaL_checkinteger( L, 1 );
int height = luaL_checkinteger( L, 2 );
int format = luaL_checkinteger( L, 3 );
Vector2 size = uluaGetVector2( L, 1 );
int format = luaL_checkinteger( L, 2 );
lua_pushinteger( L, GetPixelDataSize( width, height, format ) );
lua_pushinteger( L, GetPixelDataSize( size.x, size.y, format ) );
return 1;
}