Skip to content

Commit a5b0988

Browse files
committed
read settings for sapp_desc
1 parent c1ead62 commit a5b0988

File tree

6 files changed

+263
-134
lines changed

6 files changed

+263
-134
lines changed

src/data/settingdefault.dl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ draw_instance : 65536
66
entry : main.lua
77
project : soluna
88
service_path : "./?.lua"
9+
width : 1024
10+
height : 768
11+
high_dpi : false
12+
window_title : soluna
13+

src/embedlua.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "render.lua.h"
1212
#include "settingdefault.dl.h"
1313
#include "settings.lua.h"
14+
#include "initsetting.lua.h"
1415
#include "fontmgr.lua.h"
1516
#include "gamepad.lua.h"
1617
#include "soluna.lua.h"
@@ -69,6 +70,7 @@ luaopen_embedsource(lua_State *L) {
6970
REG_SOURCE(soluna)
7071
REG_SOURCE(util)
7172
REG_SOURCE(coroutine)
73+
REG_SOURCE(initsetting)
7274
lua_setfield(L, -2, "lib");
7375

7476
lua_newtable(L); // service

src/entry.c

Lines changed: 137 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,50 @@ lversion(lua_State *L) {
977977
return 2;
978978
}
979979

980+
static void
981+
desc_get_boolean(lua_State *L, bool *r, int index, const char * key) {
982+
if (lua_getfield(L, index, key) == LUA_TBOOLEAN) {
983+
*r = lua_toboolean(L, -1);
984+
} else {
985+
luaL_checktype(L, -1, LUA_TNIL);
986+
}
987+
lua_pop(L, 1);
988+
}
989+
990+
static void
991+
desc_get_int(lua_State *L, int *r, int index, const char * key) {
992+
if (lua_getfield(L, index, key) == LUA_TNUMBER) {
993+
*r = lua_tointeger(L, -1);
994+
} else {
995+
luaL_checktype(L, -1, LUA_TNIL);
996+
}
997+
lua_pop(L, 1);
998+
}
999+
1000+
static void
1001+
desc_get_string(lua_State *L, const char **r, int index, const char * key) {
1002+
if (lua_getfield(L, index, key) == LUA_TSTRING) {
1003+
*r = lua_tostring(L, -1);
1004+
} else {
1005+
luaL_checktype(L, -1, LUA_TNIL);
1006+
}
1007+
lua_pop(L, 1);
1008+
}
1009+
1010+
static int
1011+
linit_desc(lua_State *L) {
1012+
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
1013+
luaL_checktype(L, 2, LUA_TTABLE);
1014+
sapp_desc *d = lua_touserdata(L, 1);
1015+
desc_get_boolean(L, &d->high_dpi, 2, "high_dpi");
1016+
desc_get_boolean(L, &d->fullscreen, 2, "fullscreen");
1017+
desc_get_int(L, &d->width, 2, "width");
1018+
desc_get_int(L, &d->height, 2, "height");
1019+
desc_get_string(L, &d->window_title, 2, "window_title");
1020+
1021+
return 0;
1022+
}
1023+
9801024
int
9811025
luaopen_soluna_app(lua_State *L) {
9821026
luaL_checkversion(L);
@@ -994,6 +1038,7 @@ luaopen_soluna_app(lua_State *L) {
9941038
{ "close_window", lclose_window },
9951039
{ "platform", NULL },
9961040
{ "version", lversion },
1041+
{ "init_desc", linit_desc },
9971042
{ NULL, NULL },
9981043
};
9991044
luaL_newlib(L, l);
@@ -1033,22 +1078,6 @@ void soluna_openlibs(lua_State *L);
10331078

10341079
static const char *code = "local embed = require 'soluna.embedsource' ; local f = load(embed.runtime.main()) ; return f(...)";
10351080

1036-
static void
1037-
set_app_info(lua_State *L, int index) {
1038-
lua_newtable(L);
1039-
const float dpi_scale = sapp_dpi_scale();
1040-
const float safe_scale = dpi_scale > 0.0f ? dpi_scale : 1.0f;
1041-
const int fb_width = sapp_width();
1042-
const int fb_height = sapp_height();
1043-
const int logical_width = (int)((float)fb_width / safe_scale + 0.5f);
1044-
const int logical_height = (int)((float)fb_height / safe_scale + 0.5f);
1045-
lua_pushinteger(L, logical_width);
1046-
lua_setfield(L, -2, "width");
1047-
lua_pushinteger(L, logical_height);
1048-
lua_setfield(L, -2, "height");
1049-
lua_setfield(L, index, "app");
1050-
}
1051-
10521081
static int
10531082
pmain(lua_State *L) {
10541083
soluna_openlibs(L);
@@ -1067,8 +1096,6 @@ pmain(lua_State *L) {
10671096
lua_setfield(L, arg_table, k);
10681097
}
10691098
}
1070-
set_app_info(L, arg_table);
1071-
10721099
int arg_n = lua_gettop(L) - arg_table + 1;
10731100
if (luaL_loadstring(L, code) != LUA_OK) {
10741101
return lua_error(L);
@@ -1125,13 +1152,40 @@ msghandler(lua_State *L) {
11251152
return 1;
11261153
}
11271154

1155+
static void
1156+
get_app_info(lua_State *L) {
1157+
lua_newtable(L);
1158+
const float dpi_scale = sapp_dpi_scale();
1159+
const float safe_scale = dpi_scale > 0.0f ? dpi_scale : 1.0f;
1160+
const int fb_width = sapp_width();
1161+
const int fb_height = sapp_height();
1162+
const int logical_width = (int)((float)fb_width / safe_scale + 0.5f);
1163+
const int logical_height = (int)((float)fb_height / safe_scale + 0.5f);
1164+
lua_pushinteger(L, logical_width);
1165+
lua_setfield(L, -2, "width");
1166+
lua_pushinteger(L, logical_height);
1167+
lua_setfield(L, -2, "height");
1168+
}
1169+
11281170
static int
11291171
start_app(lua_State *L) {
1130-
lua_settop(L, 0);
1131-
lua_pushcfunction(L, msghandler);
1132-
lua_pushcfunction(L, pmain);
1133-
if (lua_pcall(L, 0, 1, 1) != LUA_OK) {
1134-
fprintf(stderr, "Start fatal : %s", lua_tostring(L, -1));
1172+
if (L == NULL) {
1173+
fprintf(stderr, "Can't open lua state\n");
1174+
return 1;
1175+
}
1176+
1177+
if (lua_gettop(L) != 2) {
1178+
fprintf(stderr, "Invalid lua stack (top = %d)\n", lua_gettop(L));
1179+
return 1;
1180+
}
1181+
if (lua_getfield(L, -1, "start") != LUA_TFUNCTION) {
1182+
fprintf(stderr, "No start function\n");
1183+
return 1;
1184+
}
1185+
lua_replace(L, -2);
1186+
get_app_info(L);
1187+
if (lua_pcall(L, 1, 1, 1) != LUA_OK) {
1188+
fprintf(stderr, "Start fatal : %s\n", lua_tostring(L, -1));
11351189
return 1;
11361190
} else {
11371191
return init_callback(L, CTX);
@@ -1140,19 +1194,6 @@ start_app(lua_State *L) {
11401194

11411195
static void
11421196
app_init() {
1143-
static struct app_context app;
1144-
lua_State *L = luaL_newstate();
1145-
if (L == NULL)
1146-
return;
1147-
1148-
app.L = L;
1149-
app.quitL = NULL;
1150-
app.send_log = NULL;
1151-
app.send_log_ud = NULL;
1152-
app.mqueue = NULL;
1153-
1154-
CTX = &app;
1155-
11561197
#if defined(__APPLE__)
11571198
soluna_macos_install_ime();
11581199
#endif
@@ -1164,10 +1205,14 @@ app_init() {
11641205
.environment = sglue_environment(),
11651206
.logger.func = log_func,
11661207
});
1208+
1209+
lua_State *L = CTX->L;
11671210
if (start_app(L)) {
11681211
sargs_shutdown();
1169-
lua_close(L);
1170-
app.L = NULL;
1212+
if (L) {
1213+
lua_close(L);
1214+
}
1215+
CTX->L = NULL;
11711216
sapp_quit();
11721217
} else {
11731218
sargs_shutdown();
@@ -1241,29 +1286,79 @@ app_event(const sapp_event* ev) {
12411286
}
12421287
}
12431288

1289+
static int
1290+
init_settings(lua_State *L, sapp_desc *desc) {
1291+
if (L == NULL) {
1292+
fprintf(stderr, "Can't open lua state\n");
1293+
return 1;
1294+
}
1295+
if (lua_gettop(L) != 2) {
1296+
fprintf(stderr, "Invalid lua stack (top = %d)\n", lua_gettop(L));
1297+
return 1;
1298+
}
1299+
if (lua_getfield(L, -1, "init") != LUA_TFUNCTION) {
1300+
fprintf(stderr, "No start function\n");
1301+
return 1;
1302+
}
1303+
lua_pushlightuserdata(L, (void *)desc);
1304+
if (lua_pcall(L, 1, 0, 1) != LUA_OK) {
1305+
fprintf(stderr, "Start fatal : %s\n", lua_tostring(L, -1));
1306+
return 1;
1307+
} else {
1308+
return 0;
1309+
}
1310+
}
1311+
12441312
sapp_desc
12451313
sokol_main(int argc, char* argv[]) {
1314+
// init sargs
12461315
sargs_desc arg_desc;
12471316
memset(&arg_desc, 0, sizeof(arg_desc));
12481317
arg_desc.argc = argc;
12491318
arg_desc.argv = argv;
12501319
sargs_setup(&arg_desc);
12511320

1321+
// init L
1322+
static struct app_context app;
1323+
lua_State *L = luaL_newstate();
1324+
1325+
lua_settop(L, 0);
1326+
lua_pushcfunction(L, msghandler);
1327+
lua_pushcfunction(L, pmain);
1328+
1329+
if (lua_pcall(L, 0, 1, 1) != LUA_OK) {
1330+
fprintf(stderr, "Init fatal : %s\n", lua_tostring(L, -1));
1331+
lua_close(L);
1332+
L = NULL;
1333+
}
1334+
1335+
// default sapp_desc
1336+
12521337
sapp_desc d;
12531338
memset(&d, 0, sizeof(d));
12541339

1255-
d.high_dpi = true;
1256-
d.width = 1024;
1257-
d.height = 768;
12581340
d.init_cb = app_init;
12591341
d.frame_cb = app_frame;
12601342
d.cleanup_cb = app_cleanup;
12611343
d.event_cb = app_event;
12621344
d.logger.func = log_func;
12631345
d.win32_console_utf8 = 1;
12641346
d.win32_console_attach = 1;
1265-
d.window_title = "soluna";
12661347
d.alpha = 0;
1348+
1349+
if (init_settings(L, &d)) {
1350+
fprintf(stderr, "Init setting fatal : %s\n", lua_tostring(L, -1));
1351+
lua_close(L);
1352+
L = NULL;
1353+
}
1354+
1355+
app.L = L;
1356+
app.quitL = NULL;
1357+
app.send_log = NULL;
1358+
app.send_log_ud = NULL;
1359+
app.mqueue = NULL;
1360+
1361+
CTX = &app;
12671362

12681363
return d;
12691364
}

src/lualib/initsetting.lua

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
local datalist = require "soluna.datalist"
2+
local source = require "soluna.embedsource"
3+
local lfs = require "soluna.lfs"
4+
local file = require "soluna.file"
5+
6+
global type, error, pairs, assert
7+
8+
local S = {}
9+
10+
local function patch(s, k, v)
11+
if type(k) == "number" then
12+
-- ignore
13+
return
14+
end
15+
local branch, key = k:match "^([^.]+)%.(.+)"
16+
if branch then
17+
local tree = s[branch]
18+
if tree == nil then
19+
tree = {}
20+
s[branch] = tree
21+
elseif type(tree) ~= "table" then
22+
error ("Conflict setting key : " .. k)
23+
end
24+
s = tree
25+
k = key
26+
end
27+
28+
if type(v) == "table" then
29+
local orig_v = s[k]
30+
if orig_v == nil then
31+
s[k] = v
32+
elseif type(orig_v) == "table" then
33+
for sub_k,sub_v in pairs(v) do
34+
patch(orig_v, sub_k, sub_v)
35+
end
36+
else
37+
error ("Conflict setting key : " .. k)
38+
end
39+
else
40+
s[k] = v
41+
end
42+
end
43+
44+
local function settings_filename(filename)
45+
if filename then
46+
local realname = lfs.realpath(filename)
47+
local curpath = realname:match "(.*)[/\\][^/\\]+$"
48+
if curpath then
49+
lfs.chdir(curpath)
50+
end
51+
return realname
52+
end
53+
if file.exist "main.game" then
54+
return "main.game"
55+
end
56+
end
57+
58+
function S.init(args)
59+
local default_settings = datalist.parse(source.data.settingdefault)
60+
local realname = settings_filename(args[1])
61+
if realname then
62+
local loader = file.loader(realname)
63+
local game_settings = datalist.parse(loader)
64+
for k,v in pairs(game_settings) do
65+
patch(default_settings, k,v)
66+
end
67+
end
68+
for k,v in pairs(args) do
69+
if type(k) == "string" then
70+
patch(default_settings, k,v)
71+
end
72+
end
73+
return default_settings
74+
end
75+
76+
return S

0 commit comments

Comments
 (0)