1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-07 06:43:34 +00:00
lovr/src/api/graphics.c

1209 lines
35 KiB
C
Raw Normal View History

2017-12-10 20:40:37 +00:00
#include "api.h"
2016-11-19 09:28:01 +00:00
#include "graphics/graphics.h"
2017-11-03 06:47:13 +00:00
#include "graphics/animator.h"
2017-12-07 07:50:52 +00:00
#include "graphics/canvas.h"
2017-10-21 21:05:58 +00:00
#include "graphics/material.h"
2017-08-09 05:34:23 +00:00
#include "graphics/mesh.h"
#include "graphics/model.h"
2018-02-11 23:22:04 +00:00
#include "data/modelData.h"
2018-01-22 16:28:33 +00:00
#include "data/rasterizer.h"
2018-02-11 23:22:04 +00:00
#include "data/textureData.h"
2018-02-11 01:27:29 +00:00
#include "data/vertexData.h"
2016-11-19 09:28:01 +00:00
#include "filesystem/filesystem.h"
2016-10-29 22:17:49 +00:00
#include <math.h>
2017-10-31 08:14:09 +00:00
#include <stdbool.h>
2016-08-10 06:28:17 +00:00
2017-11-22 19:32:30 +00:00
map_int_t ArcModes;
2018-01-26 02:31:56 +00:00
map_int_t AttributeTypes;
2017-03-12 11:03:36 +00:00
map_int_t BlendAlphaModes;
map_int_t BlendModes;
2017-03-11 11:08:07 +00:00
map_int_t CompareModes;
map_int_t DrawModes;
map_int_t FilterModes;
2017-03-16 03:12:56 +00:00
map_int_t HorizontalAligns;
2017-10-21 21:05:58 +00:00
map_int_t MaterialColors;
2018-02-12 03:16:40 +00:00
map_int_t MaterialScalars;
2017-10-21 21:05:58 +00:00
map_int_t MaterialTextures;
2017-08-11 05:23:19 +00:00
map_int_t MatrixTypes;
2017-03-12 11:03:36 +00:00
map_int_t MeshDrawModes;
map_int_t MeshUsages;
2017-12-19 03:48:28 +00:00
map_int_t StencilActions;
map_int_t TextureFormats;
map_int_t TextureTypes;
2017-03-16 03:12:56 +00:00
map_int_t VerticalAligns;
2017-08-02 07:54:33 +00:00
map_int_t Windings;
2017-03-11 11:08:07 +00:00
map_int_t WrapModes;
2017-08-11 05:23:19 +00:00
static int luax_optmatrixtype(lua_State* L, int index, MatrixType* type) {
if (lua_type(L, index) == LUA_TSTRING) {
*type = *(MatrixType*) luax_checkenum(L, index++, &MatrixTypes, "matrix type");
} else {
*type = MATRIX_MODEL;
}
return index;
}
2016-11-08 07:16:33 +00:00
static void luax_readvertices(lua_State* L, int index, vec_float_t* points) {
2017-10-31 08:14:09 +00:00
bool isTable = lua_istable(L, index);
2016-11-08 07:16:33 +00:00
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-12-19 03:48:28 +00:00
static void stencilCallback(void* userdata) {
lua_State* L = userdata;
luaL_checktype(L, -1, LUA_TFUNCTION);
lua_call(L, 0, 0);
}
2018-01-22 16:14:18 +00:00
static TextureData* luax_checktexturedata(lua_State* L, int index) {
void** type;
if ((type = luax_totype(L, index, TextureData)) != NULL) {
return *type;
} else {
Blob* blob = luax_readblob(L, index, "Texture");
TextureData* textureData = lovrTextureDataFromBlob(blob);
2018-02-26 08:59:03 +00:00
lovrRelease(blob);
2018-01-22 16:14:18 +00:00
return textureData;
}
}
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-11-03 06:47:13 +00:00
luax_registertype(L, "Animator", lovrAnimator);
2017-02-06 05:05:09 +00:00
luax_registertype(L, "Font", lovrFont);
2017-10-21 21:05:58 +00:00
luax_registertype(L, "Material", lovrMaterial);
2017-03-15 04:38:03 +00:00
luax_registertype(L, "Mesh", lovrMesh);
2017-01-21 03:46:45 +00:00
luax_registertype(L, "Model", lovrModel);
luax_registertype(L, "Shader", lovrShader);
luax_registertype(L, "Texture", lovrTexture);
2017-12-07 07:50:52 +00:00
luax_extendtype(L, "Texture", "Canvas", lovrTexture, lovrCanvas);
2017-11-22 19:32:30 +00:00
map_init(&ArcModes);
map_set(&ArcModes, "pie", ARC_MODE_PIE);
map_set(&ArcModes, "open", ARC_MODE_OPEN);
map_set(&ArcModes, "closed", ARC_MODE_CLOSED);
2018-01-26 02:31:56 +00:00
map_init(&AttributeTypes);
map_set(&AttributeTypes, "float", ATTR_FLOAT);
map_set(&AttributeTypes, "byte", ATTR_BYTE);
map_set(&AttributeTypes, "int", ATTR_INT);
2017-03-12 11:03:36 +00:00
map_init(&BlendAlphaModes);
map_set(&BlendAlphaModes, "alphamultiply", BLEND_ALPHA_MULTIPLY);
map_set(&BlendAlphaModes, "premultiplied", BLEND_PREMULTIPLIED);
2017-03-12 11:03:36 +00:00
map_init(&BlendModes);
map_set(&BlendModes, "alpha", BLEND_ALPHA);
map_set(&BlendModes, "add", BLEND_ADD);
map_set(&BlendModes, "subtract", BLEND_SUBTRACT);
map_set(&BlendModes, "multiply", BLEND_MULTIPLY);
map_set(&BlendModes, "lighten", BLEND_LIGHTEN);
map_set(&BlendModes, "darken", BLEND_DARKEN);
map_set(&BlendModes, "screen", BLEND_SCREEN);
map_set(&BlendModes, "replace", BLEND_REPLACE);
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);
2017-03-15 04:38:03 +00:00
map_init(&DrawModes);
map_set(&DrawModes, "fill", DRAW_MODE_FILL);
map_set(&DrawModes, "line", DRAW_MODE_LINE);
2016-11-08 22:44:22 +00:00
map_init(&FilterModes);
map_set(&FilterModes, "nearest", FILTER_NEAREST);
map_set(&FilterModes, "bilinear", FILTER_BILINEAR);
map_set(&FilterModes, "trilinear", FILTER_TRILINEAR);
map_set(&FilterModes, "anisotropic", FILTER_ANISOTROPIC);
2016-11-08 22:44:22 +00:00
2017-03-16 03:12:56 +00:00
map_init(&HorizontalAligns);
map_set(&HorizontalAligns, "left", ALIGN_LEFT);
map_set(&HorizontalAligns, "right", ALIGN_RIGHT);
map_set(&HorizontalAligns, "center", ALIGN_CENTER);
2017-10-21 21:05:58 +00:00
map_init(&MaterialColors);
map_set(&MaterialColors, "diffuse", COLOR_DIFFUSE);
2018-02-12 03:16:40 +00:00
map_set(&MaterialColors, "emissive", COLOR_EMISSIVE);
map_init(&MaterialScalars);
map_set(&MaterialScalars, "metalness", SCALAR_METALNESS);
map_set(&MaterialScalars, "roughness", SCALAR_ROUGHNESS);
2017-10-21 21:05:58 +00:00
map_init(&MaterialTextures);
map_set(&MaterialTextures, "diffuse", TEXTURE_DIFFUSE);
2018-02-12 03:16:40 +00:00
map_set(&MaterialTextures, "emissive", TEXTURE_EMISSIVE);
map_set(&MaterialTextures, "metalness", TEXTURE_METALNESS);
map_set(&MaterialTextures, "roughness", TEXTURE_ROUGHNESS);
map_set(&MaterialTextures, "occlusion", TEXTURE_OCCLUSION);
map_set(&MaterialTextures, "normal", TEXTURE_NORMAL);
2017-10-21 21:59:34 +00:00
map_set(&MaterialTextures, "environment", TEXTURE_ENVIRONMENT_MAP);
2017-10-21 21:05:58 +00:00
2017-08-11 05:23:19 +00:00
map_init(&MatrixTypes);
map_set(&MatrixTypes, "model", MATRIX_MODEL);
map_set(&MatrixTypes, "view", MATRIX_VIEW);
2017-03-12 11:03:36 +00:00
map_init(&MeshDrawModes);
map_set(&MeshDrawModes, "points", MESH_POINTS);
2017-11-26 03:49:22 +00:00
map_set(&MeshDrawModes, "lines", MESH_LINES);
map_set(&MeshDrawModes, "linestrip", MESH_LINE_STRIP);
2017-03-12 11:03:36 +00:00
map_set(&MeshDrawModes, "strip", MESH_TRIANGLE_STRIP);
map_set(&MeshDrawModes, "triangles", MESH_TRIANGLES);
map_set(&MeshDrawModes, "fan", MESH_TRIANGLE_FAN);
map_init(&MeshUsages);
map_set(&MeshUsages, "static", MESH_STATIC);
map_set(&MeshUsages, "dynamic", MESH_DYNAMIC);
map_set(&MeshUsages, "stream", MESH_STREAM);
2017-12-19 03:48:28 +00:00
map_init(&StencilActions);
map_set(&StencilActions, "replace", STENCIL_REPLACE);
map_set(&StencilActions, "increment", STENCIL_INCREMENT);
map_set(&StencilActions, "decrement", STENCIL_DECREMENT);
map_set(&StencilActions, "incrementwrap", STENCIL_INCREMENT_WRAP);
map_set(&StencilActions, "decrementwrap", STENCIL_DECREMENT_WRAP);
map_set(&StencilActions, "invert", STENCIL_INVERT);
map_init(&TextureFormats);
map_set(&TextureFormats, "rgb", FORMAT_RGB);
map_set(&TextureFormats, "rgba", FORMAT_RGBA);
map_set(&TextureFormats, "rgba16f", FORMAT_RGBA16F);
map_set(&TextureFormats, "rgba32f", FORMAT_RGBA32F);
map_set(&TextureFormats, "rg11b10f", FORMAT_RG11B10F);
map_set(&TextureFormats, "dxt1", FORMAT_DXT1);
map_set(&TextureFormats, "dxt3", FORMAT_DXT3);
map_set(&TextureFormats, "dxt5", FORMAT_DXT5);
map_init(&TextureTypes);
map_set(&TextureTypes, "2d", TEXTURE_2D);
map_set(&TextureTypes, "array", TEXTURE_ARRAY);
map_set(&TextureTypes, "cube", TEXTURE_CUBE);
2018-02-21 01:57:47 +00:00
map_set(&TextureTypes, "volume", TEXTURE_VOLUME);
2017-03-16 03:12:56 +00:00
map_init(&VerticalAligns);
map_set(&VerticalAligns, "top", ALIGN_TOP);
map_set(&VerticalAligns, "bottom", ALIGN_BOTTOM);
map_set(&VerticalAligns, "middle", ALIGN_MIDDLE);
2017-08-02 07:54:33 +00:00
map_init(&Windings);
map_set(&Windings, "clockwise", WINDING_CLOCKWISE);
map_set(&Windings, "counterclockwise", WINDING_COUNTERCLOCKWISE);
2016-11-08 22:44:22 +00:00
map_init(&WrapModes);
map_set(&WrapModes, "clamp", WRAP_CLAMP);
map_set(&WrapModes, "repeat", WRAP_REPEAT);
map_set(&WrapModes, "mirroredrepeat", WRAP_MIRRORED_REPEAT);
2016-08-10 06:28:17 +00:00
lovrGraphicsInit();
luax_pushconf(L);
2017-11-23 04:13:36 +00:00
// Set gamma correct
lua_getfield(L, -1, "gammacorrect");
bool gammaCorrect = lua_toboolean(L, -1);
lovrGraphicsSetGammaCorrect(gammaCorrect);
lua_pop(L, 1);
// Create window if needed
lua_getfield(L, -1, "window");
if (!lua_isnil(L, -1)) {
lua_getfield(L, -1, "width");
int width = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "height");
int height = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "fullscreen");
bool fullscreen = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "msaa");
int msaa = luaL_checkinteger(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "title");
const char* title = luaL_checkstring(L, -1);
lua_pop(L, 1);
lua_getfield(L, -1, "icon");
const char* icon = luaL_optstring(L, -1, NULL);
lua_pop(L, 1);
lovrGraphicsCreateWindow(width, height, fullscreen, msaa, title, icon);
}
2017-11-23 04:13:36 +00:00
lua_pop(L, 2);
2016-08-10 06:28:17 +00:00
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) {
int index = 1;
int top = lua_gettop(L);
bool clearColor = true;
bool clearDepth = true;
bool clearStencil = true;
Color color = lovrGraphicsGetBackgroundColor();
float depth = 1.0;
int stencil = 0;
if (top >= index) {
if (lua_type(L, index) == LUA_TNUMBER) {
color.r = luaL_checknumber(L, index++);
color.g = luaL_checknumber(L, index++);
color.b = luaL_checknumber(L, index++);
color.a = luaL_optnumber(L, index++, 1.);
} else {
clearColor = lua_toboolean(L, index++);
}
}
if (top >= index) {
if (lua_type(L, index) == LUA_TNUMBER) {
depth = luaL_checknumber(L, index++);
} else {
clearDepth = lua_toboolean(L, index++);
}
}
if (top >= index) {
if (lua_type(L, index) == LUA_TNUMBER) {
stencil = luaL_checkinteger(L, index++);
} else {
clearStencil = lua_toboolean(L, index++);
}
}
lovrGraphicsClear(clearColor, clearDepth, clearStencil, color, depth, stencil);
2016-08-10 06:28:17 +00:00
return 0;
}
int l_lovrGraphicsPresent(lua_State* L) {
lovrGraphicsPresent();
return 0;
}
2017-08-10 03:02:02 +00:00
int l_lovrGraphicsCreateWindow(lua_State* L) {
int width = luaL_optnumber(L, 1, 800);
int height = luaL_optnumber(L, 2, 600);
2017-10-31 08:14:09 +00:00
bool fullscreen = !lua_isnoneornil(L, 3) && lua_toboolean(L, 3);
2017-08-10 03:02:02 +00:00
int msaa = luaL_optnumber(L, 4, 0);
const char* title = luaL_optstring(L, 5, "LÖVR");
const char* icon = luaL_optstring(L, 6, NULL);
lovrGraphicsCreateWindow(width, height, fullscreen, msaa, title, icon);
return 0;
}
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;
}
2017-12-10 04:07:32 +00:00
int l_lovrGraphicsGetStats(lua_State* L) {
if (lua_gettop(L) > 0) {
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1);
} else {
lua_createtable(L, 0, 2);
}
GraphicsStats stats = lovrGraphicsGetStats();
lua_pushinteger(L, stats.drawCalls);
lua_setfield(L, 1, "drawcalls");
lua_pushinteger(L, stats.shaderSwitches);
lua_setfield(L, 1, "shaderswitches");
return 1;
}
2016-11-23 05:16:13 +00:00
// State
2016-09-28 04:37:46 +00:00
int l_lovrGraphicsGetBackgroundColor(lua_State* L) {
2017-08-02 08:25:56 +00:00
Color color = lovrGraphicsGetBackgroundColor();
lua_pushnumber(L, color.r);
lua_pushnumber(L, color.g);
lua_pushnumber(L, color.b);
lua_pushnumber(L, color.a);
2016-08-10 06:28:17 +00:00
return 4;
}
2016-09-28 04:37:46 +00:00
int l_lovrGraphicsSetBackgroundColor(lua_State* L) {
2017-08-02 08:25:56 +00:00
Color color;
color.r = luaL_checknumber(L, 1);
color.g = luaL_checknumber(L, 2);
color.b = luaL_checknumber(L, 3);
color.a = luaL_optnumber(L, 4, 1.);
2017-08-02 08:25:56 +00:00
lovrGraphicsSetBackgroundColor(color);
2016-08-10 06:28:17 +00:00
return 0;
}
2017-03-12 11:03:36 +00:00
int l_lovrGraphicsGetBlendMode(lua_State* L) {
BlendMode mode;
BlendAlphaMode alphaMode;
lovrGraphicsGetBlendMode(&mode, &alphaMode);
luax_pushenum(L, &BlendModes, mode);
luax_pushenum(L, &BlendAlphaModes, alphaMode);
return 2;
}
int l_lovrGraphicsSetBlendMode(lua_State* L) {
BlendMode mode = *(BlendMode*) luax_checkenum(L, 1, &BlendModes, "blend mode");
BlendAlphaMode alphaMode = *(BlendAlphaMode*) luax_optenum(L, 2, "alphamultiply", &BlendAlphaModes, "alpha blend mode");
lovrGraphicsSetBlendMode(mode, alphaMode);
return 0;
}
int l_lovrGraphicsGetCanvas(lua_State* L) {
Canvas* canvas[MAX_CANVASES];
int count;
lovrGraphicsGetCanvas(canvas, &count);
for (int i = 0; i < count; i++) {
luax_pushtype(L, Canvas, canvas[i]);
}
return count;
}
int l_lovrGraphicsSetCanvas(lua_State* L) {
Canvas* canvas[MAX_CANVASES];
int count = MIN(lua_gettop(L), MAX_CANVASES);
for (int i = 0; i < count; i++) {
canvas[i] = luax_checktype(L, i + 1, Canvas);
}
lovrGraphicsSetCanvas(canvas, count);
return 0;
}
2016-09-29 03:11:58 +00:00
int l_lovrGraphicsGetColor(lua_State* L) {
2017-08-02 08:25:56 +00:00
Color color = lovrGraphicsGetColor();
lua_pushnumber(L, color.r);
lua_pushnumber(L, color.g);
lua_pushnumber(L, color.b);
lua_pushnumber(L, color.a);
2016-09-29 03:11:58 +00:00
return 4;
}
int l_lovrGraphicsSetColor(lua_State* L) {
2017-10-21 20:10:07 +00:00
Color color = luax_checkcolor(L, 1);
2017-08-02 08:25:56 +00:00
lovrGraphicsSetColor(color);
2016-09-29 03:11:58 +00:00
return 0;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsIsCullingEnabled(lua_State* L) {
lua_pushboolean(L, lovrGraphicsIsCullingEnabled());
2016-09-14 00:02:23 +00:00
return 1;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsSetCullingEnabled(lua_State* L) {
lovrGraphicsSetCullingEnabled(lua_toboolean(L, 1));
2016-08-10 06:28:17 +00:00
return 0;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsGetDefaultFilter(lua_State* L) {
TextureFilter filter = lovrGraphicsGetDefaultFilter();
luax_pushenum(L, &FilterModes, filter.mode);
if (filter.mode == FILTER_ANISOTROPIC) {
lua_pushnumber(L, filter.anisotropy);
return 2;
}
2017-02-03 23:16:30 +00:00
return 1;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsSetDefaultFilter(lua_State* L) {
FilterMode mode = *(FilterMode*) luax_checkenum(L, 1, &FilterModes, "filter mode");
float anisotropy = luaL_optnumber(L, 2, 1.);
TextureFilter filter = { .mode = mode, .anisotropy = anisotropy };
lovrGraphicsSetDefaultFilter(filter);
2017-02-03 23:16:30 +00:00
return 0;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsGetDepthTest(lua_State* L) {
2018-02-09 05:50:47 +00:00
CompareMode mode;
bool write;
lovrGraphicsGetDepthTest(&mode, &write);
luax_pushenum(L, &CompareModes, mode);
lua_pushboolean(L, write);
return 2;
2017-08-02 07:54:33 +00:00
}
int l_lovrGraphicsSetDepthTest(lua_State* L) {
2018-02-09 05:50:47 +00:00
if (lua_isnoneornil(L, 1) && lua_isnoneornil(L, 2)) {
lovrGraphicsSetDepthTest(COMPARE_NONE, false);
2017-08-02 07:54:33 +00:00
} else {
2018-02-09 05:50:47 +00:00
CompareMode mode = *(CompareMode*) luax_checkenum(L, 1, &CompareModes, "compare mode");
bool write = lua_isnoneornil(L, 2) ? true : lua_toboolean(L, 2);
lovrGraphicsSetDepthTest(mode, write);
2017-08-02 07:54:33 +00:00
}
return 0;
}
2017-08-10 03:02:02 +00:00
int l_lovrGraphicsGetFont(lua_State* L) {
Font* font = lovrGraphicsGetFont();
luax_pushtype(L, Font, font);
return 1;
}
int l_lovrGraphicsSetFont(lua_State* L) {
Font* font = lua_isnoneornil(L, 1) ? NULL : luax_checktype(L, 1, Font);
lovrGraphicsSetFont(font);
return 0;
}
int l_lovrGraphicsIsGammaCorrect(lua_State* L) {
bool gammaCorrect = lovrGraphicsIsGammaCorrect();
lua_pushboolean(L, gammaCorrect);
return 1;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsGetSystemLimits(lua_State* L) {
GraphicsLimits limits = lovrGraphicsGetLimits();
lua_newtable(L);
lua_pushnumber(L, limits.pointSizes[1]);
lua_setfield(L, -2, "pointsize");
lua_pushinteger(L, limits.textureSize);
lua_setfield(L, -2, "texturesize");
lua_pushinteger(L, limits.textureMSAA);
lua_setfield(L, -2, "texturemsaa");
lua_pushinteger(L, limits.textureAnisotropy);
lua_setfield(L, -2, "anisotropy");
return 1;
}
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;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsGetShader(lua_State* L) {
Shader* shader = lovrGraphicsGetShader();
luax_pushtype(L, Shader, shader);
2016-11-23 05:07:33 +00:00
return 1;
}
2017-08-02 07:54:33 +00:00
int l_lovrGraphicsSetShader(lua_State* L) {
Shader* shader = lua_isnoneornil(L, 1) ? NULL : luax_checktype(L, 1, Shader);
lovrGraphicsSetShader(shader);
2016-11-23 05:07:33 +00:00
return 0;
}
int l_lovrGraphicsGetStencilTest(lua_State* L) {
CompareMode mode;
int value;
lovrGraphicsGetStencilTest(&mode, &value);
if (mode == COMPARE_NONE) {
lua_pushnil(L);
return 1;
}
luax_pushenum(L, &CompareModes, mode);
lua_pushinteger(L, value);
return 2;
}
int l_lovrGraphicsSetStencilTest(lua_State* L) {
if (lua_isnoneornil(L, 1)) {
lovrGraphicsSetStencilTest(COMPARE_NONE, 0);
} else {
CompareMode mode = *(CompareMode*) luax_checkenum(L, 1, &CompareModes, "compare mode");
int value = luaL_checkinteger(L, 2);
lovrGraphicsSetStencilTest(mode, value);
}
return 0;
}
2017-08-10 03:02:02 +00:00
int l_lovrGraphicsGetWinding(lua_State* L) {
luax_pushenum(L, &Windings, lovrGraphicsGetWinding());
return 1;
}
2017-08-10 03:02:02 +00:00
int l_lovrGraphicsSetWinding(lua_State* L) {
Winding* winding = (Winding*) luax_checkenum(L, 1, &Windings, "winding");
lovrGraphicsSetWinding(*winding);
return 0;
}
2017-08-10 03:02:02 +00:00
int l_lovrGraphicsIsWireframe(lua_State* L) {
lua_pushboolean(L, lovrGraphicsIsWireframe());
2016-11-23 05:16:13 +00:00
return 1;
}
2017-08-10 03:02:02 +00:00
int l_lovrGraphicsSetWireframe(lua_State* L) {
lovrGraphicsSetWireframe(lua_toboolean(L, 1));
return 0;
2016-11-23 05:16:13 +00:00
}
// Transforms
2016-09-21 07:55:53 +00:00
int l_lovrGraphicsPush(lua_State* L) {
lovrGraphicsPush();
2016-09-21 07:55:53 +00:00
return 0;
}
int l_lovrGraphicsPop(lua_State* L) {
lovrGraphicsPop();
2016-09-21 07:55:53 +00:00
return 0;
}
2016-09-21 22:26:05 +00:00
int l_lovrGraphicsOrigin(lua_State* L) {
lovrGraphicsOrigin();
return 0;
}
int l_lovrGraphicsTranslate(lua_State* L) {
2017-08-11 05:23:19 +00:00
MatrixType type;
int i = luax_optmatrixtype(L, 1, &type);
float x = luaL_checknumber(L, i++);
float y = luaL_checknumber(L, i++);
float z = luaL_checknumber(L, i++);
lovrGraphicsTranslate(type, x, y, z);
return 0;
}
int l_lovrGraphicsRotate(lua_State* L) {
2017-08-11 05:23:19 +00:00
MatrixType type;
int i = luax_optmatrixtype(L, 1, &type);
float angle = luaL_checknumber(L, i++);
float axisX = luaL_optnumber(L, i++, 0);
float axisY = luaL_optnumber(L, i++, 1);
float axisZ = luaL_optnumber(L, i++, 0);
lovrGraphicsRotate(type, angle, axisX, axisY, axisZ);
return 0;
}
int l_lovrGraphicsScale(lua_State* L) {
2017-08-11 05:23:19 +00:00
MatrixType type;
int i = luax_optmatrixtype(L, 1, &type);
float x = luaL_checknumber(L, i++);
float y = luaL_optnumber(L, i++, x);
float z = luaL_optnumber(L, i++, x);
lovrGraphicsScale(type, x, y, z);
return 0;
}
2017-01-20 03:13:37 +00:00
int l_lovrGraphicsTransform(lua_State* L) {
2017-08-11 05:23:19 +00:00
MatrixType type;
int i = luax_optmatrixtype(L, 1, &type);
2017-01-20 03:13:37 +00:00
float transform[16];
luax_readtransform(L, i++, transform, 3);
2017-08-11 05:23:19 +00:00
lovrGraphicsMatrixTransform(type, transform);
2017-01-20 03:13:37 +00:00
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 = DRAW_MODE_FILL;
Material* material = NULL;
if (lua_isuserdata(L, 1)) {
material = luax_checktype(L, 1, Material);
} else {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
}
2016-11-23 04:43:22 +00:00
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, material, points.data);
2016-11-23 04:43:22 +00:00
vec_deinit(&points);
return 0;
}
2016-10-04 03:56:45 +00:00
int l_lovrGraphicsPlane(lua_State* L) {
if (lua_isuserdata(L, 1) && lua_gettop(L) == 1) {
Texture* texture = luax_checktypeof(L, 1, Texture);
2017-10-21 20:50:43 +00:00
lovrGraphicsPlaneFullscreen(texture);
return 0;
2017-01-13 09:59:00 +00:00
}
2017-10-21 20:50:43 +00:00
DrawMode drawMode = DRAW_MODE_FILL;
Material* material = NULL;
if (lua_isuserdata(L, 1)) {
material = luax_checktype(L, 1, Material);
} else {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
}
float transform[16];
luax_readtransform(L, 2, transform, 2);
lovrGraphicsPlane(drawMode, material, transform);
2016-10-04 03:56:45 +00:00
return 0;
}
static int luax_rectangularprism(lua_State* L, int scaleComponents) {
DrawMode drawMode = DRAW_MODE_FILL;
Material* material = NULL;
if (lua_isuserdata(L, 1)) {
material = luax_checktype(L, 1, Material);
} else {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
}
float transform[16];
luax_readtransform(L, 2, transform, scaleComponents);
lovrGraphicsBox(drawMode, material, transform);
2016-09-30 06:18:51 +00:00
return 0;
}
int l_lovrGraphicsCube(lua_State* L) {
return luax_rectangularprism(L, 1);
}
int l_lovrGraphicsBox(lua_State* L) {
return luax_rectangularprism(L, 3);
}
2017-11-22 19:32:30 +00:00
int l_lovrGraphicsArc(lua_State* L) {
DrawMode drawMode = DRAW_MODE_FILL;
Material* material = NULL;
if (lua_isuserdata(L, 1)) {
material = luax_checktype(L, 1, Material);
} else {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
}
2017-11-22 19:32:30 +00:00
ArcMode arcMode = ARC_MODE_PIE;
int index = 2;
if (lua_type(L, index) == LUA_TSTRING) {
2017-11-22 19:32:30 +00:00
arcMode = *(ArcMode*) luax_checkenum(L, index++, &ArcModes, "arc mode");
}
float transform[16];
index = luax_readtransform(L, index, transform, 1);
2017-11-22 19:32:30 +00:00
float theta1 = luaL_optnumber(L, index++, 0);
float theta2 = luaL_optnumber(L, index++, 2 * M_PI);
int segments = luaL_optinteger(L, index, 32) * fabsf(theta2 - theta1) * 2 * M_PI + .5f;
lovrGraphicsArc(drawMode, arcMode, material, transform, theta1, theta2, segments);
2017-11-22 19:32:30 +00:00
return 0;
}
2017-11-22 04:53:34 +00:00
int l_lovrGraphicsCircle(lua_State* L) {
DrawMode drawMode = DRAW_MODE_FILL;
Material* material = NULL;
if (lua_isuserdata(L, 1)) {
material = luax_checktype(L, 1, Material);
} else {
drawMode = *(DrawMode*) luax_checkenum(L, 1, &DrawModes, "draw mode");
}
2017-11-22 04:53:34 +00:00
float transform[16];
int index = luax_readtransform(L, 2, transform, 1);
2017-11-22 04:53:34 +00:00
int segments = luaL_optnumber(L, index, 32);
lovrGraphicsCircle(drawMode, material, transform, segments);
2017-11-22 04:53:34 +00:00
return 0;
}
2017-06-21 03:54:22 +00:00
int l_lovrGraphicsCylinder(lua_State* L) {
int index = 1;
Material* material = lua_isuserdata(L, index) ? luax_checktype(L, index++, Material) : NULL;
float x1 = luaL_checknumber(L, index++);
float y1 = luaL_checknumber(L, index++);
float z1 = luaL_checknumber(L, index++);
float x2 = luaL_checknumber(L, index++);
float y2 = luaL_checknumber(L, index++);
float z2 = luaL_checknumber(L, index++);
float r1 = luaL_optnumber(L, index++, 1);
float r2 = luaL_optnumber(L, index++, 1);
bool capped = lua_isnoneornil(L, index) ? true : lua_toboolean(L, index++);
int segments = luaL_optnumber(L, index, floorf(16 + 16 * MAX(r1, r2)));
lovrGraphicsCylinder(material, x1, y1, z1, x2, y2, z2, r1, r2, capped, segments);
2017-06-21 03:54:22 +00:00
return 0;
}
2017-06-22 06:10:45 +00:00
int l_lovrGraphicsSphere(lua_State* L) {
float transform[16];
int index = 1;
Material* material = lua_isuserdata(L, index) ? luax_checktype(L, index++, Material) : NULL;
2017-06-22 06:10:45 +00:00
index = luax_readtransform(L, index, transform, 1);
int segments = luaL_optnumber(L, index, 30);
lovrGraphicsSphere(material, transform, segments);
2017-10-15 23:56:00 +00:00
return 0;
}
int l_lovrGraphicsSkybox(lua_State* L) {
Texture* texture = luax_checktypeof(L, 1, Texture);
2017-10-15 23:56:00 +00:00
float angle = luaL_optnumber(L, 2, 0);
float ax = luaL_optnumber(L, 3, 0);
float ay = luaL_optnumber(L, 4, 1);
float az = luaL_optnumber(L, 5, 0);
lovrGraphicsSkybox(texture, angle, ax, ay, az);
2017-06-22 06:10:45 +00:00
return 0;
}
2017-06-22 02:44:02 +00:00
int l_lovrGraphicsPrint(lua_State* L) {
const char* str = luaL_checkstring(L, 1);
float transform[16];
int index = luax_readtransform(L, 2, transform, 1);
float wrap = luaL_optnumber(L, index++, 0);
HorizontalAlign halign = *(HorizontalAlign*) luax_optenum(L, index++, "center", &HorizontalAligns, "alignment");
VerticalAlign valign = *(VerticalAlign*) luax_optenum(L, index++, "middle", &VerticalAligns, "alignment");
lovrGraphicsPrint(str, transform, wrap, halign, valign);
return 0;
}
2017-12-19 03:48:28 +00:00
int l_lovrGraphicsStencil(lua_State* L) {
luaL_checktype(L, 1, LUA_TFUNCTION);
StencilAction action = *(StencilAction*) luax_optenum(L, 2, "replace", &StencilActions, "stencil action");
int replaceValue = luaL_optinteger(L, 3, 1);
bool keepValues = lua_toboolean(L, 4);
if (!keepValues) {
int clearTo = lua_isnumber(L, 4) ? lua_tonumber(L, 4) : 0;
lovrGraphicsClear(false, false, true, (Color) { 0, 0, 0, 0 }, 0, clearTo);
2017-12-19 03:48:28 +00:00
}
lua_settop(L, 1);
lovrGraphicsStencil(action, replaceValue, stencilCallback, L);
return 0;
}
2016-11-23 05:16:13 +00:00
// Types
2017-11-03 06:47:13 +00:00
int l_lovrGraphicsNewAnimator(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
2018-01-30 04:30:13 +00:00
Animator* animator = lovrAnimatorCreate(model->modelData);
2017-11-03 06:47:13 +00:00
luax_pushtype(L, Animator, animator);
return 1;
}
2017-12-07 07:50:52 +00:00
int l_lovrGraphicsNewCanvas(lua_State* L) {
int width = luaL_checkinteger(L, 1);
int height = luaL_checkinteger(L, 2);
luaL_argcheck(L, width > 0, 1, "width must be positive");
luaL_argcheck(L, height > 0, 2, "height must be positive");
TextureFormat format = FORMAT_RGBA;
int msaa = 0;
bool depth = true;
bool stencil = false;
if (lua_istable(L, 3)) {
lua_getfield(L, 3, "format");
format = *(TextureFormat*) luax_optenum(L, -1, "rgba", &TextureFormats, "canvas format");
lua_pop(L, 1);
lua_getfield(L, 3, "msaa");
msaa = luaL_optinteger(L, -1, 0);
lua_pop(L, 1);
lua_getfield(L, 3, "depth");
depth = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 3, "stencil");
stencil = lua_toboolean(L, -1);
lua_pop(L, 1);
}
if (!lovrCanvasSupportsFormat(format)) {
return luaL_error(L, "Unsupported texture format for canvas");
2017-12-07 07:50:52 +00:00
}
Canvas* canvas = lovrCanvasCreate(width, height, format, msaa, depth, stencil);
2017-12-07 07:50:52 +00:00
luax_pushtype(L, Canvas, canvas);
return 1;
}
2017-03-11 22:13:49 +00:00
int l_lovrGraphicsNewFont(lua_State* L) {
2018-01-22 16:46:09 +00:00
Rasterizer* rasterizer;
void** type;
if ((type = luax_totype(L, 1, Rasterizer)) != NULL) {
rasterizer = *type;
2017-03-11 22:13:49 +00:00
} else {
2018-01-22 16:46:09 +00:00
Blob* blob = NULL;
float size;
if (lua_type(L, 1) == LUA_TNUMBER || lua_isnoneornil(L, 1)) {
size = luaL_optnumber(L, 1, 32);
} else {
blob = luax_readblob(L, 1, "Font");
size = luaL_optnumber(L, 2, 32);
}
rasterizer = lovrRasterizerCreate(blob, size);
2018-02-26 08:59:03 +00:00
lovrRelease(blob);
2017-03-11 22:13:49 +00:00
}
2018-01-22 16:28:33 +00:00
Font* font = lovrFontCreate(rasterizer);
2017-03-11 22:13:49 +00:00
luax_pushtype(L, Font, font);
2018-02-26 08:59:03 +00:00
lovrRelease(font);
2017-03-11 22:13:49 +00:00
return 1;
}
2017-10-21 21:05:58 +00:00
int l_lovrGraphicsNewMaterial(lua_State* L) {
2018-01-30 05:44:32 +00:00
Material* material = lovrMaterialCreate(false);
int index = 1;
if (lua_type(L, index) == LUA_TSTRING) {
Blob* blob = luax_readblob(L, index++, "Texture");
TextureData* textureData = lovrTextureDataFromBlob(blob);
2018-02-26 08:59:03 +00:00
lovrRelease(blob);
Texture* texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true, true);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, texture);
2018-02-26 08:59:03 +00:00
lovrRelease(texture);
} else if (lua_isuserdata(L, index)) {
Texture* texture = luax_checktypeof(L, index, Texture);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, texture);
index++;
}
if (lua_isnumber(L, index)) {
Color color = luax_checkcolor(L, index);
lovrMaterialSetColor(material, COLOR_DIFFUSE, color);
}
2017-10-21 21:05:58 +00:00
luax_pushtype(L, Material, material);
return 1;
}
2017-03-11 22:13:49 +00:00
int l_lovrGraphicsNewMesh(lua_State* L) {
uint32_t count;
int dataIndex = 0;
int drawModeIndex = 2;
VertexData* vertexData = NULL;
bool hasFormat = false;
2018-01-26 02:31:56 +00:00
VertexFormat format;
2018-01-27 02:58:36 +00:00
vertexFormatInit(&format);
if (lua_isnumber(L, 1)) {
count = lua_tointeger(L, 1);
} else if (lua_istable(L, 1)) {
if (lua_isnumber(L, 2)) {
2016-11-13 10:42:05 +00:00
drawModeIndex++;
hasFormat = luax_checkvertexformat(L, 1, &format);
count = lua_tointeger(L, 2);
dataIndex = 0;
} else if (lua_istable(L, 2)) {
2016-11-13 10:42:05 +00:00
drawModeIndex++;
hasFormat = luax_checkvertexformat(L, 1, &format);
count = lua_objlen(L, 2);
dataIndex = 2;
} else {
count = lua_objlen(L, 1);
dataIndex = 1;
}
} else if (lua_isuserdata(L, 1)) {
vertexData = luax_checktype(L, 1, VertexData);
format = vertexData->format;
count = vertexData->count;
hasFormat = true;
} else {
luaL_argerror(L, 1, "table or number expected");
2016-11-08 22:15:37 +00:00
return 0;
}
2018-03-21 21:48:46 +00:00
if (!hasFormat) {
vertexFormatAppend(&format, "lovrPosition", ATTR_FLOAT, 3);
vertexFormatAppend(&format, "lovrNormal", ATTR_FLOAT, 3);
vertexFormatAppend(&format, "lovrTexCoord", ATTR_FLOAT, 2);
}
2017-03-11 22:13:49 +00:00
MeshDrawMode* drawMode = (MeshDrawMode*) luax_optenum(L, drawModeIndex, "fan", &MeshDrawModes, "mesh draw mode");
MeshUsage* usage = (MeshUsage*) luax_optenum(L, drawModeIndex + 1, "dynamic", &MeshUsages, "mesh usage");
2018-03-21 21:48:46 +00:00
Mesh* mesh = lovrMeshCreate(count, format, *drawMode, *usage);
if (dataIndex) {
uint32_t dataCount = lua_objlen(L, dataIndex);
2018-01-27 02:58:36 +00:00
format = *lovrMeshGetVertexFormat(mesh);
2018-03-21 21:48:46 +00:00
VertexPointer vertices = lovrMeshMapVertices(mesh, 0, dataCount, false, true);
2017-03-12 01:27:18 +00:00
for (uint32_t i = 0; i < dataCount; i++) {
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;
2018-01-27 02:58:36 +00:00
for (int j = 0; j < format.count; j++) {
Attribute attribute = format.attributes[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) {
2018-01-27 20:51:41 +00:00
case ATTR_FLOAT: *vertices.floats++ = luaL_optnumber(L, -1, 0.f); break;
case ATTR_BYTE: *vertices.bytes++ = luaL_optint(L, -1, 255); break;
case ATTR_INT: *vertices.ints++ = luaL_optint(L, -1, 0); break;
}
2016-11-21 01:33:19 +00:00
lua_pop(L, 1);
}
}
lua_pop(L, 1);
}
2018-03-21 21:48:46 +00:00
} else if (vertexData) {
VertexPointer vertices = lovrMeshMapVertices(mesh, 0, count, false, true);
memcpy(vertices.raw, vertexData->blob.data, vertexData->count * vertexData->format.stride);
}
2017-03-11 22:13:49 +00:00
luax_pushtype(L, Mesh, mesh);
2018-02-26 08:59:03 +00:00
lovrRelease(mesh);
2017-02-03 23:16:30 +00:00
return 1;
}
2016-08-10 06:28:17 +00:00
int l_lovrGraphicsNewModel(lua_State* L) {
2018-01-23 02:24:39 +00:00
ModelData* modelData;
void** type;
if ((type = luax_totype(L, 1, ModelData)) != NULL) {
modelData = *type;
} else {
Blob* blob = luax_readblob(L, 1, "Model");
modelData = lovrModelDataCreate(blob);
2018-02-26 08:59:03 +00:00
lovrRelease(blob);
2018-01-23 02:24:39 +00:00
}
Model* model = lovrModelCreate(modelData);
if (lua_gettop(L) >= 2) {
if (lua_type(L, 2) == LUA_TSTRING) {
Blob* blob = luax_readblob(L, 2, "Texture");
TextureData* textureData = lovrTextureDataFromBlob(blob);
Texture* texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true, true);
2018-01-30 05:44:32 +00:00
Material* material = lovrMaterialCreate(false);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, texture);
lovrModelSetMaterial(model, material);
2018-02-26 08:59:03 +00:00
lovrRelease(blob);
lovrRelease(texture);
lovrRelease(material);
} else {
lovrModelSetMaterial(model, luax_checktype(L, 2, Material));
}
}
luax_pushtype(L, Model, model);
2018-02-26 08:59:03 +00:00
lovrRelease(model);
2016-08-10 06:28:17 +00:00
return 1;
}
int l_lovrGraphicsNewShader(lua_State* L) {
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;
2017-03-11 09:37:00 +00:00
size_t 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);
2017-08-09 07:56:13 +00:00
Shader* shader = lovrShaderCreate(vertexSource, fragmentSource);
2017-02-18 22:44:52 +00:00
luax_pushtype(L, Shader, shader);
2018-02-26 08:59:03 +00:00
lovrRelease(shader);
2016-08-10 06:28:17 +00:00
return 1;
}
2016-10-16 03:11:54 +00:00
2016-11-08 11:14:33 +00:00
int l_lovrGraphicsNewTexture(lua_State* L) {
2017-12-07 07:50:52 +00:00
bool isTable = lua_istable(L, 1);
2017-10-15 23:56:00 +00:00
if (!isTable) {
lua_newtable(L);
lua_pushvalue(L, 1);
lua_rawseti(L, -2, 1);
lua_replace(L, 1);
2017-12-07 07:50:52 +00:00
}
int sliceCount = lua_objlen(L, 1);
TextureType type = isTable ? (sliceCount > 0 ? TEXTURE_ARRAY : TEXTURE_CUBE) : TEXTURE_2D;
bool hasFlags = lua_istable(L, 2);
2017-12-07 07:50:52 +00:00
bool srgb = true;
bool mipmaps = true;
if (hasFlags) {
lua_getfield(L, 2, "linear");
2017-12-07 07:50:52 +00:00
srgb = !lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "mipmaps");
mipmaps = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 2, "type");
if (!lua_isnil(L, -1)) {
type = *(TextureType*) luax_checkenum(L, -1, &TextureTypes, "texture type");
}
lua_pop(L, 1);
}
if (type == TEXTURE_CUBE && sliceCount == 0) {
sliceCount = 6;
const char* faces[6] = { "right", "left", "top", "bottom", "back", "front" };
for (int i = 0; i < 6; i++) {
lua_pushstring(L, faces[i]);
lua_rawget(L, 1);
lua_rawseti(L, 1, i + 1);
}
}
Texture* texture = lovrTextureCreate(type, NULL, sliceCount, srgb, mipmaps);
for (int i = 0; i < sliceCount; i++) {
lua_rawgeti(L, 1, i + 1);
TextureData* textureData = luax_checktexturedata(L, -1);
lovrTextureReplacePixels(texture, textureData, i);
lua_pop(L, 1);
2017-12-07 07:50:52 +00:00
}
2017-10-15 23:56:00 +00:00
2016-11-19 08:57:18 +00:00
luax_pushtype(L, Texture, texture);
2018-02-26 08:59:03 +00:00
lovrRelease(texture);
2016-11-08 11:14:33 +00:00
return 1;
}
2017-03-11 11:08:07 +00:00
const luaL_Reg lovrGraphics[] = {
{ "reset", l_lovrGraphicsReset },
{ "clear", l_lovrGraphicsClear },
{ "present", l_lovrGraphicsPresent },
2017-08-10 03:02:02 +00:00
{ "createWindow", l_lovrGraphicsCreateWindow },
{ "getWidth", l_lovrGraphicsGetWidth },
{ "getHeight", l_lovrGraphicsGetHeight },
{ "getDimensions", l_lovrGraphicsGetDimensions },
2017-12-10 04:07:32 +00:00
{ "getStats", l_lovrGraphicsGetStats },
2017-03-11 11:08:07 +00:00
{ "getBackgroundColor", l_lovrGraphicsGetBackgroundColor },
{ "setBackgroundColor", l_lovrGraphicsSetBackgroundColor },
2017-03-12 11:03:36 +00:00
{ "getBlendMode", l_lovrGraphicsGetBlendMode },
{ "setBlendMode", l_lovrGraphicsSetBlendMode },
{ "getCanvas", l_lovrGraphicsGetCanvas },
{ "setCanvas", l_lovrGraphicsSetCanvas },
2017-03-11 11:08:07 +00:00
{ "getColor", l_lovrGraphicsGetColor },
{ "setColor", l_lovrGraphicsSetColor },
{ "isCullingEnabled", l_lovrGraphicsIsCullingEnabled },
{ "setCullingEnabled", l_lovrGraphicsSetCullingEnabled },
{ "getDefaultFilter", l_lovrGraphicsGetDefaultFilter },
{ "setDefaultFilter", l_lovrGraphicsSetDefaultFilter },
2017-08-28 05:59:51 +00:00
{ "getDepthTest", l_lovrGraphicsGetDepthTest },
{ "setDepthTest", l_lovrGraphicsSetDepthTest },
2017-08-10 03:02:02 +00:00
{ "getFont", l_lovrGraphicsGetFont },
{ "setFont", l_lovrGraphicsSetFont },
{ "isGammaCorrect", l_lovrGraphicsIsGammaCorrect },
2017-08-02 07:54:33 +00:00
{ "getSystemLimits", l_lovrGraphicsGetSystemLimits },
{ "getLineWidth", l_lovrGraphicsGetLineWidth },
{ "setLineWidth", l_lovrGraphicsSetLineWidth },
{ "getPointSize", l_lovrGraphicsGetPointSize },
{ "setPointSize", l_lovrGraphicsSetPointSize },
2017-08-10 03:02:02 +00:00
{ "getShader", l_lovrGraphicsGetShader },
{ "setShader", l_lovrGraphicsSetShader },
{ "getStencilTest", l_lovrGraphicsGetStencilTest },
{ "setStencilTest", l_lovrGraphicsSetStencilTest },
2017-08-02 07:54:33 +00:00
{ "getWinding", l_lovrGraphicsGetWinding },
{ "setWinding", l_lovrGraphicsSetWinding },
{ "isWireframe", l_lovrGraphicsIsWireframe },
{ "setWireframe", l_lovrGraphicsSetWireframe },
2017-03-11 11:08:07 +00:00
{ "push", l_lovrGraphicsPush },
{ "pop", l_lovrGraphicsPop },
{ "origin", l_lovrGraphicsOrigin },
{ "translate", l_lovrGraphicsTranslate },
{ "rotate", l_lovrGraphicsRotate },
{ "scale", l_lovrGraphicsScale },
{ "transform", l_lovrGraphicsTransform },
{ "points", l_lovrGraphicsPoints },
{ "line", l_lovrGraphicsLine },
{ "triangle", l_lovrGraphicsTriangle },
{ "plane", l_lovrGraphicsPlane },
{ "cube", l_lovrGraphicsCube },
{ "box", l_lovrGraphicsBox },
2017-11-22 19:32:30 +00:00
{ "arc", l_lovrGraphicsArc },
2017-11-22 04:53:34 +00:00
{ "circle", l_lovrGraphicsCircle },
2017-06-21 03:54:22 +00:00
{ "cylinder", l_lovrGraphicsCylinder },
2017-06-22 06:10:45 +00:00
{ "sphere", l_lovrGraphicsSphere },
2017-10-15 23:56:00 +00:00
{ "skybox", l_lovrGraphicsSkybox },
2017-06-22 02:44:02 +00:00
{ "print", l_lovrGraphicsPrint },
2017-12-19 03:48:28 +00:00
{ "stencil", l_lovrGraphicsStencil },
2017-11-03 06:47:13 +00:00
{ "newAnimator", l_lovrGraphicsNewAnimator },
2017-12-07 07:50:52 +00:00
{ "newCanvas", l_lovrGraphicsNewCanvas },
2017-03-11 11:08:07 +00:00
{ "newFont", l_lovrGraphicsNewFont },
2017-10-21 21:05:58 +00:00
{ "newMaterial", l_lovrGraphicsNewMaterial },
2017-03-11 22:13:49 +00:00
{ "newMesh", l_lovrGraphicsNewMesh },
2017-03-11 11:08:07 +00:00
{ "newModel", l_lovrGraphicsNewModel },
{ "newShader", l_lovrGraphicsNewShader },
{ "newTexture", l_lovrGraphicsNewTexture },
{ NULL, NULL }
};