naev 0.10.4
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 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 NLUA_ERROR( L, _("Spritesheet dimensions must be positive") );
222 if (ld->type != LUADATA_NUMBER)
223 NLUA_ERROR( L, _("Data has invalid type for texture") );
224 if (w*h*ld->elem*4 != ld->size)
225 NLUA_ERROR( L, _("Texture dimensions don't match data size!") );
226 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 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 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 int i, j;
314 float *data;
315
316 s = NULL;
317 if (lua_isfile(L,1)) {
318 lf = luaL_checkfile(L,1);
319 s = lf->path;
320 }
321 else
322 s = luaL_checkstring(L,1);
323 rw = PHYSFSRWOPS_openRead( s );
324 if (rw == NULL)
325 NLUA_ERROR(L, _("problem opening file '%s' for reading"), s );
326
327 /* Try to read the image. */
328 surface = IMG_Load_RW( rw, 1 );
329 if (surface == NULL)
330 NLUA_ERROR(L, _("problem opening image for reading") );
331
332 /* Convert surface to LuaData_t */
333 SDL_LockSurface( surface );
334 size = surface->w * surface->h;
335 ld.elem = sizeof(float);
336 ld.size = ld.elem * size * 4;
337 ld.data = calloc( ld.elem*4, size );
338 ld.type = LUADATA_NUMBER;
339 data = (float*)ld.data;
340 for (i=0; i<surface->h; i++) {
341 for (j=0; j<surface->w; j++) {
342 pix = get_pixel( surface, j, i );
343 SDL_GetRGBA( pix, surface->format, &r, &g, &b, &a );
344 size_t pos = 4*((surface->h-i-1)*surface->w+j);
345 data[ pos+0 ] = ((float)r)/255.;
346 data[ pos+1 ] = ((float)g)/255.;
347 data[ pos+2 ] = ((float)b)/255.;
348 data[ pos+3 ] = ((float)a)/255.;
349 }
350 }
351 SDL_UnlockSurface( surface );
352
353 /* Return parameters. */
354 lua_pushdata(L, ld);
355 lua_pushinteger(L, surface->w);
356 lua_pushinteger(L, surface->h);
357
358 /* Clean up. */
359 SDL_FreeSurface( surface );
360
361 return 3;
362}
363
371static int texL_writeData( lua_State *L )
372{
373 glTexture *tex = luaL_checktex(L,1);
374 const char *filename = luaL_checkstring(L,2);
375 int w, h;
376 size_t len;
377 char *data;
378 SDL_Surface *surface;
379 SDL_RWops *rw;
380
381 w = tex->w;
382 h = tex->h;
383 len = w * h * 4 * sizeof(GLubyte);
384 data = malloc( len );
385
386 /* Read raw data. */
387 glBindTexture( GL_TEXTURE_2D, tex->texture );
388 glGetTexImage( GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
389 gl_checkErr();
390
391 /* Convert to PNG. */
392 surface = SDL_CreateRGBSurface( 0, w, h, 32, RGBAMASK );
393 for (int i=0; i<h; i++)
394 memcpy( (GLubyte*)surface->pixels + i * (4*w), &data[ (h - i - 1) * (4*w) ], 4*w );
395
396 /* Free buffer. */
397 free( data );
398
399 /* Save to file. */
400 if (!(rw = PHYSFSRWOPS_openWrite( filename )))
401 NLUA_ERROR(L,_("Unable to open '%s' for writing!"),filename);
402 else
403 IMG_SavePNG_RW( surface, rw, 1 );
404
405 SDL_FreeSurface( surface );
406
407 lua_pushboolean(L,1);
408 return 1;
409}
410
423static int texL_dim( lua_State *L )
424{
425 glTexture *tex = luaL_checktex( L, 1 );
426
427 /* Get all 4 values. */
428 lua_pushnumber( L, tex->w );
429 lua_pushnumber( L, tex->h );
430 lua_pushnumber( L, tex->sw );
431 lua_pushnumber( L, tex->sh );
432 return 4;
433}
434
446static int texL_sprites( lua_State *L )
447{
448 glTexture *tex = luaL_checktex( L, 1 );
449
450 /* Get sprites. */
451 lua_pushnumber( L, tex->sx * tex->sy );
452 lua_pushnumber( L, tex->sx );
453 lua_pushnumber( L, tex->sy );
454 return 3;
455}
456
468static int texL_spriteFromDir( lua_State *L )
469{
470
471 int sx, sy;
472
473 glTexture *tex = luaL_checktex( L, 1 );
474 double a = luaL_checknumber( L, 2 );
475
476 /* Calculate with parameter validity.. */
477 if ((a >= 2.*M_PI) || (a < 0.)) {
478 a = fmod( a, 2.*M_PI );
479 if (a < 0.)
480 a += 2.*M_PI;
481 }
482 gl_getSpriteFromDir( &sx, &sy, tex, a );
483
484 /* Return. */
485 lua_pushinteger( L, sx+1 );
486 lua_pushinteger( L, sy+1 );
487 return 2;
488}
489
498static int texL_setFilter( lua_State *L )
499{
500 glTexture *tex = luaL_checktex(L,1);
501 const char *smin = luaL_checkstring(L,2);
502 const char *smag = luaL_optstring(L,3,smin);
503 GLint min, mag;
504
505 min = gl_stringToFilter( smin );
506 mag = gl_stringToFilter( smag );
507
508 if (min==0 || mag==0)
509 NLUA_INVALID_PARAMETER(L);
510
511 glBindTexture( GL_TEXTURE_2D, tex->texture );
512 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag );
513 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min );
514 gl_checkErr();
515
516 return 0;
517}
518
528static int texL_setWrap( lua_State *L )
529{
530 glTexture *tex = luaL_checktex(L,1);
531 const char *shoriz = luaL_checkstring(L,2);
532 const char *svert = luaL_optstring(L,3,shoriz);
533 const char *sdepth = luaL_optstring(L,4,shoriz);
534 GLint horiz, vert, depth;
535
536 horiz = gl_stringToClamp( shoriz );
537 vert = gl_stringToClamp( svert );
538 depth = gl_stringToClamp( sdepth );
539
540 if (horiz==0 || vert==0 || depth==0)
541 NLUA_INVALID_PARAMETER(L);
542
543 glBindTexture( GL_TEXTURE_2D, tex->texture );
544 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, horiz );
545 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vert );
546 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, depth );
547 gl_checkErr();
548
549 return 0;
550}
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:387
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:124
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:95
static int texL_dim(lua_State *L)
Gets the dimensions of the texture.
Definition: nlua_tex.c:423
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:528
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:468
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:371
static int texL_sprites(lua_State *L)
Gets the number of sprites in the texture.
Definition: nlua_tex.c:446
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:498
int nlua_loadTex(nlua_env env)
Loads the texture library.
Definition: nlua_tex.c:62
int asprintf(char **strp, const char *fmt,...)
Like sprintf(), but it allocates a large-enough string and returns the pointer in the first argument....
Definition: nstring.c:161
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:809
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:684
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:722
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
Definition: opengl_tex.c:570
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:857
void gl_freeTexture(glTexture *texture)
Frees a texture.
Definition: opengl_tex.c:755
static const double a[]
Definition: rng.c:247
static const double b[]
Definition: rng.c:256
Wrapper to datas.
Definition: nlua_data.h:17
char * data
Definition: nlua_data.h:20
LuaDataType_t type
Definition: nlua_data.h:21
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:34
double sw
Definition: opengl_tex.h:44
double sh
Definition: opengl_tex.h:45
double w
Definition: opengl_tex.h:38
double sx
Definition: opengl_tex.h:42
GLuint texture
Definition: opengl_tex.h:50
double sy
Definition: opengl_tex.h:43
double h
Definition: opengl_tex.h:39