naev 0.11.5
nlua_tex.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <lauxlib.h>
11#include "SDL.h"
12#include "SDL_image.h"
13
14#include "naev.h"
17#include "physfsrwops.h"
18
19#include "nlua_tex.h"
20
21#include "log.h"
22#include "ndata.h"
23#include "nlua_data.h"
24#include "nlua_file.h"
25#include "nluadef.h"
26
27static int nlua_tex_counter = 0;
28
29/* Helpers. */
30static inline uint32_t get_pixel(SDL_Surface *surface, int x, int y);
31
32/* Texture metatable methods. */
33static int texL_close( lua_State *L );
34static int texL_new( lua_State *L );
35static int texL_readData( lua_State *L );
36static int texL_writeData( lua_State *L );
37static int texL_dim( lua_State *L );
38static int texL_sprites( lua_State *L );
39static int texL_spriteFromDir( lua_State *L );
40static int texL_setFilter( lua_State *L );
41static int texL_setWrap( lua_State *L );
42static const luaL_Reg texL_methods[] = {
43 { "__gc", texL_close },
44 { "new", texL_new },
45 { "open", texL_new },
46 { "readData", texL_readData },
47 { "writeData", texL_writeData },
48 { "dim", texL_dim },
49 { "sprites", texL_sprites },
50 { "spriteFromDir", texL_spriteFromDir },
51 { "setFilter", texL_setFilter },
52 { "setWrap", texL_setWrap },
53 {0,0}
54};
62int nlua_loadTex( nlua_env env )
63{
64 nlua_register(env, TEX_METATABLE, texL_methods, 1);
65 return 0;
66}
67
89glTexture* lua_totex( lua_State *L, int ind )
90{
91 return *((glTexture**) lua_touserdata(L,ind));
92}
100glTexture* luaL_checktex( lua_State *L, int ind )
101{
102 if (lua_istex(L,ind))
103 return lua_totex(L,ind);
104 luaL_typerror(L, ind, TEX_METATABLE);
105 return NULL;
106}
115glTexture* luaL_validtex( lua_State *L, int ind, const char *searchpath )
116{
117 char path[PATH_MAX];
118 if (lua_istex(L,ind))
119 return gl_dupTexture( luaL_checktex(L,ind) );
120 ndata_getPathDefault( path, sizeof(path), searchpath, luaL_checkstring(L,ind) );
121 return gl_newImage( path, 0 );
122}
130glTexture** lua_pushtex( lua_State *L, glTexture *texture )
131{
132 glTexture **t = (glTexture**) lua_newuserdata(L, sizeof(glTexture*));
133 *t = texture;
134 luaL_getmetatable(L, TEX_METATABLE);
135 lua_setmetatable(L, -2);
136 return t;
137}
145int lua_istex( lua_State *L, int ind )
146{
147 int ret;
148
149 if (lua_getmetatable(L,ind)==0)
150 return 0;
151 lua_getfield(L, LUA_REGISTRYINDEX, TEX_METATABLE);
152
153 ret = 0;
154 if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */
155 ret = 1;
156
157 lua_pop(L, 2); /* remove both metatables */
158 return ret;
159}
160
167static int texL_close( lua_State *L )
168{
169 /* Free texture. */
170 gl_freeTexture( luaL_checktex( L, 1 ) );
171
172 return 0;
173}
174
193static int texL_new( lua_State *L )
194{
195 const char *path;
196 glTexture *tex;
197 LuaFile_t *lf;
198 LuaData_t *ld;
199 int sx, sy;
200 SDL_RWops *rw;
201 char *name;
202
203
204 /* Defaults. */
205 lf = NULL;
206 ld = NULL;
207 path = NULL;
208
209 /* Get path. */
210 if (lua_isdata(L,1)) {
211 int w, h;
212 ld = luaL_checkdata(L,1);
213 /* Since we don't know the size we need the width and height separately. */
214 w = luaL_checkinteger(L,2);
215 h = luaL_checkinteger(L,3);
216 if ((w < 0 ) || (h < 0))
217 return NLUA_ERROR( L, _("Texture dimensions must be positive") );
218 sx = luaL_optinteger(L,4,1);
219 sy = luaL_optinteger(L,5,1);
220 if ((sx < 0 ) || (sy < 0))
221 return NLUA_ERROR( L, _("Spritesheet dimensions must be positive") );
222 if (ld->type != LUADATA_NUMBER)
223 return NLUA_ERROR( L, _("Data has invalid type for texture") );
224 if (w*h*ld->elem*4 != ld->size)
225 return NLUA_ERROR( L, _("Texture dimensions don't match data size!") );
226 SDL_asprintf( &name, "nlua_texture_%03d", ++nlua_tex_counter );
227 tex = gl_loadImageData( (void*)ld->data, w, h, sx, sy, name );
228 free( name );
229 if (tex==NULL)
230 return 0;
231 lua_pushtex(L, tex);
232 return 1;
233 }
234 else if (lua_isfile(L,1))
235 lf = luaL_checkfile(L,1);
236 else
237 path = luaL_checkstring(L, 1);
238
239 sx = luaL_optinteger(L,2,1);
240 sy = luaL_optinteger(L,3,1);
241 if ((sx < 0 ) || (sy < 0))
242 return NLUA_ERROR( L, _("Spritesheet dimensions must be positive") );
243
244 /* Push new texture. */
245 if (path != NULL)
246 tex = gl_newSprite( path, sx, sy, 0 );
247 else {
248 rw = PHYSFSRWOPS_openRead( lf->path );
249 if (rw==NULL)
250 return NLUA_ERROR(L,"Unable to open '%s'", lf->path );
251 tex = gl_newSpriteRWops( lf->path, rw, sx, sy, 0 );
252 SDL_RWclose( rw );
253 }
254
255 /* Failed to load. */
256 if (tex == NULL)
257 return 0;
258 /* Properly loaded. */
259 lua_pushtex( L, tex );
260 return 1;
261}
262
263static inline uint32_t get_pixel(SDL_Surface *surface, int x, int y)
264{
265 int bpp = surface->format->BytesPerPixel;
266 /* Here p is the address to the pixel we want to retrieve */
267 uint8_t *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
268
269 switch(bpp) {
270 case 1:
271 return *p;
272 break;
273
274 case 2:
275 return *(Uint16 *)p;
276 break;
277
278 case 3:
279 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
280 return p[0] << 16 | p[1] << 8 | p[2];
281 else
282 return p[0] | p[1] << 8 | p[2] << 16;
283 break;
284
285 case 4:
286 return *(Uint32 *)p;
287 break;
288
289 default:
290 return 0; /* shouldn't happen, but avoids warnings */
291 }
292}
293
303static int texL_readData( lua_State *L )
304{
305 LuaFile_t *lf;
306 LuaData_t ld;
307 SDL_Surface *surface;
308 SDL_RWops *rw;
309 const char *s;
310 size_t size;
311 uint8_t r, g, b, a;
312 uint32_t pix;
313 float *data;
314
315 s = NULL;
316 if (lua_isfile(L,1)) {
317 lf = luaL_checkfile(L,1);
318 s = lf->path;
319 }
320 else
321 s = luaL_checkstring(L,1);
322 rw = PHYSFSRWOPS_openRead( s );
323 if (rw == NULL)
324 return NLUA_ERROR(L, _("problem opening file '%s' for reading"), s );
325
326 /* Try to read the image. */
327 surface = IMG_Load_RW( rw, 1 );
328 if (surface == NULL)
329 return NLUA_ERROR(L, _("problem opening image for reading") );
330
331 /* Convert surface to LuaData_t */
332 SDL_LockSurface( surface );
333 size = surface->w * surface->h;
334 ld.elem = sizeof(float);
335 ld.size = ld.elem * size * 4;
336 ld.data = calloc( ld.elem*4, size );
337 ld.type = LUADATA_NUMBER;
338 data = (float*)ld.data;
339 for (int i=0; i<surface->h; i++) {
340 for (int j=0; j<surface->w; j++) {
341 pix = get_pixel( surface, j, i );
342 SDL_GetRGBA( pix, surface->format, &r, &g, &b, &a );
343 size_t pos = 4*((surface->h-i-1)*surface->w+j);
344 data[ pos+0 ] = ((float)r)/255.;
345 data[ pos+1 ] = ((float)g)/255.;
346 data[ pos+2 ] = ((float)b)/255.;
347 data[ pos+3 ] = ((float)a)/255.;
348 }
349 }
350 SDL_UnlockSurface( surface );
351
352 /* Return parameters. */
353 lua_pushdata(L, ld);
354 lua_pushinteger(L, surface->w);
355 lua_pushinteger(L, surface->h);
356
357 /* Clean up. */
358 SDL_FreeSurface( surface );
359
360 return 3;
361}
362
370static int texL_writeData( lua_State *L )
371{
372 glTexture *tex = luaL_checktex(L,1);
373 const char *filename = luaL_checkstring(L,2);
374 int w, h;
375 size_t len;
376 char *data;
377 SDL_Surface *surface;
378 SDL_RWops *rw;
379
380 w = tex->w;
381 h = tex->h;
382 len = w * h * 4 * sizeof(GLubyte);
383 data = malloc( len );
384
385 /* Read raw data. */
386 glBindTexture( GL_TEXTURE_2D, tex->texture );
387 glGetTexImage( GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
388 gl_checkErr();
389
390 /* Convert to PNG. */
391 surface = SDL_CreateRGBSurface( 0, w, h, 32, RGBAMASK );
392 for (int i=0; i<h; i++)
393 memcpy( (GLubyte*)surface->pixels + i * (4*w), &data[ (h - i - 1) * (4*w) ], 4*w );
394
395 /* Free buffer. */
396 free( data );
397
398 /* Save to file. */
399 if (!(rw = PHYSFSRWOPS_openWrite( filename )))
400 return NLUA_ERROR(L,_("Unable to open '%s' for writing!"),filename);
401 else
402 IMG_SavePNG_RW( surface, rw, 1 );
403
404 SDL_FreeSurface( surface );
405
406 lua_pushboolean(L,1);
407 return 1;
408}
409
422static int texL_dim( lua_State *L )
423{
424 glTexture *tex = luaL_checktex( L, 1 );
425
426 /* Get all 4 values. */
427 lua_pushnumber( L, tex->w );
428 lua_pushnumber( L, tex->h );
429 lua_pushnumber( L, tex->sw );
430 lua_pushnumber( L, tex->sh );
431 return 4;
432}
433
445static int texL_sprites( lua_State *L )
446{
447 glTexture *tex = luaL_checktex( L, 1 );
448
449 /* Get sprites. */
450 lua_pushnumber( L, tex->sx * tex->sy );
451 lua_pushnumber( L, tex->sx );
452 lua_pushnumber( L, tex->sy );
453 return 3;
454}
455
467static int texL_spriteFromDir( lua_State *L )
468{
469
470 int sx, sy;
471 const glTexture *tex = luaL_checktex( L, 1 );
472 double a = luaL_checknumber( L, 2 );
473
474 /* Calculate with parameter validity.. */
475 if ((a >= 2.*M_PI) || (a < 0.)) {
476 a = fmod( a, 2.*M_PI );
477 if (a < 0.)
478 a += 2.*M_PI;
479 }
480 gl_getSpriteFromDir( &sx, &sy, tex, a );
481
482 /* Return. */
483 lua_pushinteger( L, sx+1 );
484 lua_pushinteger( L, sy+1 );
485 return 2;
486}
487
496static int texL_setFilter( lua_State *L )
497{
498 glTexture *tex = luaL_checktex(L,1);
499 const char *smin = luaL_checkstring(L,2);
500 const char *smag = luaL_optstring(L,3,smin);
501 GLint min, mag;
502
503 min = gl_stringToFilter( smin );
504 mag = gl_stringToFilter( smag );
505
506 if (min==0 || mag==0)
507 NLUA_INVALID_PARAMETER(L,2);
508
509 glBindTexture( GL_TEXTURE_2D, tex->texture );
510 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag );
511 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min );
512 gl_checkErr();
513
514 return 0;
515}
516
526static int texL_setWrap( lua_State *L )
527{
528 glTexture *tex = luaL_checktex(L,1);
529 const char *shoriz = luaL_checkstring(L,2);
530 const char *svert = luaL_optstring(L,3,shoriz);
531 const char *sdepth = luaL_optstring(L,4,shoriz);
532 GLint horiz, vert, depth;
533
534 horiz = gl_stringToClamp( shoriz );
535 vert = gl_stringToClamp( svert );
536 depth = gl_stringToClamp( sdepth );
537
538 if (horiz==0 || vert==0 || depth==0)
539 NLUA_INVALID_PARAMETER(L,2);
540
541 glBindTexture( GL_TEXTURE_2D, tex->texture );
542 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, horiz );
543 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vert );
544 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, depth );
545 gl_checkErr();
546
547 return 0;
548}
Header file with generic functions and naev-specifics.
#define PATH_MAX
Definition naev.h:50
int ndata_getPathDefault(char *path, int len, const char *default_path, const char *filename)
Tries to see if a file is in a default path before seeing if it is an absolute path.
Definition ndata.c:386
LuaData_t * luaL_checkdata(lua_State *L, int ind)
Gets data at index or raises error if there is no data at index.
Definition nlua_data.c:83
int lua_isdata(lua_State *L, int ind)
Checks to see if ind is a data.
Definition nlua_data.c:113
LuaData_t * lua_pushdata(lua_State *L, LuaData_t data)
Pushes a data on the stack.
Definition nlua_data.c:97
int lua_isfile(lua_State *L, int ind)
Checks to see if ind is a file.
Definition nlua_file.c:126
LuaFile_t * luaL_checkfile(lua_State *L, int ind)
Gets file at index or raises error if there is no file at index.
Definition nlua_file.c:97
static int texL_dim(lua_State *L)
Gets the dimensions of the texture.
Definition nlua_tex.c:422
glTexture * lua_totex(lua_State *L, int ind)
Lua bindings to interact with OpenGL textures.
Definition nlua_tex.c:89
static int texL_setWrap(lua_State *L)
Sets the texture wrapping.
Definition nlua_tex.c:526
static int texL_readData(lua_State *L)
Reads image data from a file.
Definition nlua_tex.c:303
int lua_istex(lua_State *L, int ind)
Checks to see if ind is a texture.
Definition nlua_tex.c:145
static int texL_spriteFromDir(lua_State *L)
Gets the sprite that corresponds to a direction.
Definition nlua_tex.c:467
glTexture ** lua_pushtex(lua_State *L, glTexture *texture)
Pushes a texture on the stack.
Definition nlua_tex.c:130
static int texL_new(lua_State *L)
Opens a texture.
Definition nlua_tex.c:193
glTexture * luaL_checktex(lua_State *L, int ind)
Gets texture at index or raises error if there is no texture at index.
Definition nlua_tex.c:100
static int texL_writeData(lua_State *L)
Saves texture data as a png.
Definition nlua_tex.c:370
static int texL_sprites(lua_State *L)
Gets the number of sprites in the texture.
Definition nlua_tex.c:445
glTexture * luaL_validtex(lua_State *L, int ind, const char *searchpath)
Gets texture directly or from a filename (string) at index or raises error if there is no texture at ...
Definition nlua_tex.c:115
static int texL_close(lua_State *L)
Frees the texture.
Definition nlua_tex.c:167
static const luaL_Reg texL_methods[]
Definition nlua_tex.c:42
static int texL_setFilter(lua_State *L)
Sets the texture minification and magnification filters.
Definition nlua_tex.c:496
int nlua_loadTex(nlua_env env)
Loads the texture library.
Definition nlua_tex.c:62
GLint gl_stringToFilter(const char *s)
Gets the associated min/mag filter from a string.
Definition opengl.c:643
GLint gl_stringToClamp(const char *s)
Gets the associated min/mag filter from a string.
Definition opengl.c:658
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
Definition opengl_tex.c:917
glTexture * gl_newSprite(const char *path, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
Definition opengl_tex.c:791
glTexture * gl_newSpriteRWops(const char *path, SDL_RWops *rw, const int sx, const int sy, const unsigned int flags)
Loads the texture immediately, but also sets it as a sprite.
Definition opengl_tex.c:829
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
Definition opengl_tex.c:675
void gl_getSpriteFromDir(int *x, int *y, const glTexture *t, const double dir)
Sets x and y to be the appropriate sprite for glTexture using dir.
Definition opengl_tex.c:967
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition opengl_tex.c:862
Wrapper to datas.
Definition nlua_data.h:17
LuaDataType_t type
Definition nlua_data.h:21
void * data
Definition nlua_data.h:20
size_t size
Definition nlua_data.h:18
size_t elem
Definition nlua_data.h:19
Wrapper to files.
Definition nlua_file.h:17
char path[PATH_MAX]
Definition nlua_file.h:18
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:36
double sw
Definition opengl_tex.h:46
double sh
Definition opengl_tex.h:47
double w
Definition opengl_tex.h:40
double sx
Definition opengl_tex.h:44
GLuint texture
Definition opengl_tex.h:52
double sy
Definition opengl_tex.h:45
double h
Definition opengl_tex.h:41