diff --git a/Makefile b/Makefile index 66b02100f..242389cb3 100644 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ WINDOWS_AUTO_BUILDER ?= 0 # Setup extra cflags EXTRA_CFLAGS ?= EXTRA_CPP_FLAGS ?= -EXTRA_CFLAGS += -Wno-format-security -Wno-trigraphs +EXTRA_CFLAGS += -Wno-format-security -Wno-trigraphs -Wno-missing-braces dev:; @$(MAKE) DEVELOPMENT=1 diff --git a/autogen/common.py b/autogen/common.py index 1c3575b02..09b806de9 100644 --- a/autogen/common.py +++ b/autogen/common.py @@ -6,6 +6,7 @@ usf_types = ['u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'f32', 'f64'] vec_types = list(VEC_TYPES.keys()) typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision', 'LevelScript', 'Trajectory', 'Texture'] cobject_function_identifier = 'FUNCTION' +cobject_property_identifier = 'PROPERTY' type_mappings = { 'char': 's8', @@ -149,14 +150,10 @@ def translate_type_to_lvt(ptype, allowArrays=False): if ptype == cobject_function_identifier: return "LVT_FUNCTION" - if "struct" in ptype: - if pointerLvl > 1: - return "LVT_???" - if pointerLvl == 1: - return "LVT_COBJECT_P" - return "LVT_COBJECT" + if ptype == cobject_property_identifier: + return "LVT_PROPERTY" - if ptype in override_types: + if "struct" in ptype or ptype in override_types: if pointerLvl > 1: return "LVT_???" if pointerLvl == 1: @@ -174,16 +171,8 @@ def translate_type_to_lot(ptype, allowArrays=True): pointerLvl = 0 lvt = translate_type_to_lvt(ptype, allowArrays=allowArrays) - if ptype == 'void': - return 'LOT_NONE' - - if ptype == 'const char*': - return 'LOT_NONE' - - if ptype == 'ByteString': - return 'LOT_NONE' - - if 'unsigned' not in ptype and (ptype == 'char*' or ('char' in ptype and '[' in ptype)): + if ptype == ('void', 'const char*', 'ByteString') \ + or 'unsigned' not in ptype and (ptype == 'char*' or ('char' in ptype and '[' in ptype)): return 'LOT_NONE' # Remove array symbols so they can be identified @@ -199,13 +188,7 @@ def translate_type_to_lot(ptype, allowArrays=True): if '[' in ptype or '{' in ptype: return 'LOT_???' - if 'enum ' in ptype: - return 'LOT_NONE' - - if ptype in usf_types: - return 'LOT_NONE' - - if extract_integer_datatype(ptype): + if 'enum ' in ptype or ptype in usf_types or extract_integer_datatype(ptype): return 'LOT_NONE' # Strip out our pointer stars to get the true type. @@ -214,22 +197,10 @@ def translate_type_to_lot(ptype, allowArrays=True): pointerLvl = ptype.count("*") ptype = ptype.replace("*", "").strip() - if ptype == 'bool': - return 'LOT_NONE' - if ptype in vec_types: return 'LOT_' + ptype.upper() - if ptype == 'float': - return 'LOT_NONE' - - if ptype == 'LuaFunction': - return 'LOT_NONE' - - if ptype == 'LuaTable': - return 'LOT_NONE' - - if ptype == cobject_function_identifier: + if ptype in ('bool', 'float', 'LuaFunction', 'LuaTable', cobject_function_identifier, cobject_property_identifier): return 'LOT_NONE' if ptype in override_types: @@ -291,22 +262,10 @@ def translate_type_to_lua(ptype): return '`number`', None return '`integer`', None - if ptype == 'char': + if ptype in ('char', 'int', 'lua_Integer'): return '`integer`', None - if ptype == 'int': - return '`integer`', None - - if ptype == 'lua_Integer': - return '`integer`', None - - if ptype == 'float': - return '`number`', None - - if ptype == 'lua_Number': - return '`number`', None - - if ptype == 'double': + if ptype in ('float', 'lua_Number', 'double'): return '`number`', None if ptype == 'bool': @@ -324,6 +283,9 @@ def translate_type_to_lua(ptype): if ptype == cobject_function_identifier: return cobject_function_identifier, None + if ptype == cobject_property_identifier: + return cobject_property_identifier, None + if ptype.count('*') == 1 and '???' not in translate_type_to_lvt(ptype): ptype = ptype.replace('const', '').replace('*', '').strip() s = '`Pointer` <`%s`>' % translate_type_to_lua(ptype)[0].replace('`', '').strip() diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 3a88390ec..4c6f37b7a 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -264,10 +264,17 @@ def table_to_string(table): for row in table: for i in range(columns): - if '#' in row[i]: + if '#' in row[i] or row[i][-1] == '\\': continue if len(row[i]) > column_width[i]: column_width[i] = len(row[i]) + + for row in table: + for i in range(columns): + if row[i][-1] == '\\': + row[i] = row[i][:-1] + row[i+1] = row[i][column_width[i]:] + row[i+1] + row[i] = row[i][:column_width[i]] s = '' for row in table: @@ -327,12 +334,21 @@ def parse_struct(struct_str, sortFields = False): # handle function members if field['type'].startswith(cobject_function_identifier): - field_function = field['identifier'] field_type, field_id = field['type'].split() + field_function = field['identifier'] field['type'] = field_type.strip() - field['identifier'] = field_id.strip('"').strip() + field['identifier'] = field_id.strip() field['function'] = field_function.strip() + # handle property members + if field['type'].startswith(cobject_property_identifier): + field_type, field_id, field_get = field['type'].split() + field_set = field['identifier'] + field['type'] = field_type.strip() + field['identifier'] = field_id.strip() + field['get'] = field_get.strip() + field['set'] = field_set.strip() + struct['fields'].append(field) if identifier == 'Object': @@ -496,9 +512,6 @@ def get_struct_field_info(struct, field): if fid in override_field_mutable[sid] or '*' in override_field_mutable[sid]: fimmutable = 'false' - if ftype == cobject_function_identifier: - fimmutable = 'true' - if not ('char' in ftype and '[' in ftype and 'unsigned' not in ftype): array_match = re.search(r'\[([^\]]+)\]', ftype) if array_match: @@ -549,27 +562,24 @@ def build_struct(struct): startStr += '#ifndef ' + override_field_version_excludes[fid] + '\n' endStr += '\n#endif' startStr += ' { ' - if ftype == cobject_function_identifier: - row.append(startStr ) - row.append('"%s", ' % fid ) - row.append('%s, ' % lvt ) - row.append('(size_t) "%s", ' % field['function']) - row.append('%s, ' % fimmutable ) - row.append('%s, ' % lot ) - row.append('%s, ' % size ) - row.append('sizeof(const char *)' ) - row.append(endStr ) - field_functions.append(field['function']) + row.append(startStr) + row.append('"%s", ' % fid) + row.append('%s, ' % lvt) + if field.get('function'): + row.append('.function = "%s"\\' % field['function']) + elif field.get('get'): + row.append('.get = "%s", ' % field['get']) + row.append('.set = "%s"\\' % field['set']) else: - row.append(startStr ) - row.append('"%s", ' % fid ) - row.append('%s, ' % lvt ) row.append('offsetof(%s%s, %s), ' % (struct_str, name, field['identifier'])) - row.append('%s, ' % fimmutable ) - row.append('%s, ' % lot ) - row.append('%s, ' % size ) - row.append('sizeof(%s)' % ftype ) - row.append(endStr ) + row.append('%s, ' % fimmutable) + row.append('%s, ' % lot ) + row.append('%s, ' % size ) + row.append('sizeof(%s)' % ftype ) + row.extend(['\\'] * (8 - len(row))) + row.append(endStr) + if field.get('function'): + field_functions.append(field['function']) field_table.append(row) field_table_str, field_count = table_to_string(field_table) @@ -726,6 +736,10 @@ def doc_struct_field(struct, field): flink = doc_find_function_link(field['function']) return '| %s | [`%s`](%s) |\n' % (fid, field['function'], flink), True + if ftype == cobject_property_identifier: + ftype = get_function_signature(field['get']) + ftype = f"`{ftype[ftype.rfind(':')+2:]}`" + restrictions = ('', 'read-only')[fimmutable == 'true'] global total_fields @@ -854,6 +868,9 @@ def def_struct(struct): # try to get the function signature if ftype == cobject_function_identifier: ftype = get_function_signature(field['function']) + elif ftype == cobject_property_identifier: + ftype = get_function_signature(field['get']) + ftype = f"{ftype[ftype.rfind(':')+2:]}" else: ftype = translate_to_def(ftype) diff --git a/autogen/extract_structs.py b/autogen/extract_structs.py index 5fb06c5ef..b57e96850 100644 --- a/autogen/extract_structs.py +++ b/autogen/extract_structs.py @@ -1,7 +1,7 @@ import os import re import sys -from common import cobject_function_identifier +from common import cobject_function_identifier, cobject_property_identifier def extract_structs(filename): with open(filename) as file: @@ -38,7 +38,10 @@ def extract_structs(filename): txt = txt.replace(' ', ' ') # handle function members (NOT function pointers) - txt = re.sub(f'{cobject_function_identifier}\\((.*),(.*)\\)', f'{cobject_function_identifier} \\1 \\2', txt) + txt = re.sub(f'{cobject_function_identifier}\\((.*),(.*)\\)', f'{cobject_function_identifier} \\1\\2', txt) + + # handle property members + txt = re.sub(f'{cobject_property_identifier}\\((.*),(.*),(.*)\\)', f'{cobject_property_identifier} \\1\\2\\3', txt) # strip macros txt = re.sub(r'[^a-zA-Z0-9_][A-Z0-9_]+\(.*\)', '', txt) diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index c971ce2ff..dca13a197 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1207,6 +1207,10 @@ --- @field public isStream boolean --- @field public baseVolume number --- @field public loaded boolean +--- @field public position number +--- @field public looping boolean +--- @field public frequency number +--- @field public volume number --- @class ModFs --- @field public mod Mod diff --git a/docs/lua/structs.md b/docs/lua/structs.md index f189b286d..d902f0837 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1763,6 +1763,10 @@ | isStream | `boolean` | read-only | | baseVolume | `number` | | | loaded | `boolean` | read-only | +| position | `number` | | +| looping | `boolean` | | +| frequency | `number` | | +| volume | `number` | | [:arrow_up_small:](#) diff --git a/src/pc/lua/smlua_autogen.h b/src/pc/lua/smlua_autogen.h index 5373e3972..08dd61f18 100644 --- a/src/pc/lua/smlua_autogen.h +++ b/src/pc/lua/smlua_autogen.h @@ -21,6 +21,12 @@ // Optional parameters must be contiguous until the last parameter (a mandatory parameter following an optional parameter is not allowed) #define OPTIONAL +/* A macro to tell autogen the field `name` is a property member of the struct that calls `get` or `set` accessors + - get: fun(self) -> value + - set: fun(self, value) +*/ +#define PROPERTY(name, get, set) + // A macro to tell autogen the field `name` is a function member of the struct that calls `c_function` #define FUNCTION(name, c_function) diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c index 104c02074..7f60cdbca 100644 --- a/src/pc/lua/smlua_cobject.c +++ b/src/pc/lua/smlua_cobject.c @@ -101,6 +101,7 @@ static const char *sLuaLvtNames[] = { [LVT_LUATABLE] = "LuaTable", [LVT_POINTER] = "pointer", [LVT_FUNCTION] = "function", + [LVT_PROPERTY] = "property", [LVT_MAX] = "unknown", }; @@ -553,8 +554,16 @@ static int smlua__get_field(lua_State* L) { // CObject function members if (data->valueType == LVT_FUNCTION) { - const char *function = (const char *) data->valueOffset; - lua_getglobal(L, function); + lua_getglobal(L, data->function); + LUA_STACK_CHECK_END(L); + return 1; + } + + // CObject property + if (data->valueType == LVT_PROPERTY) {; + lua_getglobal(L, data->get); + lua_pushvalue(L, 1); + smlua_pcall(L, 1, 1, 0); LUA_STACK_CHECK_END(L); return 1; } @@ -634,7 +643,17 @@ static int smlua__set_field(lua_State* L) { return 0; } - if (data->immutable) { + // CObject property + if (data->valueType == LVT_PROPERTY) { + lua_getglobal(L, data->set); + lua_pushvalue(L, 1); + lua_pushvalue(L, 3); + smlua_pcall(L, 2, 1, 0); + LUA_STACK_CHECK_END(L); + return 1; + } + + if (data->immutable || data->valueType == LVT_FUNCTION) { LOG_LUA_LINE("_set_field on immutable key '%s'", key); return 0; } diff --git a/src/pc/lua/smlua_cobject.h b/src/pc/lua/smlua_cobject.h index 83cac836d..905cfa80e 100644 --- a/src/pc/lua/smlua_cobject.h +++ b/src/pc/lua/smlua_cobject.h @@ -36,17 +36,27 @@ enum LuaValueType { LVT_LUATABLE, LVT_POINTER, LVT_FUNCTION, + LVT_PROPERTY, LVT_MAX, }; struct LuaObjectField { const char* key; enum LuaValueType valueType; - size_t valueOffset; - bool immutable; - u16 lot; - u16 count; - u32 size; + union { + struct { + size_t valueOffset; + bool immutable; + u16 lot; + u16 count; + u32 size; + }; + const char* function; + struct { + const char* get; + const char* set; + }; + }; }; struct LuaObjectTable { diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index e2cbf87ea..03bb49f8c 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -1492,60 +1492,64 @@ static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = { { "size", LVT_U64, offsetof(struct Mod, size), true, LOT_NONE, 1, sizeof(size_t) }, }; -#define LUA_MOD_AUDIO_FIELD_COUNT 4 +#define LUA_MOD_AUDIO_FIELD_COUNT 8 static struct LuaObjectField sModAudioFields[LUA_MOD_AUDIO_FIELD_COUNT] = { { "baseVolume", LVT_F32, offsetof(struct ModAudio, baseVolume), false, LOT_NONE, 1, sizeof(f32) }, { "filepath", LVT_STRING_P, offsetof(struct ModAudio, filepath), true, LOT_NONE, 1, sizeof(const char*) }, + { "frequency", LVT_PROPERTY, .get = "audio_stream_get_frequency", .set = "audio_stream_set_frequency" }, { "isStream", LVT_BOOL, offsetof(struct ModAudio, isStream), true, LOT_NONE, 1, sizeof(bool) }, { "loaded", LVT_BOOL, offsetof(struct ModAudio, loaded), true, LOT_NONE, 1, sizeof(bool) }, + { "looping", LVT_PROPERTY, .get = "audio_stream_get_looping", .set = "audio_stream_set_looping" }, + { "position", LVT_PROPERTY, .get = "audio_stream_get_position", .set = "audio_stream_set_position" }, + { "volume", LVT_PROPERTY, .get = "audio_stream_get_volume", .set = "audio_stream_set_volume" }, }; #define LUA_MOD_FS_FIELD_COUNT 15 static struct LuaObjectField sModFsFields[LUA_MOD_FS_FIELD_COUNT] = { - { "clear", LVT_FUNCTION, (size_t) "mod_fs_clear", true, LOT_NONE, 1, sizeof(const char *) }, - { "copy_file", LVT_FUNCTION, (size_t) "mod_fs_copy_file", true, LOT_NONE, 1, sizeof(const char *) }, - { "create_file", LVT_FUNCTION, (size_t) "mod_fs_create_file", true, LOT_NONE, 1, sizeof(const char *) }, - { "delete", LVT_FUNCTION, (size_t) "mod_fs_delete", true, LOT_NONE, 1, sizeof(const char *) }, - { "delete_file", LVT_FUNCTION, (size_t) "mod_fs_delete_file", true, LOT_NONE, 1, sizeof(const char *) }, - { "get_file", LVT_FUNCTION, (size_t) "mod_fs_get_file", true, LOT_NONE, 1, sizeof(const char *) }, - { "get_filename", LVT_FUNCTION, (size_t) "mod_fs_get_filename", true, LOT_NONE, 1, sizeof(const char *) }, - { "isPublic", LVT_BOOL, offsetof(struct ModFs, isPublic), true, LOT_NONE, 1, sizeof(bool) }, - { "mod", LVT_COBJECT_P, offsetof(struct ModFs, mod), true, LOT_MOD, 1, sizeof(struct Mod*) }, - { "modPath", LVT_STRING, offsetof(struct ModFs, modPath), true, LOT_NONE, 1, sizeof(char) }, - { "move_file", LVT_FUNCTION, (size_t) "mod_fs_move_file", true, LOT_NONE, 1, sizeof(const char *) }, - { "numFiles", LVT_U16, offsetof(struct ModFs, numFiles), true, LOT_NONE, 1, sizeof(u16) }, - { "save", LVT_FUNCTION, (size_t) "mod_fs_save", true, LOT_NONE, 1, sizeof(const char *) }, - { "set_public", LVT_FUNCTION, (size_t) "mod_fs_set_public", true, LOT_NONE, 1, sizeof(const char *) }, - { "totalSize", LVT_U32, offsetof(struct ModFs, totalSize), true, LOT_NONE, 1, sizeof(u32) }, + { "clear", LVT_FUNCTION, .function = "mod_fs_clear" }, + { "copy_file", LVT_FUNCTION, .function = "mod_fs_copy_file" }, + { "create_file", LVT_FUNCTION, .function = "mod_fs_create_file" }, + { "delete", LVT_FUNCTION, .function = "mod_fs_delete" }, + { "delete_file", LVT_FUNCTION, .function = "mod_fs_delete_file" }, + { "get_file", LVT_FUNCTION, .function = "mod_fs_get_file" }, + { "get_filename", LVT_FUNCTION, .function = "mod_fs_get_filename" }, + { "isPublic", LVT_BOOL, offsetof(struct ModFs, isPublic), true, LOT_NONE, 1, sizeof(bool) }, + { "mod", LVT_COBJECT_P, offsetof(struct ModFs, mod), true, LOT_MOD, 1, sizeof(struct Mod*) }, + { "modPath", LVT_STRING, offsetof(struct ModFs, modPath), true, LOT_NONE, 1, sizeof(char) }, + { "move_file", LVT_FUNCTION, .function = "mod_fs_move_file" }, + { "numFiles", LVT_U16, offsetof(struct ModFs, numFiles), true, LOT_NONE, 1, sizeof(u16) }, + { "save", LVT_FUNCTION, .function = "mod_fs_save" }, + { "set_public", LVT_FUNCTION, .function = "mod_fs_set_public" }, + { "totalSize", LVT_U32, offsetof(struct ModFs, totalSize), true, LOT_NONE, 1, sizeof(u32) }, }; #define LUA_MOD_FS_FILE_FIELD_COUNT 25 static struct LuaObjectField sModFsFileFields[LUA_MOD_FS_FILE_FIELD_COUNT] = { - { "erase", LVT_FUNCTION, (size_t) "mod_fs_file_erase", true, LOT_NONE, 1, sizeof(const char *) }, + { "erase", LVT_FUNCTION, .function = "mod_fs_file_erase" }, { "filepath", LVT_STRING, offsetof(struct ModFsFile, filepath), true, LOT_NONE, 1, sizeof(char) }, - { "fill", LVT_FUNCTION, (size_t) "mod_fs_file_fill", true, LOT_NONE, 1, sizeof(const char *) }, + { "fill", LVT_FUNCTION, .function = "mod_fs_file_fill" }, { "isPublic", LVT_BOOL, offsetof(struct ModFsFile, isPublic), true, LOT_NONE, 1, sizeof(bool) }, { "isText", LVT_BOOL, offsetof(struct ModFsFile, isText), true, LOT_NONE, 1, sizeof(bool) }, - { "is_eof", LVT_FUNCTION, (size_t) "mod_fs_file_is_eof", true, LOT_NONE, 1, sizeof(const char *) }, + { "is_eof", LVT_FUNCTION, .function = "mod_fs_file_is_eof" }, { "modFs", LVT_COBJECT_P, offsetof(struct ModFsFile, modFs), true, LOT_MODFS, 1, sizeof(struct ModFs*) }, { "offset", LVT_U32, offsetof(struct ModFsFile, offset), true, LOT_NONE, 1, sizeof(u32) }, - { "read_bool", LVT_FUNCTION, (size_t) "mod_fs_file_read_bool", true, LOT_NONE, 1, sizeof(const char *) }, - { "read_bytes", LVT_FUNCTION, (size_t) "mod_fs_file_read_bytes", true, LOT_NONE, 1, sizeof(const char *) }, - { "read_integer", LVT_FUNCTION, (size_t) "mod_fs_file_read_integer", true, LOT_NONE, 1, sizeof(const char *) }, - { "read_line", LVT_FUNCTION, (size_t) "mod_fs_file_read_line", true, LOT_NONE, 1, sizeof(const char *) }, - { "read_number", LVT_FUNCTION, (size_t) "mod_fs_file_read_number", true, LOT_NONE, 1, sizeof(const char *) }, - { "read_string", LVT_FUNCTION, (size_t) "mod_fs_file_read_string", true, LOT_NONE, 1, sizeof(const char *) }, - { "rewind", LVT_FUNCTION, (size_t) "mod_fs_file_rewind", true, LOT_NONE, 1, sizeof(const char *) }, - { "seek", LVT_FUNCTION, (size_t) "mod_fs_file_seek", true, LOT_NONE, 1, sizeof(const char *) }, - { "set_public", LVT_FUNCTION, (size_t) "mod_fs_file_set_public", true, LOT_NONE, 1, sizeof(const char *) }, - { "set_text_mode", LVT_FUNCTION, (size_t) "mod_fs_file_set_text_mode", true, LOT_NONE, 1, sizeof(const char *) }, + { "read_bool", LVT_FUNCTION, .function = "mod_fs_file_read_bool" }, + { "read_bytes", LVT_FUNCTION, .function = "mod_fs_file_read_bytes" }, + { "read_integer", LVT_FUNCTION, .function = "mod_fs_file_read_integer" }, + { "read_line", LVT_FUNCTION, .function = "mod_fs_file_read_line" }, + { "read_number", LVT_FUNCTION, .function = "mod_fs_file_read_number" }, + { "read_string", LVT_FUNCTION, .function = "mod_fs_file_read_string" }, + { "rewind", LVT_FUNCTION, .function = "mod_fs_file_rewind" }, + { "seek", LVT_FUNCTION, .function = "mod_fs_file_seek" }, + { "set_public", LVT_FUNCTION, .function = "mod_fs_file_set_public" }, + { "set_text_mode", LVT_FUNCTION, .function = "mod_fs_file_set_text_mode" }, { "size", LVT_U32, offsetof(struct ModFsFile, size), true, LOT_NONE, 1, sizeof(u32) }, - { "write_bool", LVT_FUNCTION, (size_t) "mod_fs_file_write_bool", true, LOT_NONE, 1, sizeof(const char *) }, - { "write_bytes", LVT_FUNCTION, (size_t) "mod_fs_file_write_bytes", true, LOT_NONE, 1, sizeof(const char *) }, - { "write_integer", LVT_FUNCTION, (size_t) "mod_fs_file_write_integer", true, LOT_NONE, 1, sizeof(const char *) }, - { "write_line", LVT_FUNCTION, (size_t) "mod_fs_file_write_line", true, LOT_NONE, 1, sizeof(const char *) }, - { "write_number", LVT_FUNCTION, (size_t) "mod_fs_file_write_number", true, LOT_NONE, 1, sizeof(const char *) }, - { "write_string", LVT_FUNCTION, (size_t) "mod_fs_file_write_string", true, LOT_NONE, 1, sizeof(const char *) }, + { "write_bool", LVT_FUNCTION, .function = "mod_fs_file_write_bool" }, + { "write_bytes", LVT_FUNCTION, .function = "mod_fs_file_write_bytes" }, + { "write_integer", LVT_FUNCTION, .function = "mod_fs_file_write_integer" }, + { "write_line", LVT_FUNCTION, .function = "mod_fs_file_write_line" }, + { "write_number", LVT_FUNCTION, .function = "mod_fs_file_write_number" }, + { "write_string", LVT_FUNCTION, .function = "mod_fs_file_write_string" }, }; #define LUA_NAMETAGS_SETTINGS_FIELD_COUNT 2 diff --git a/src/pc/lua/utils/smlua_audio_utils.h b/src/pc/lua/utils/smlua_audio_utils.h index deca8b0d0..715ad7a3b 100644 --- a/src/pc/lua/utils/smlua_audio_utils.h +++ b/src/pc/lua/utils/smlua_audio_utils.h @@ -31,6 +31,11 @@ struct ModAudio { bool isStream; f32 baseVolume; bool loaded; + + PROPERTY(position, audio_stream_get_position, audio_stream_set_position); + PROPERTY(looping, audio_stream_get_looping, audio_stream_set_looping); + PROPERTY(frequency, audio_stream_get_frequency, audio_stream_set_frequency); + PROPERTY(volume, audio_stream_get_volume, audio_stream_set_volume); }; /* |description|Loads an `audio` stream by `filename` (with extension)|descriptionEnd| */