2016-11-19 09:28:01 +00:00
|
|
|
#include "lovr/graphics.h"
|
|
|
|
#include "lovr/types/buffer.h"
|
|
|
|
#include "lovr/types/model.h"
|
|
|
|
#include "lovr/types/shader.h"
|
|
|
|
#include "lovr/types/skybox.h"
|
|
|
|
#include "lovr/types/texture.h"
|
2017-01-20 03:11:42 +00:00
|
|
|
#include "lovr/types/transform.h"
|
2016-11-19 09:28:01 +00:00
|
|
|
#include "graphics/graphics.h"
|
2017-02-03 23:16:30 +00:00
|
|
|
#include "loaders/font.h"
|
2016-11-26 07:15:04 +00:00
|
|
|
#include "loaders/model.h"
|
2016-11-26 07:54:45 +00:00
|
|
|
#include "loaders/texture.h"
|
2016-11-19 09:28:01 +00:00
|
|
|
#include "filesystem/filesystem.h"
|
2016-10-29 22:17:49 +00:00
|
|
|
#include <math.h>
|
2016-08-10 06:28:17 +00:00
|
|
|
|
2016-11-08 07:16:33 +00:00
|
|
|
static void luax_readvertices(lua_State* L, int index, vec_float_t* points) {
|
|
|
|
int isTable = lua_istable(L, index);
|
|
|
|
|
|
|
|
if (!isTable && !lua_isnumber(L, index)) {
|
|
|
|
luaL_error(L, "Expected number or table, got '%s'", lua_typename(L, lua_type(L, 1)));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-23 04:43:22 +00:00
|
|
|
int count = isTable ? lua_objlen(L, index) : lua_gettop(L) - index + 1;
|
2016-11-08 07:16:33 +00:00
|
|
|
if (count % 3 != 0) {
|
|
|
|
vec_deinit(points);
|
|
|
|
luaL_error(L, "Number of coordinates must be a multiple of 3, got '%d'", count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec_reserve(points, count);
|
|
|
|
|
|
|
|
if (isTable) {
|
|
|
|
for (int i = 1; i <= count; i++) {
|
|
|
|
lua_rawgeti(L, index, i);
|
|
|
|
vec_push(points, lua_tonumber(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
vec_push(points, lua_tonumber(L, index + i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-30 03:03:50 +00:00
|
|
|
static Texture* luax_readtexture(lua_State* L, int index) {
|
|
|
|
const char* path = luaL_checkstring(L, index);
|
|
|
|
int size;
|
|
|
|
void* data = lovrFilesystemRead(path, &size);
|
|
|
|
if (!data) {
|
|
|
|
luaL_error(L, "Could not load texture file '%s'", path);
|
|
|
|
}
|
|
|
|
TextureData* textureData = lovrTextureDataFromFile(data, size);
|
|
|
|
Texture* texture = lovrTextureCreate(textureData);
|
|
|
|
free(data);
|
|
|
|
return texture;
|
|
|
|
}
|
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
const luaL_Reg lovrGraphics[] = {
|
2016-09-28 03:20:08 +00:00
|
|
|
{ "reset", l_lovrGraphicsReset },
|
2016-08-10 06:28:17 +00:00
|
|
|
{ "clear", l_lovrGraphicsClear },
|
|
|
|
{ "present", l_lovrGraphicsPresent },
|
2016-09-28 04:37:46 +00:00
|
|
|
{ "getBackgroundColor", l_lovrGraphicsGetBackgroundColor },
|
|
|
|
{ "setBackgroundColor", l_lovrGraphicsSetBackgroundColor },
|
2016-09-29 03:11:58 +00:00
|
|
|
{ "getColor", l_lovrGraphicsGetColor },
|
|
|
|
{ "setColor", l_lovrGraphicsSetColor },
|
2016-09-28 04:32:57 +00:00
|
|
|
{ "getColorMask", l_lovrGraphicsGetColorMask },
|
|
|
|
{ "setColorMask", l_lovrGraphicsSetColorMask },
|
2016-09-29 04:47:36 +00:00
|
|
|
{ "getScissor", l_lovrGraphicsGetScissor },
|
|
|
|
{ "setScissor", l_lovrGraphicsSetScissor },
|
2016-10-01 20:44:20 +00:00
|
|
|
{ "getShader", l_lovrGraphicsGetShader },
|
2016-08-10 06:28:17 +00:00
|
|
|
{ "setShader", l_lovrGraphicsSetShader },
|
2017-02-03 23:16:30 +00:00
|
|
|
{ "getFont", l_lovrGraphicsGetFont },
|
|
|
|
{ "setFont", l_lovrGraphicsSetFont },
|
2016-09-24 05:11:56 +00:00
|
|
|
{ "setProjection", l_lovrGraphicsSetProjection },
|
2016-10-01 20:48:31 +00:00
|
|
|
{ "getLineWidth", l_lovrGraphicsGetLineWidth },
|
|
|
|
{ "setLineWidth", l_lovrGraphicsSetLineWidth },
|
2016-11-13 01:38:49 +00:00
|
|
|
{ "getPointSize", l_lovrGraphicsGetPointSize },
|
|
|
|
{ "setPointSize", l_lovrGraphicsSetPointSize },
|
2016-10-03 19:02:49 +00:00
|
|
|
{ "isCullingEnabled", l_lovrGraphicsIsCullingEnabled },
|
|
|
|
{ "setCullingEnabled", l_lovrGraphicsSetCullingEnabled },
|
|
|
|
{ "getPolygonWinding", l_lovrGraphicsGetPolygonWinding },
|
|
|
|
{ "setPolygonWinding", l_lovrGraphicsSetPolygonWinding },
|
2016-11-23 04:59:11 +00:00
|
|
|
{ "getDepthTest", l_lovrGraphicsGetDepthTest },
|
|
|
|
{ "setDepthTest", l_lovrGraphicsSetDepthTest },
|
2016-11-23 05:07:33 +00:00
|
|
|
{ "isWireframe", l_lovrGraphicsIsWireframe },
|
|
|
|
{ "setWireframe", l_lovrGraphicsSetWireframe },
|
2016-09-21 07:55:53 +00:00
|
|
|
{ "push", l_lovrGraphicsPush },
|
|
|
|
{ "pop", l_lovrGraphicsPop },
|
2016-09-21 22:26:05 +00:00
|
|
|
{ "origin", l_lovrGraphicsOrigin },
|
2016-09-23 04:53:17 +00:00
|
|
|
{ "translate", l_lovrGraphicsTranslate },
|
|
|
|
{ "rotate", l_lovrGraphicsRotate },
|
|
|
|
{ "scale", l_lovrGraphicsScale },
|
2017-01-20 03:13:37 +00:00
|
|
|
{ "transform", l_lovrGraphicsTransform },
|
2016-11-08 07:16:33 +00:00
|
|
|
{ "points", l_lovrGraphicsPoints },
|
2016-09-30 02:39:25 +00:00
|
|
|
{ "line", l_lovrGraphicsLine },
|
2016-11-23 04:43:22 +00:00
|
|
|
{ "triangle", l_lovrGraphicsTriangle },
|
2016-10-04 03:56:45 +00:00
|
|
|
{ "plane", l_lovrGraphicsPlane },
|
2016-09-30 06:18:51 +00:00
|
|
|
{ "cube", l_lovrGraphicsCube },
|
2017-02-03 23:16:30 +00:00
|
|
|
{ "print", l_lovrGraphicsPrint },
|
2016-09-29 05:10:03 +00:00
|
|
|
{ "getWidth", l_lovrGraphicsGetWidth },
|
|
|
|
{ "getHeight", l_lovrGraphicsGetHeight },
|
|
|
|
{ "getDimensions", l_lovrGraphicsGetDimensions },
|
2016-08-10 06:28:17 +00:00
|
|
|
{ "newBuffer", l_lovrGraphicsNewBuffer },
|
2017-02-03 23:16:30 +00:00
|
|
|
{ "newFont", l_lovrGraphicsNewFont },
|
|
|
|
{ "newModel", l_lovrGraphicsNewModel },
|
2016-08-10 06:28:17 +00:00
|
|
|
{ "newShader", l_lovrGraphicsNewShader },
|
2016-10-16 03:11:54 +00:00
|
|
|
{ "newSkybox", l_lovrGraphicsNewSkybox },
|
2016-11-08 11:14:33 +00:00
|
|
|
{ "newTexture", l_lovrGraphicsNewTexture },
|
2016-08-10 06:28:17 +00:00
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
|
2016-11-23 05:16:13 +00:00
|
|
|
// Base
|
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
int l_lovrGraphicsInit(lua_State* L) {
|
|
|
|
lua_newtable(L);
|
|
|
|
luaL_register(L, NULL, lovrGraphics);
|
2017-01-21 03:46:45 +00:00
|
|
|
luax_registertype(L, "Buffer", lovrBuffer);
|
2017-02-03 23:16:30 +00:00
|
|
|
luax_registertype(L, "Font", NULL);
|
2017-01-21 03:46:45 +00:00
|
|
|
luax_registertype(L, "Model", lovrModel);
|
|
|
|
luax_registertype(L, "Shader", lovrShader);
|
|
|
|
luax_registertype(L, "Skybox", lovrSkybox);
|
|
|
|
luax_registertype(L, "Texture", lovrTexture);
|
2016-09-17 22:38:13 +00:00
|
|
|
|
2016-10-10 00:40:02 +00:00
|
|
|
map_init(&BufferAttributeTypes);
|
|
|
|
map_set(&BufferAttributeTypes, "float", BUFFER_FLOAT);
|
|
|
|
map_set(&BufferAttributeTypes, "byte", BUFFER_BYTE);
|
2016-11-15 05:31:17 +00:00
|
|
|
map_set(&BufferAttributeTypes, "int", BUFFER_INT);
|
2016-10-10 00:40:02 +00:00
|
|
|
|
2016-09-17 22:38:13 +00:00
|
|
|
map_init(&BufferDrawModes);
|
|
|
|
map_set(&BufferDrawModes, "points", BUFFER_POINTS);
|
|
|
|
map_set(&BufferDrawModes, "strip", BUFFER_TRIANGLE_STRIP);
|
|
|
|
map_set(&BufferDrawModes, "triangles", BUFFER_TRIANGLES);
|
|
|
|
map_set(&BufferDrawModes, "fan", BUFFER_TRIANGLE_FAN);
|
|
|
|
|
|
|
|
map_init(&BufferUsages);
|
|
|
|
map_set(&BufferUsages, "static", BUFFER_STATIC);
|
|
|
|
map_set(&BufferUsages, "dynamic", BUFFER_DYNAMIC);
|
|
|
|
map_set(&BufferUsages, "stream", BUFFER_STREAM);
|
|
|
|
|
2016-10-01 19:10:38 +00:00
|
|
|
map_init(&DrawModes);
|
|
|
|
map_set(&DrawModes, "fill", DRAW_MODE_FILL);
|
|
|
|
map_set(&DrawModes, "line", DRAW_MODE_LINE);
|
|
|
|
|
2016-10-03 19:02:49 +00:00
|
|
|
map_init(&PolygonWindings);
|
|
|
|
map_set(&PolygonWindings, "clockwise", POLYGON_WINDING_CLOCKWISE);
|
|
|
|
map_set(&PolygonWindings, "counterclockwise", POLYGON_WINDING_COUNTERCLOCKWISE);
|
|
|
|
|
2016-11-23 04:59:11 +00:00
|
|
|
map_init(&CompareModes);
|
|
|
|
map_set(&CompareModes, "equal", COMPARE_EQUAL);
|
|
|
|
map_set(&CompareModes, "notequal", COMPARE_NOT_EQUAL);
|
|
|
|
map_set(&CompareModes, "less", COMPARE_LESS);
|
|
|
|
map_set(&CompareModes, "lequal", COMPARE_LEQUAL);
|
|
|
|
map_set(&CompareModes, "gequal", COMPARE_GEQUAL);
|
|
|
|
map_set(&CompareModes, "greater", COMPARE_GREATER);
|
|
|
|
|
2016-11-08 22:44:22 +00:00
|
|
|
map_init(&FilterModes);
|
|
|
|
map_set(&FilterModes, "nearest", FILTER_NEAREST);
|
|
|
|
map_set(&FilterModes, "linear", FILTER_LINEAR);
|
|
|
|
|
|
|
|
map_init(&WrapModes);
|
|
|
|
map_set(&WrapModes, "clamp", WRAP_CLAMP);
|
|
|
|
map_set(&WrapModes, "repeat", WRAP_REPEAT);
|
|
|
|
map_set(&WrapModes, "mirroredrepeat", WRAP_MIRRORED_REPEAT);
|
|
|
|
map_set(&WrapModes, "clampzero", WRAP_CLAMP_ZERO);
|
|
|
|
|
2017-01-12 07:38:28 +00:00
|
|
|
map_init(&TextureProjections);
|
|
|
|
map_set(&TextureProjections, "2d", PROJECTION_ORTHOGRAPHIC);
|
|
|
|
map_set(&TextureProjections, "3d", PROJECTION_PERSPECTIVE);
|
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
lovrGraphicsInit();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-09-28 03:20:08 +00:00
|
|
|
int l_lovrGraphicsReset(lua_State* L) {
|
|
|
|
lovrGraphicsReset();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
int l_lovrGraphicsClear(lua_State* L) {
|
2016-09-17 03:11:11 +00:00
|
|
|
int color = lua_gettop(L) < 1 || lua_toboolean(L, 1);
|
|
|
|
int depth = lua_gettop(L) < 2 || lua_toboolean(L, 2);
|
|
|
|
lovrGraphicsClear(color, depth);
|
2016-08-10 06:28:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsPresent(lua_State* L) {
|
|
|
|
lovrGraphicsPresent();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 05:16:13 +00:00
|
|
|
// State
|
|
|
|
|
2016-09-28 04:37:46 +00:00
|
|
|
int l_lovrGraphicsGetBackgroundColor(lua_State* L) {
|
2016-08-10 06:28:17 +00:00
|
|
|
float r, g, b, a;
|
2016-09-28 04:37:46 +00:00
|
|
|
lovrGraphicsGetBackgroundColor(&r, &g, &b, &a);
|
2016-08-10 06:28:17 +00:00
|
|
|
lua_pushnumber(L, r);
|
|
|
|
lua_pushnumber(L, g);
|
|
|
|
lua_pushnumber(L, b);
|
|
|
|
lua_pushnumber(L, a);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2016-09-28 04:37:46 +00:00
|
|
|
int l_lovrGraphicsSetBackgroundColor(lua_State* L) {
|
2016-08-10 06:28:17 +00:00
|
|
|
float r = luaL_checknumber(L, 1);
|
|
|
|
float g = luaL_checknumber(L, 2);
|
|
|
|
float b = luaL_checknumber(L, 3);
|
|
|
|
float a = 255.0;
|
|
|
|
if (lua_gettop(L) > 3) {
|
|
|
|
a = luaL_checknumber(L, 4);
|
|
|
|
}
|
2016-09-28 04:37:46 +00:00
|
|
|
lovrGraphicsSetBackgroundColor(r, g, b, a);
|
2016-08-10 06:28:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-29 03:11:58 +00:00
|
|
|
int l_lovrGraphicsGetColor(lua_State* L) {
|
|
|
|
unsigned char r, g, b, a;
|
|
|
|
lovrGraphicsGetColor(&r, &g, &b, &a);
|
|
|
|
lua_pushinteger(L, r);
|
|
|
|
lua_pushinteger(L, g);
|
|
|
|
lua_pushinteger(L, b);
|
|
|
|
lua_pushinteger(L, a);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetColor(lua_State* L) {
|
2016-11-30 18:53:21 +00:00
|
|
|
unsigned char r, g, b, a;
|
|
|
|
r = g = b = a = 0xff;
|
|
|
|
|
|
|
|
if (lua_gettop(L) == 1 && lua_isnumber(L, 1)) {
|
|
|
|
unsigned int x = lua_tointeger(L, 1);
|
|
|
|
r = LOVR_COLOR_R(x);
|
|
|
|
g = LOVR_COLOR_G(x);
|
|
|
|
b = LOVR_COLOR_B(x);
|
|
|
|
a = LOVR_COLOR_A(x);
|
|
|
|
} else if (lua_istable(L, 1)) {
|
|
|
|
for (int i = 1; i <= 4; i++) {
|
|
|
|
lua_rawgeti(L, 1, i);
|
|
|
|
}
|
|
|
|
r = luaL_checknumber(L, -4);
|
|
|
|
g = luaL_checknumber(L, -3);
|
|
|
|
b = luaL_checknumber(L, -2);
|
|
|
|
a = lua_gettop(L) > 1 ? luaL_checknumber(L, 2) : luaL_optnumber(L, -1, 255);
|
|
|
|
lua_pop(L, 4);
|
|
|
|
} else if (lua_gettop(L) >= 3) {
|
|
|
|
r = lua_tointeger(L, 1);
|
|
|
|
g = lua_tointeger(L, 2);
|
|
|
|
b = lua_tointeger(L, 3);
|
|
|
|
a = lua_isnoneornil(L, 4) ? 255 : lua_tointeger(L, 4);
|
2016-09-29 03:11:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lovrGraphicsSetColor(r, g, b, a);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-28 04:32:57 +00:00
|
|
|
int l_lovrGraphicsGetColorMask(lua_State* L) {
|
2016-10-03 18:41:31 +00:00
|
|
|
char r, g, b, a;
|
2016-09-28 04:32:57 +00:00
|
|
|
lovrGraphicsGetColorMask(&r, &g, &b, &a);
|
|
|
|
lua_pushboolean(L, r);
|
|
|
|
lua_pushboolean(L, g);
|
|
|
|
lua_pushboolean(L, b);
|
|
|
|
lua_pushboolean(L, a);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetColorMask(lua_State* L) {
|
|
|
|
if (lua_gettop(L) <= 1 && lua_isnoneornil(L, 1)) {
|
|
|
|
lovrGraphicsSetColorMask(1, 1, 1, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-03 18:41:31 +00:00
|
|
|
char r = lua_toboolean(L, 1);
|
|
|
|
char g = lua_toboolean(L, 2);
|
|
|
|
char b = lua_toboolean(L, 3);
|
|
|
|
char a = lua_toboolean(L, 4);
|
2016-09-28 04:32:57 +00:00
|
|
|
lovrGraphicsSetColorMask(r, g, b, a);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-29 04:47:36 +00:00
|
|
|
int l_lovrGraphicsGetScissor(lua_State* L) {
|
|
|
|
if (!lovrGraphicsIsScissorEnabled()) {
|
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x, y, width, height;
|
|
|
|
lovrGraphicsGetScissor(&x, &y, &width, &height);
|
|
|
|
lua_pushnumber(L, x);
|
|
|
|
lua_pushnumber(L, y);
|
|
|
|
lua_pushnumber(L, width);
|
|
|
|
lua_pushnumber(L, height);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetScissor(lua_State* L) {
|
|
|
|
if (lua_gettop(L) <= 1 && lua_isnoneornil(L, 1)) {
|
|
|
|
lovrGraphicsSetScissorEnabled(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = luaL_checkint(L, 1);
|
|
|
|
int y = luaL_checkint(L, 2);
|
|
|
|
int width = luaL_checkint(L, 3);
|
|
|
|
int height = luaL_checkint(L, 4);
|
|
|
|
lovrGraphicsSetScissor(x, y, width, height);
|
|
|
|
lovrGraphicsSetScissorEnabled(1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-14 00:02:23 +00:00
|
|
|
int l_lovrGraphicsGetShader(lua_State* L) {
|
2016-11-19 08:57:18 +00:00
|
|
|
luax_pushtype(L, Shader, lovrGraphicsGetShader());
|
2016-09-14 00:02:23 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
int l_lovrGraphicsSetShader(lua_State* L) {
|
2016-11-19 08:57:18 +00:00
|
|
|
Shader* shader = lua_isnoneornil(L, 1) ? NULL : luax_checktype(L, 1, Shader);
|
2016-08-10 06:28:17 +00:00
|
|
|
lovrGraphicsSetShader(shader);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-03 23:16:30 +00:00
|
|
|
int l_lovrGraphicsGetFont(lua_State* L) {
|
|
|
|
luax_pushtype(L, Font, lovrGraphicsGetFont());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetFont(lua_State* L) {
|
|
|
|
Font* font = luax_checktype(L, 1, Font);
|
|
|
|
lovrGraphicsSetFont(font);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-24 05:11:56 +00:00
|
|
|
int l_lovrGraphicsSetProjection(lua_State* L) {
|
|
|
|
float near = luaL_checknumber(L, 1);
|
|
|
|
float far = luaL_checknumber(L, 2);
|
|
|
|
float fov = luaL_checknumber(L, 3);
|
2016-09-27 06:48:09 +00:00
|
|
|
lovrGraphicsSetProjection(near, far, fov);
|
2016-09-24 05:11:56 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-01 20:48:31 +00:00
|
|
|
int l_lovrGraphicsGetLineWidth(lua_State* L) {
|
|
|
|
lua_pushnumber(L, lovrGraphicsGetLineWidth());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetLineWidth(lua_State* L) {
|
|
|
|
float width = luaL_optnumber(L, 1, 1.f);
|
|
|
|
lovrGraphicsSetLineWidth(width);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-13 01:38:49 +00:00
|
|
|
int l_lovrGraphicsGetPointSize(lua_State* L) {
|
|
|
|
lua_pushnumber(L, lovrGraphicsGetPointSize());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetPointSize(lua_State* L) {
|
|
|
|
float size = luaL_optnumber(L, 1, 1.f);
|
|
|
|
lovrGraphicsSetPointSize(size);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:02:49 +00:00
|
|
|
int l_lovrGraphicsIsCullingEnabled(lua_State* L) {
|
|
|
|
lua_pushboolean(L, lovrGraphicsIsCullingEnabled());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetCullingEnabled(lua_State* L) {
|
|
|
|
lovrGraphicsSetCullingEnabled(lua_toboolean(L, 1));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsGetPolygonWinding(lua_State* L) {
|
2017-01-22 01:38:44 +00:00
|
|
|
luax_pushenum(L, &PolygonWindings, lovrGraphicsGetPolygonWinding());
|
2016-11-08 22:15:37 +00:00
|
|
|
return 1;
|
2016-10-03 19:02:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetPolygonWinding(lua_State* L) {
|
2016-11-23 04:45:57 +00:00
|
|
|
PolygonWinding* winding = (PolygonWinding*) luax_checkenum(L, 1, &PolygonWindings, "winding direction");
|
2016-10-03 19:02:49 +00:00
|
|
|
lovrGraphicsSetPolygonWinding(*winding);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 04:59:11 +00:00
|
|
|
int l_lovrGraphicsGetDepthTest(lua_State* L) {
|
2017-01-22 01:38:44 +00:00
|
|
|
luax_pushenum(L, &CompareModes, lovrGraphicsGetDepthTest());
|
2016-11-23 04:59:11 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetDepthTest(lua_State* L) {
|
2016-11-24 23:45:59 +00:00
|
|
|
if (lua_isnoneornil(L, 1)) {
|
|
|
|
lovrGraphicsSetDepthTest(COMPARE_NONE);
|
|
|
|
} else {
|
|
|
|
CompareMode* depthTest = (CompareMode*) luax_checkenum(L, 1, &CompareModes, "compare mode");
|
|
|
|
lovrGraphicsSetDepthTest(*depthTest);
|
|
|
|
}
|
2016-11-23 04:59:11 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 05:07:33 +00:00
|
|
|
int l_lovrGraphicsIsWireframe(lua_State* L) {
|
|
|
|
lua_pushboolean(L, lovrGraphicsIsWireframe());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsSetWireframe(lua_State* L) {
|
|
|
|
lovrGraphicsSetWireframe(lua_toboolean(L, 1));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 05:16:13 +00:00
|
|
|
int l_lovrGraphicsGetWidth(lua_State* L) {
|
|
|
|
lua_pushnumber(L, lovrGraphicsGetWidth());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsGetHeight(lua_State* L) {
|
|
|
|
lua_pushnumber(L, lovrGraphicsGetHeight());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsGetDimensions(lua_State* L) {
|
|
|
|
lua_pushnumber(L, lovrGraphicsGetWidth());
|
|
|
|
lua_pushnumber(L, lovrGraphicsGetHeight());
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Transforms
|
|
|
|
|
2016-09-21 07:55:53 +00:00
|
|
|
int l_lovrGraphicsPush(lua_State* L) {
|
|
|
|
if (lovrGraphicsPush()) {
|
|
|
|
return luaL_error(L, "Unbalanced matrix stack (more pushes than pops?)");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsPop(lua_State* L) {
|
|
|
|
if (lovrGraphicsPop()) {
|
|
|
|
return luaL_error(L, "Unbalanced matrix stack (more pops than pushes?)");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-21 22:26:05 +00:00
|
|
|
int l_lovrGraphicsOrigin(lua_State* L) {
|
|
|
|
lovrGraphicsOrigin();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-23 04:53:17 +00:00
|
|
|
int l_lovrGraphicsTranslate(lua_State* L) {
|
|
|
|
float x = luaL_checknumber(L, 1);
|
|
|
|
float y = luaL_checknumber(L, 2);
|
|
|
|
float z = luaL_checknumber(L, 3);
|
|
|
|
lovrGraphicsTranslate(x, y, z);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsRotate(lua_State* L) {
|
2016-09-29 06:59:10 +00:00
|
|
|
float angle = luaL_checknumber(L, 1);
|
|
|
|
float axisX = luaL_checknumber(L, 2);
|
|
|
|
float axisY = luaL_checknumber(L, 3);
|
|
|
|
float axisZ = luaL_checknumber(L, 4);
|
2016-12-02 01:32:39 +00:00
|
|
|
lovrGraphicsRotate(angle, axisX, axisY, axisZ);
|
2016-09-23 04:53:17 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsScale(lua_State* L) {
|
|
|
|
float x = luaL_checknumber(L, 1);
|
|
|
|
float y = luaL_checknumber(L, 2);
|
|
|
|
float z = luaL_checknumber(L, 3);
|
|
|
|
lovrGraphicsScale(x, y, z);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-01-20 03:13:37 +00:00
|
|
|
int l_lovrGraphicsTransform(lua_State* L) {
|
|
|
|
float transform[16];
|
|
|
|
luax_readtransform(L, 1, transform);
|
|
|
|
lovrGraphicsMatrixTransform(transform);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 05:16:13 +00:00
|
|
|
// Primitives
|
|
|
|
|
2016-11-08 07:16:33 +00:00
|
|
|
int l_lovrGraphicsPoints(lua_State* L) {
|
2016-09-30 02:39:25 +00:00
|
|
|
vec_float_t points;
|
|
|
|
vec_init(&points);
|
2016-11-08 07:16:33 +00:00
|
|
|
luax_readvertices(L, 1, &points);
|
|
|
|
lovrGraphicsPoints(points.data, points.length);
|
|
|
|
vec_deinit(&points);
|
|
|
|
return 0;
|
|
|
|
}
|
2016-09-30 02:39:25 +00:00
|
|
|
|
2016-11-08 07:16:33 +00:00
|
|
|
int l_lovrGraphicsLine(lua_State* L) {
|
|
|
|
vec_float_t points;
|
|
|
|
vec_init(&points);
|
|
|
|
luax_readvertices(L, 1, &points);
|
|
|
|
lovrGraphicsLine(points.data, points.length);
|
2016-09-30 02:39:25 +00:00
|
|
|
vec_deinit(&points);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 04:43:22 +00:00
|
|
|
int l_lovrGraphicsTriangle(lua_State* L) {
|
|
|
|
DrawMode* drawMode = (DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
|
|
|
|
int top = lua_gettop(L);
|
|
|
|
if (top != 10) {
|
|
|
|
return luaL_error(L, "Expected 9 coordinates to make a triangle, got %d values", top - 1);
|
|
|
|
}
|
|
|
|
vec_float_t points;
|
|
|
|
vec_init(&points);
|
|
|
|
luax_readvertices(L, 2, &points);
|
|
|
|
lovrGraphicsTriangle(*drawMode, points.data);
|
|
|
|
vec_deinit(&points);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-10-04 03:56:45 +00:00
|
|
|
int l_lovrGraphicsPlane(lua_State* L) {
|
2017-01-13 09:59:00 +00:00
|
|
|
Texture* texture = NULL;
|
|
|
|
DrawMode drawMode;
|
|
|
|
if (lua_isstring(L, 1)) {
|
|
|
|
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
|
|
|
|
} else {
|
|
|
|
drawMode = DRAW_MODE_FILL;
|
|
|
|
texture = luax_checktype(L, 1, Texture);
|
|
|
|
if (lua_gettop(L) == 1) {
|
|
|
|
lovrGraphicsPlaneFullscreen(texture);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2016-10-04 03:56:45 +00:00
|
|
|
float x = luaL_optnumber(L, 2, 0.f);
|
|
|
|
float y = luaL_optnumber(L, 3, 0.f);
|
|
|
|
float z = luaL_optnumber(L, 4, 0.f);
|
|
|
|
float s = luaL_optnumber(L, 5, 1.f);
|
|
|
|
float nx = luaL_optnumber(L, 6, 0.f);
|
|
|
|
float ny = luaL_optnumber(L, 7, 1.f);
|
|
|
|
float nz = luaL_optnumber(L, 8, 0.f);
|
2017-01-13 09:59:00 +00:00
|
|
|
lovrGraphicsPlane(drawMode, texture, x, y, z, s, nx, ny, nz);
|
2016-10-04 03:56:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-30 06:18:51 +00:00
|
|
|
int l_lovrGraphicsCube(lua_State* L) {
|
2017-01-13 09:59:00 +00:00
|
|
|
Texture* texture = NULL;
|
|
|
|
DrawMode drawMode;
|
|
|
|
if (lua_isstring(L, 1)) {
|
|
|
|
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
|
|
|
|
} else {
|
|
|
|
drawMode = DRAW_MODE_FILL;
|
|
|
|
texture = luax_checktype(L, 1, Texture);
|
|
|
|
}
|
2017-01-20 03:11:42 +00:00
|
|
|
float transform[16];
|
|
|
|
luax_readtransform(L, 2, transform);
|
|
|
|
lovrGraphicsCube(drawMode, texture, transform);
|
2016-09-30 06:18:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-03 23:16:30 +00:00
|
|
|
int l_lovrGraphicsPrint(lua_State* L) {
|
|
|
|
const char* str = luaL_checkstring(L, 1);
|
|
|
|
lovrGraphicsPrint(str);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-11-23 05:16:13 +00:00
|
|
|
// Types
|
2016-09-29 05:10:03 +00:00
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
int l_lovrGraphicsNewBuffer(lua_State* L) {
|
2016-10-10 00:40:02 +00:00
|
|
|
int size;
|
|
|
|
int dataIndex = 0;
|
|
|
|
int drawModeIndex = 2;
|
|
|
|
BufferFormat format;
|
|
|
|
vec_init(&format);
|
|
|
|
|
|
|
|
if (lua_isnumber(L, 1)) {
|
|
|
|
size = lua_tointeger(L, 1);
|
|
|
|
} else if (lua_istable(L, 1)) {
|
|
|
|
if (lua_isnumber(L, 2)) {
|
2016-11-13 10:42:05 +00:00
|
|
|
drawModeIndex++;
|
2016-10-10 00:40:02 +00:00
|
|
|
luax_checkbufferformat(L, 1, &format);
|
|
|
|
size = lua_tointeger(L, 2);
|
|
|
|
dataIndex = 0;
|
|
|
|
} else if (lua_istable(L, 2)) {
|
2016-11-13 10:42:05 +00:00
|
|
|
drawModeIndex++;
|
2016-10-10 00:40:02 +00:00
|
|
|
luax_checkbufferformat(L, 1, &format);
|
|
|
|
size = lua_objlen(L, 2);
|
|
|
|
dataIndex = 2;
|
|
|
|
} else {
|
|
|
|
size = lua_objlen(L, 1);
|
|
|
|
dataIndex = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
luaL_argerror(L, 1, "table or number expected");
|
2016-11-08 22:15:37 +00:00
|
|
|
return 0;
|
2016-10-10 00:40:02 +00:00
|
|
|
}
|
|
|
|
|
2016-11-08 22:15:37 +00:00
|
|
|
BufferDrawMode* drawMode = (BufferDrawMode*) luax_optenum(L, drawModeIndex, "fan", &BufferDrawModes, "buffer draw mode");
|
|
|
|
BufferUsage* usage = (BufferUsage*) luax_optenum(L, drawModeIndex + 1, "dynamic", &BufferUsages, "buffer usage");
|
2016-10-10 00:40:02 +00:00
|
|
|
Buffer* buffer = lovrBufferCreate(size, format.length ? &format : NULL, *drawMode, *usage);
|
|
|
|
|
|
|
|
if (dataIndex) {
|
|
|
|
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
2016-11-21 01:33:19 +00:00
|
|
|
for (size_t i = 0; i < lua_objlen(L, dataIndex); i++) {
|
2016-10-10 00:40:02 +00:00
|
|
|
lua_rawgeti(L, dataIndex, i + 1);
|
|
|
|
if (!lua_istable(L, -1)) {
|
|
|
|
return luaL_error(L, "Vertex information should be specified as a table");
|
|
|
|
}
|
|
|
|
|
2016-11-21 01:33:19 +00:00
|
|
|
int component = 0;
|
|
|
|
char* vertex = lovrBufferGetScratchVertex(buffer);
|
|
|
|
for (int j = 0; j < format.length; j++) {
|
|
|
|
BufferAttribute attribute = format.data[j];
|
2016-11-20 23:53:36 +00:00
|
|
|
for (int k = 0; k < attribute.count; k++) {
|
2016-11-21 01:33:19 +00:00
|
|
|
lua_rawgeti(L, -1, ++component);
|
|
|
|
switch (attribute.type) {
|
|
|
|
case BUFFER_FLOAT: *((float*) vertex) = luaL_optnumber(L, -1, 0.f); break;
|
|
|
|
case BUFFER_BYTE: *((unsigned char*) vertex) = luaL_optint(L, -1, 255); break;
|
|
|
|
case BUFFER_INT: *((int*) vertex) = luaL_optint(L, -1, 0); break;
|
2016-10-10 00:40:02 +00:00
|
|
|
}
|
2016-11-21 01:33:19 +00:00
|
|
|
vertex += sizeof(attribute.type);
|
|
|
|
lua_pop(L, 1);
|
2016-10-10 00:40:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-21 01:33:19 +00:00
|
|
|
lovrBufferSetVertex(buffer, i, lovrBufferGetScratchVertex(buffer));
|
2016-10-10 00:40:02 +00:00
|
|
|
lua_pop(L, 1);
|
2016-09-17 22:38:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-10 00:40:02 +00:00
|
|
|
vec_deinit(&format);
|
2016-11-19 08:37:43 +00:00
|
|
|
luax_pushtype(L, Buffer, buffer);
|
2016-08-10 06:28:17 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-02-03 23:16:30 +00:00
|
|
|
int l_lovrGraphicsNewFont(lua_State* L) {
|
|
|
|
const char* path = luaL_checkstring(L, 1);
|
2017-02-06 04:30:17 +00:00
|
|
|
float fontSize = luaL_optnumber(L, 2, 12);
|
|
|
|
|
2017-02-03 23:16:30 +00:00
|
|
|
int fileSize;
|
|
|
|
void* data = lovrFilesystemRead(path, &fileSize);
|
|
|
|
if (!data) {
|
|
|
|
luaL_error(L, "Could not load font '%s'", path);
|
|
|
|
}
|
2017-02-06 04:30:17 +00:00
|
|
|
|
|
|
|
FontData* fontData = lovrFontDataCreate(data, fileSize, fontSize);
|
2017-02-03 23:16:30 +00:00
|
|
|
Font* font = lovrFontCreate(fontData);
|
|
|
|
luax_pushtype(L, Font, font);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-08-10 06:28:17 +00:00
|
|
|
int l_lovrGraphicsNewModel(lua_State* L) {
|
2016-11-26 09:07:40 +00:00
|
|
|
const char* path = lua_tostring(L, 1);
|
|
|
|
int size;
|
|
|
|
void* data = lovrFilesystemRead(path, &size);
|
|
|
|
if (!data) {
|
|
|
|
return luaL_error(L, "Could not load model file '%s'", path);
|
2016-11-08 06:34:04 +00:00
|
|
|
}
|
|
|
|
|
2016-11-26 09:07:40 +00:00
|
|
|
ModelData* modelData = lovrModelDataFromFile(data, size);
|
2017-01-30 03:03:50 +00:00
|
|
|
Model* model = lovrModelCreate(modelData);
|
|
|
|
|
|
|
|
if (lua_gettop(L) >= 2) {
|
|
|
|
Texture* texture = luax_readtexture(L, 2);
|
|
|
|
lovrModelSetTexture(model, texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
luax_pushtype(L, Model, model);
|
2016-11-26 09:07:40 +00:00
|
|
|
free(data);
|
2016-08-10 06:28:17 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int l_lovrGraphicsNewShader(lua_State* L) {
|
2016-11-14 22:42:40 +00:00
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
if (lua_isnoneornil(L, i + 1)) continue;
|
|
|
|
const char* source = luaL_checkstring(L, i + 1);
|
|
|
|
if (!lovrFilesystemIsFile(source)) continue;
|
|
|
|
int bytesRead;
|
|
|
|
char* contents = lovrFilesystemRead(source, &bytesRead);
|
|
|
|
if (bytesRead <= 0) {
|
|
|
|
return luaL_error(L, "Could not read shader from file '%s'", source);
|
|
|
|
}
|
|
|
|
lua_pushlstring(L, contents, bytesRead);
|
|
|
|
lua_replace(L, i + 1);
|
|
|
|
free(contents);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* vertexSource = lua_tostring(L, 1);
|
|
|
|
const char* fragmentSource = lua_tostring(L, 2);
|
2016-11-19 08:57:18 +00:00
|
|
|
luax_pushtype(L, Shader, lovrShaderCreate(vertexSource, fragmentSource));
|
2016-08-10 06:28:17 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2016-10-16 03:11:54 +00:00
|
|
|
|
|
|
|
int l_lovrGraphicsNewSkybox(lua_State* L) {
|
2016-11-05 22:57:10 +00:00
|
|
|
void* data[6];
|
|
|
|
int size[6];
|
2016-10-16 03:11:54 +00:00
|
|
|
|
2016-10-24 22:02:23 +00:00
|
|
|
if (lua_istable(L, 1)) {
|
|
|
|
if (lua_objlen(L, 1) != 6) {
|
|
|
|
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
lua_rawgeti(L, 1, i + 1);
|
|
|
|
|
|
|
|
if (!lua_isstring(L, -1)) {
|
|
|
|
return luaL_argerror(L, 1, "Expected 6 strings or a table containing 6 strings");
|
|
|
|
}
|
|
|
|
|
2016-11-05 22:57:10 +00:00
|
|
|
const char* filename = lua_tostring(L, -1);
|
|
|
|
data[i] = lovrFilesystemRead(filename, size + i);
|
2016-10-24 22:02:23 +00:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < 6; i++) {
|
2016-11-05 22:57:10 +00:00
|
|
|
const char* filename = luaL_checkstring(L, i + 1);
|
|
|
|
data[i] = lovrFilesystemRead(filename, size + i);
|
2016-10-24 22:02:23 +00:00
|
|
|
}
|
2016-10-16 03:11:54 +00:00
|
|
|
}
|
|
|
|
|
2016-11-19 08:57:18 +00:00
|
|
|
luax_pushtype(L, Skybox, lovrSkyboxCreate(data, size));
|
2016-11-05 22:57:10 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
|
|
free(data[i]);
|
|
|
|
}
|
|
|
|
|
2016-10-16 03:11:54 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2016-11-08 11:14:33 +00:00
|
|
|
|
|
|
|
int l_lovrGraphicsNewTexture(lua_State* L) {
|
2016-11-14 01:28:22 +00:00
|
|
|
Texture* texture;
|
|
|
|
|
2017-01-09 06:51:43 +00:00
|
|
|
if (lua_type(L, 1) == LUA_TSTRING) {
|
2017-01-30 03:03:50 +00:00
|
|
|
texture = luax_readtexture(L, 1);
|
2017-01-09 06:51:43 +00:00
|
|
|
} else {
|
|
|
|
int width = luaL_checknumber(L, 1);
|
|
|
|
int height = luaL_checknumber(L, 2);
|
2017-01-12 07:38:28 +00:00
|
|
|
TextureProjection* projection = luax_optenum(L, 3, "2d", &TextureProjections, "projection");
|
2017-01-15 01:38:25 +00:00
|
|
|
int msaa = luaL_optnumber(L, 4, 0);
|
2017-02-06 04:30:17 +00:00
|
|
|
TextureData* textureData = lovrTextureDataGetEmpty(width, height, FORMAT_RGBA);
|
2017-01-15 01:38:25 +00:00
|
|
|
texture = lovrTextureCreateWithFramebuffer(textureData, *projection, msaa);
|
2016-11-08 11:14:33 +00:00
|
|
|
}
|
|
|
|
|
2016-11-19 08:57:18 +00:00
|
|
|
luax_pushtype(L, Texture, texture);
|
2016-11-08 11:14:33 +00:00
|
|
|
return 1;
|
|
|
|
}
|