123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 |
- #include <stdlib.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include <getopt.h>
- #include <gtk/gtk.h>
- #include "lua.h"
- #include "lualib.h"
- #include "lauxlib.h"
- #include <glplatform/glplatform-glcore.h>
- #include <glplatform/math3d.h>
- #include <glplatform/glplatform.h>
- #include "glsl_parser.h"
- #include "glsl_ast.h"
- #include "mesh.h"
- #include "geometry.h"
- #include "program.h"
- #include "texture.h"
- extern char *metalval;
- #include <gdk-pixbuf/gdk-pixbuf.h>
- #include <glib.h>
- #include <glib-unix.h>
- #define MAX_TEXTURE_UNITS 8
- #define USE_SLERP 1
- #define NEW_STRUCT(TYPE) ((struct TYPE *)malloc(sizeof(struct TYPE), sizeof(intptr_t)))
- static int set_b2l_file(lua_State *L);
- static int need_redraw(lua_State *L);
- static int get_shader_uniforms(lua_State *L);
- static int filter_shader_text(lua_State *L);
- static int make_path_relative(lua_State *L);
- static int directory_name(lua_State *L);
- static int create_glwin(lua_State *L);
- luaL_Reg lua_b2l_material_editor_capi[] = {
- { "directory_name", directory_name },
- { "make_path_relative", make_path_relative },
- { "set_b2l_file", set_b2l_file},
- { "need_redraw", need_redraw},
- { "get_shader_uniforms", get_shader_uniforms},
- { "filter_shader_text", filter_shader_text},
- { "create_glwin", create_glwin},
- { NULL, NULL }
- };
- static glplatform_gl_context_t g_ctx;
- static struct glplatform_win *g_win;
- static lua_State *g_L;
- static bool g_need_redraw = true;
- static GSource *g_src;
- static int g_dx[3];
- static int g_dy[3];
- static float g_log_zoom = 0.3;
- static bool g_mouse_down[3] = {false, false, false};
- static void on_expose(struct glplatform_win *win);
- static void on_destroy(struct glplatform_win *win);
- static void on_mouse_button_up(struct glplatform_win *, int, int, int);
- static void on_mouse_button_down(struct glplatform_win *, int, int, int);
- static void on_mouse_move(struct glplatform_win *, int, int);
- static void on_resize(struct glplatform_win *);
- static void on_mouse_wheel(struct glplatform_win *, int, int, int);
- static void redraw(struct glplatform_win *win);
- static struct math3d_quaternion q_cur = {0,0,0,1};
- static struct math3d_quaternion q_delta = {0,0,0,1};
- static struct math3d_vec3 g_offset = {{0,0,0}};
- static struct math3d_vec3 g_offset_next = {{0,0,0}};
- static void on_mouse_button_up(struct glplatform_win *win, int button, int x, int y)
- {
- if (g_mouse_down[0] && button == 1) {
- struct math3d_quaternion next;
- math3d_quaternion_mul(&q_delta, &q_cur, &next);
- q_cur = next;
- q_delta.x = 0;
- q_delta.y = 0;
- q_delta.z = 0;
- q_delta.w = 1;
- need_redraw(g_L);
- }
- if (g_mouse_down[2] && button == 3) {
- g_offset.v[0] += g_offset_next.v[0];
- g_offset.v[1] += g_offset_next.v[1];
- g_offset.v[2] += g_offset_next.v[2];
- g_offset_next.v[0] = 0;
- g_offset_next.v[1] = 0;
- g_offset_next.v[2] = 0;
- need_redraw(g_L);
- }
- g_mouse_down[button -1] = false;
- on_mouse_move(win, x, y);
- }
- static void on_mouse_button_down(struct glplatform_win *win, int button, int x, int y)
- {
- g_mouse_down[button -1] = true;
- g_dx[button - 1] = x;
- g_dy[button - 1] = y;
- on_mouse_move(win, x, y);
- }
- static void on_mouse_move(struct glplatform_win *win, int x, int y)
- {
- struct math3d_quaternion next;
- math3d_quaternion_mul(&q_delta, &q_cur, &next);
- if (g_mouse_down[0]) {
- struct math3d_vec3 axis;
- axis.v[0] = g_dy[0] - y;
- axis.v[1] = g_dx[0] - x;
- axis.v[2] = 0;
- float length = math3d_vec3_length(&axis);
- math3d_vec3_normalize(&axis);
- math3d_quaternion_from_axis_angle(&q_delta, &axis, length * 3 / win->width);
- need_redraw(g_L);
- }
- if (g_mouse_down[2]) {
- struct math3d_vec3 delta;
- delta.v[0] = (g_dx[2] - x) * 2.0 / win->width;
- delta.v[1] = -(g_dy[2] - y) * 2.0 / win->height;
- delta.v[2] = 0;
- math3d_quaternion_unit_inv_mul_vec3(&next, &delta, &g_offset_next);
- g_offset_next.v[0] = -g_offset_next.v[0];
- g_offset_next.v[1] = -g_offset_next.v[1];
- g_offset_next.v[2] = -g_offset_next.v[2];
- need_redraw(g_L);
- }
- }
- static void on_expose(struct glplatform_win *win)
- {
- need_redraw(g_L);
- }
- static void on_mouse_wheel(struct glplatform_win *win, int x, int y, int direction)
- {
- g_log_zoom += direction * 0.1;
- need_redraw(g_L);
- }
- static int lua_backtrace_string(lua_State *L)
- {
- static lua_Debug ar;
- int i = 0;
- while (lua_getstack(L, i++, &ar)) {
- lua_getinfo(L, "Sl", &ar);
- char *str = g_strdup_printf("%s:%d\n", ar.source, ar.currentline);
- lua_pushstring(L, str);
- g_free(str);
- }
- lua_concat(L, i -1);
- return 1;
- }
- static int make_path_relative(lua_State *L)
- {
- if (!lua_isstring(L, -1) || !lua_isstring(L, -2)) {
- lua_pushnil(L);
- return 1;
- }
- const char *x = lua_tostring(L, -1); //file
- const char *y = lua_tostring(L, -2); //origin path (with trailing '/')
- int strings = 1;
- while (*x && *x == *y) {
- x++;
- y++;
- }
- while (*y) {
- if (*(y++) == '/') {
- lua_pushstring(L, "../");
- strings++;
- }
- }
- lua_pushstring(L, x);
- lua_concat(L, strings);
- return 1;
- }
- static void truncate_to_dirname(char *str)
- {
- char *x = str;
- char *y = NULL;
- while (*x) {
- if (*x == '/')
- y = x;
- x++;
- }
- if (y)
- *(++y) = 0;
- else
- *str = 0;
- }
- static int directory_name(lua_State *L)
- {
- char *filename = strdup(lua_tostring(L, -1));
- truncate_to_dirname(filename);
- lua_pushstring(L, filename);
- free(filename);
- return 1;
- }
- static void on_resize(struct glplatform_win *win)
- {
- need_redraw(g_L);
- }
- static void on_destroy(struct glplatform_win *win)
- {
- exit(0);
- }
- struct glplatform_win_callbacks cb;
- static uint8_t *get_file_buffer(const char *fname, size_t *size)
- {
- FILE *f = fopen(fname, "rb");
- if (!f) {
- return NULL;
- }
- fseek(f, 0, SEEK_END);
- *size = ftell(f);
- fseek(f, 0, SEEK_SET);
- uint8_t *ret = (uint8_t *)malloc(*size);
- if (fread(ret, *size, 1, f) != 1) {
- free(ret);
- ret = NULL;
- }
- fclose(f);
- return ret;
- }
- struct gl_state {
- const uint8_t *blob;
- size_t blob_size;
- bool initialized;
- GLuint vao;
- } g_gl_state;
- static bool recompile_shaders();
- static void init_gl_state();
- static gboolean dispatch(gpointer user_data)
- {
- glplatform_get_events(false);
- return glplatform_process_events();
- }
- int luaopen_material_editor_capi(lua_State *L)
- {
- lua_newtable(L);
- luaL_setfuncs(L, lua_b2l_material_editor_capi, 0);
- g_L = L;
- cb.on_expose = on_expose;
- cb.on_destroy = on_destroy;
- cb.on_resize = on_resize;
- cb.on_mouse_button_up = on_mouse_button_up;
- cb.on_mouse_button_down = on_mouse_button_down;
- cb.on_mouse_move = on_mouse_move;
- cb.on_mouse_wheel = on_mouse_wheel;
- cb.on_resize = on_resize;
- glplatform_init();
- GMainContext *ctx = g_main_context_default();
- g_src = g_unix_fd_source_new(glplatform_epoll_fd, G_IO_IN);
- g_source_attach(g_src, ctx);
- g_source_set_callback(g_src, dispatch, NULL, NULL);
- return 1;
- }
- static int create_glwin(lua_State *L)
- {
- int xid = lua_tointeger(L, -1);
- g_win = glplatform_create_window("B2L 3D View", &cb, NULL, 512, 512);
- if (!g_win)
- exit(-1);
- glplatform_set_win_type(g_win, GLWIN_UTILITY);
- glplatform_set_win_transient_for(g_win, xid);
- glplatform_show_window(g_win);
- g_ctx = glplatform_create_context(g_win, 3, 3);
- if (!g_ctx)
- exit(-1);
- glplatform_make_current(g_win, g_ctx);
- need_redraw(L);
- return 0;
- }
- static int need_redraw(lua_State *L)
- {
- g_need_redraw = true;
- return 0;
- }
- struct insert_shader_uniforms_state {
- const char *tag;
- const char *name;
- int type_code;
- bool uniform;
- lua_State *L;
- int uniform_table_idx;
- };
- static void insert_shader_uniforms_enter(struct glsl_ast_walk_data *data, struct glsl_node *n, intptr_t state_)
- {
- int i;
- struct insert_shader_uniforms_state *state = (struct insert_shader_uniforms_state *) state_;
- switch(n->code) {
- case TRANSLATION_UNIT:
- case DECLARATION_STATEMENT_LIST:
- for (i = n->child_count - 1; i >= 0; i--) {
- glsl_ast_walk_push_node(data, n->children[i]); //DECLARATION_STATEMENT
- }
- break;
- case TYPE_QUALIFIER_LIST:
- for (i = 0; i < n->child_count; i++) {
- if (n->children[i]->code == UNIFORM) {
- state->uniform = true;
- }
- }
- break;
- case DECLARATION:
- glsl_ast_walk_push_node(data, n->children[0]); //declaration
- break;
- case SECTION_STATEMENT:
- state->tag = n->children[0]->data.str; //IDENTIFIER
- glsl_ast_walk_push_node(data, n->children[1]);
- break;
- case SINGLE_DECLARATION:
- state->name = n->children[1]->data.str; //IDENTIFIER
- glsl_ast_walk_push_node(data, n->children[0]);
- break;
- case FULLY_SPECIFIED_TYPE:
- glsl_ast_walk_push_node(data, n->children[1]); //TYPE_SPECIFIER
- glsl_ast_walk_push_node(data, n->children[0]); //TYPE_QUALIFIER_LIST
- break;
- case TYPE_SPECIFIER:
- state->type_code = n->children[0]->code; //type_specifier_nonarray
- break;
- }
- }
- static void insert_shader_uniforms_exit(struct glsl_ast_walk_data *data, struct glsl_node *n, intptr_t state_)
- {
- struct insert_shader_uniforms_state *state = (struct insert_shader_uniforms_state *) state_;
- switch (n->code) {
- case SECTION_STATEMENT:
- state->tag = NULL;
- break;
- case DECLARATION: {
- const char *type_string;
- switch (state->type_code) {
- case FLOAT:
- type_string = "float";
- break;
- case VEC3:
- type_string = "vec3";
- break;
- case MAT4:
- type_string = "mat4";
- break;
- case BOOL:
- type_string = "bool";
- break;
- case SAMPLER2D:
- type_string = "sampler2D";
- break;
- default:
- type_string = NULL;
- }
- if (state->uniform && type_string && state->name) {
- lua_getfield(state->L, state->uniform_table_idx, state->name);
- if (lua_isnil(state->L, -1)) {
- lua_newtable(state->L);
- lua_pushstring(state->L, type_string);
- lua_setfield(state->L, -2, "datatype");
- if (state->tag) {
- lua_pushstring(state->L, state->tag);
- lua_setfield(state->L, -2, "tag");
- }
- lua_setfield(state->L, state->uniform_table_idx, state->name);
- }
- lua_pushstring(state->L, state->name);
- lua_rawseti(state->L, state->uniform_table_idx, lua_rawlen(state->L, state->uniform_table_idx) + 1);
- lua_pop(state->L, 1);
- }
- state->uniform = false;
- state->type_code = -1;
- state->name = NULL;
- } break;
- }
- }
- int insert_shader_uniforms(lua_State *L, int text_idx, int uniform_table_idx)
- {
- const char *temp = lua_tostring(L, text_idx);
- struct glsl_parse_context context;
- glsl_parse_context_init(&context);
- glsl_parse_string(&context, temp);
- struct insert_shader_uniforms_state lstate;
- //Data we need during traversal
- lstate.L = L;
- lstate.uniform_table_idx = uniform_table_idx;
- lstate.type_code = -1;
- lstate.uniform = false;
- lstate.name = NULL;
- lstate.tag = NULL;
- struct glsl_ast_walk_data wd;
- glsl_ast_walk_init(&wd);
- glsl_ast_walk_push_node(&wd, context.root);
- glsl_ast_walk(&wd, (intptr_t)&lstate, insert_shader_uniforms_enter, insert_shader_uniforms_exit);
- glsl_parse_context_destroy(&context);
- return 0;
- }
- //
- // Strip meta-data from shader text
- //
- int filter_shader_text(lua_State *L)
- {
- const char *input = lua_tostring(L, -1);
- char *output;
- struct glsl_parse_context context;
- glsl_parse_context_init(&context);
- glsl_parse_string(&context, input);
- output = glsl_ast_generate_glsl(context.root);
- glsl_parse_context_destroy(&context);
- lua_pushstring(L, "#version 330\n"); //TODO: we need to grab the actual text for this
- lua_pushstring(L, output);
- lua_concat(L, 2);
- //glsl_ast_print(context.root, 0);
- //printf("%s\n", output);
- free(output);
- return 1;
- }
- static int get_shader_uniforms(lua_State *L)
- {
- int vertex_text_index = lua_gettop(L) - 1;
- int fragment_text_index = lua_gettop(L);
- lua_newtable(L);
- if (insert_shader_uniforms(L, vertex_text_index, lua_gettop(L))) {
- lua_pop(L, 1);
- lua_pushnil(L);
- return 1;
- }
- if (insert_shader_uniforms(L, fragment_text_index, lua_gettop(L))) {
- lua_pop(L, 1);
- lua_pushnil(L);
- return 1;
- }
- return 1;
- }
- static void init_gl_state()
- {
- printf("OpenGL version %s\n", glGetString(GL_VERSION));
- glGenVertexArrays(1, &g_gl_state.vao);
- glBindVertexArray(g_gl_state.vao);
- g_gl_state.initialized = true;
- }
- static void redraw(struct glplatform_win *win)
- {
- struct glplatform_thread_state thread_state;
- glplatform_get_thread_state(&thread_state);
- glplatform_make_current(win, g_ctx);
- lua_State *L = g_L;
- static bool gl_init_attempted = false;
- static bool gl_init_result = false;
- if (!gl_init_attempted) {
- gl_init_result = glplatform_glcore_init(3, 3);
- }
- if (!gl_init_result) {
- fprintf(stderr, "Failed to initialize OpenGL bindings\n");
- exit(-1);
- return;
- }
- if (!GLPLATFORM_GL_ARB_buffer_storage) {
- fprintf(stderr, "Missing GL extension: GL_ARB_buffer_storage\n");
- exit(-1);
- }
- if (!GLPLATFORM_GL_ARB_vertex_attrib_binding) {
- fprintf(stderr, "Missing GL extension: GL_ARB_vertex_attrib_binding\n");
- exit(-1);
- }
- glViewport(0, 0, win->width, win->height);
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- int top_idx = lua_gettop(L);
- if (!g_gl_state.initialized)
- init_gl_state();
- if (!g_gl_state.initialized) {
- goto end;
- }
- lua_getglobal(L, "b2l_data"); //1
- if (!lua_istable(L, -1)) {
- lua_pop(L, 1);
- goto end;
- }
- int b2l_data_idx = lua_gettop(L);
- lua_getglobal(L, "current_object");
- if (!lua_isstring(L, -1)) {
- goto end;
- }
- const char *current_object = lua_tostring(L, -1);
- lua_getglobal(L, "current_scene");
- if (!lua_isstring(L, -1)) {
- goto end;
- }
- const char *current_scene = lua_tostring(L, -1);
- double frame;
- int frame_start;
- lua_getglobal(L, "frame_start");
- frame_start = lua_tointeger(L, -1);
- lua_getglobal(L, "frame_delta");
- frame = frame_start + lua_tonumber(L, -1);
- struct math3d_mat4 view;
- struct math3d_mat4 model;
- struct math3d_mat4 proj;
- struct math3d_quaternion next;
- math3d_quaternion_mul(&q_delta, &q_cur, &next);
- math3d_quaternion_to_mat4(&next, &view);
- view.v[3][3] = 1;
- math3d_mat4_identity(&model);
- model.v[3][0] = g_offset.v[0] + g_offset_next.v[0];
- model.v[3][1] = g_offset.v[1] + g_offset_next.v[1];
- model.v[3][2] = g_offset.v[2] + g_offset_next.v[2];
- float zoom = exp(g_log_zoom);
- float zr = 100;
- math3d_mat4_zero(&proj);
- proj.v[0][0] = 1.0/zoom;
- proj.v[1][1] = 1.0*win->width/(zoom*win->height);
- proj.v[2][2] = 1.0/zr;
- proj.v[3][3] = 1.0;
- lua_getglobal(L, "materials");
- int materials_idx = lua_gettop(L);
- if (lua_isnil(L, -1))
- goto end;
- lua_pushnil(L);
- while(lua_next(L, -2)) {
- int material_idx = lua_gettop(L);
- lua_getfield(L, material_idx, "program");
- //
- // Create material program object if it's missing
- //
- if (!lua_isuserdata(L, -1)) {
- lprogram_create(L);
- lua_setfield(L, material_idx, "program");
- }
- lua_getfield(L, material_idx, "program");
- int program_idx = lua_gettop(L);
- struct program *program = lua_touserdata(L, program_idx);
- //
- // Assign shaders to the program. The shaders
- // will be compiled and the program will be linked
- // if the values are different than previously
- // specified
- //
- lua_getfield(L, material_idx, "shaders");
- lua_getfield(L, -1, "_vs_text");
- lua_getfield(L, -2, "_fs_text");
- const char *vs_text = lua_tostring(L, -2);
- const char *fs_text = lua_tostring(L, -1);
- lua_pushvalue(L, program_idx);
- if (!lprogram_set_shaders(L, vs_text, fs_text)) {
- goto end;
- }
- glUseProgram(program->program);
- //
- // Upload textures if neccisary
- //
- lua_getfield(L, material_idx, "params");
- lua_pushnil(L); /* first key */
- int texunit = 0;
- while (lua_next(L, -2)) {
- int variable_idx = lua_gettop(L);
- lua_getfield(L, variable_idx, "datatype");
- const char *datatype = lua_tostring(L, -1);
- if (!strcmp(datatype,"sampler2D")) {
- lua_getfield(L, variable_idx, "_texture");
- if (!lua_isuserdata(L, -1)) {
- lua_getfield(L, variable_idx, "_pbuf");
- if (lua_isuserdata(L, -1)) {
- GdkPixbuf *pbuf;
- lua_getfield(L, -1, "_native");
- pbuf = (GdkPixbuf *)lua_touserdata(L, -1);
- ltexture_create(L, pbuf);
- lua_setfield(L, variable_idx, "_texture");
- }
- }
- texunit++;
- }
- lua_settop(L, variable_idx - 1);
- }
- lua_settop(L, material_idx - 1);
- }
- render_mesh(L, b2l_data_idx, materials_idx, g_gl_state.blob,
- current_scene,
- current_object, frame,
- &model,
- &view,
- &proj);
- end:
- lua_settop(L, top_idx);
- {
- GLenum err = glGetError();
- if (err)
- printf("render_scene GL error = %d\n", err);
- }
- glplatform_swap_buffers(g_win);
- glplatform_set_thread_state(&thread_state);
- g_need_redraw = false;
- return;
- }
- static int set_b2l_file(lua_State *L)
- {
- size_t blob_size;
- uint8_t *blob = get_file_buffer(lua_tostring(L, -1), &blob_size);
- if (blob == NULL) {
- printf("failed to load blob file %s\n",lua_tostring(L, -1));
- return -1;
- }
- g_gl_state.blob = blob;
- g_gl_state.blob_size = blob_size;
- return 0;
- }
- static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize)
- {
- (void)ud;
- (void)osize; /* not used */
- if (nsize == 0) {
- free(ptr);
- return NULL;
- } else {
- return realloc(ptr, nsize);
- }
- }
- int luaopen_lgi_corelgilua (lua_State* L);
- int lua_message_handler (lua_State* L)
- {
- lua_pushvalue(L, -1);
- lua_pushstring(L, "\n");
- lua_backtrace_string(L);
- lua_concat(L, 3);
- return 1;
- }
- int lua_panic_handler (lua_State* L)
- {
- lua_pushvalue(L, -1);
- lua_pushstring(L, "\n");
- lua_backtrace_string(L);
- lua_concat(L, 3);
- fprintf(stderr, "%s\n", lua_tostring(L, -1));
- return 1;
- }
- static void print_help(const char *program_name)
- {
- printf("Usage: %s [OPTION]...\n", program_name);
- printf("\n"
- "Options:\n"
- " -d,--data-dir <path> Path to application data. Overrides B2L_DATA_DIR.\n"
- " -h,--help Print this page.\n");
- }
- int main(int argc, char **argv)
- {
- /*
- char exe_path[200];
- ssize_t sz = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
- if (sz < 0)
- return -1;
- exe_path[sz] = '\0';
- truncate_to_dirname(exe_path);
- */
- const char *b2l_data_dir = NULL;
- const char *b2l_file_name = NULL;
- static struct option options [] = {
- {"data-dir" , 1, 0, 'd' },
- {"help" , 0, 0, 'h' }
- };
- while (1) {
- int option_index;
- int c = getopt_long(argc, argv, "d:h", options, &option_index);
- if (c == -1) {
- break;
- }
- switch(c) {
- case 'd':
- b2l_data_dir = optarg;
- break;
- case 'h':
- print_help(argv[0]);
- exit(0);
- break;
- }
- }
- if (!b2l_data_dir) {
- b2l_data_dir = getenv("B2L_DATA_DIR");
- }
- if (!b2l_data_dir) {
- b2l_data_dir = DATA_DIR;
- }
- if (optind < argc) {
- b2l_file_name = argv[optind];
- }
- lua_State *L = lua_newstate(l_alloc, NULL);
- luaL_openlibs(L);
- lua_atpanic(L, lua_panic_handler);
- lua_getglobal(L, "package"); //1
- lua_getfield(L, -1, "preload"); //2
- lua_pushcfunction(L, luaopen_material_editor_capi);
- lua_setfield(L, -2, "material_editor_capi");
- lua_pushcfunction(L, luaopen_lgi_corelgilua);
- lua_setfield(L, -2, "lgi.corelgilua");
- lua_pushstring(L, b2l_data_dir);
- lua_pushstring(L, "/?.lua;");
- lua_pushstring(L, b2l_data_dir);
- lua_pushstring(L, "/lgi/?.lua");
- lua_concat(L, 4);
- lua_setfield(L, -3, "path");
- lua_pushstring(L, b2l_data_dir);
- lua_pushstring(L, "/lib/?.so;");
- lua_pushstring(L, b2l_data_dir);
- lua_pushstring(L, "/lgi/lib/?.so");
- lua_concat(L, 4);
- lua_setfield(L, -3, "cpath");
- lua_pushcfunction(L, lua_message_handler);
- int msgh = lua_gettop(L);
- lua_pushstring(L, b2l_data_dir);
- lua_pushstring(L, "/material_editor.lua");
- lua_concat(L, 2);
- int err;
- err = luaL_loadfile(L, lua_tostring(L, -1));
- if (err != LUA_OK) {
- fprintf(stderr, "Error loading script: %s\n", lua_tostring(L, -1));
- return 0;
- }
- if (!b2l_file_name) {
- lua_pushnil(L);
- } else {
- lua_pushstring(L, b2l_file_name);
- }
- lua_setglobal(L, "b2l_filename");
- err = lua_pcall(L, 0, 0, msgh);
- switch (err) {
- case LUA_ERRRUN:
- fprintf(stderr, "Lua runtime error: ");
- break;
- case LUA_ERRMEM:
- fprintf(stderr, "Lua memory allocation error: ");
- break;
- case LUA_ERRERR:
- fprintf(stderr, "Lua internal error: ");
- break;
- case LUA_ERRGCMM:
- fprintf(stderr, "Lua garbage collection error: ");
- break;
- }
- if (err != LUA_OK) {
- fprintf(stderr, "%s\n", lua_tostring(L, -1));
- return -1;
- }
- bool shutdown = false;
- bool block = true;
- bool animation_playing = false;
- while (!shutdown) {
- while ((gtk_events_pending() || block) && !shutdown) {
- gtk_main_iteration_do(block);
- block = false;
- lua_getglobal(g_L, "shutdown");
- shutdown = lua_toboolean(g_L, -1);
- lua_pop(g_L, 1);
- lua_getglobal(g_L, "playing_animation");
- animation_playing = lua_toboolean(g_L, -1);
- lua_pop(g_L, 1);
- }
- if (animation_playing) {
- lua_getglobal(g_L, "animation_update");
- lua_call(g_L, 0, 0);
- g_need_redraw = true;
- }
- if (g_win && g_need_redraw) {
- redraw(g_win);
- }
- block = !animation_playing;
- if (!block) {
- glplatform_get_events(false);
- glplatform_process_events();
- }
- lua_gc(g_L, LUA_GCCOLLECT, 0);
- }
- return 0;
- }
|