diff --git a/.gitignore b/.gitignore
index 50b9bf70..0f5f4c4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,3 +36,4 @@ stage/
# Editors
.vscode
+*.code-workspace
diff --git a/gen_all_definitions.sh b/gen_all_definitions.sh
index 734fac85..241b889f 100755
--- a/gen_all_definitions.sh
+++ b/gen_all_definitions.sh
@@ -7,7 +7,7 @@ mkdir -p "$outdir" "$outdir/cpp" "$outdir/templated" "$outdir/experimental" "$ou
DEFS="./lsl_definitions.yaml"
SLUA="./slua_definitions.yaml"
-CMD="python gen_definitions.py"
+CMD="$(command -v python3 || command -v python) gen_definitions.py"
# Viewer outputs
$CMD $DEFS syntax "$outdir/lsl_keywords.xml"
@@ -33,6 +33,7 @@ $CMD $DEFS gen_lscript_interface "$outdir/cpp/lscript_interface.cpp"
$CMD $DEFS gen_mono_bind_interfaces "$outdir/cpp/mono_bind_interfaces.cpp"
$CMD $DEFS gen_lua_registrations 1 "$outdir/cpp/lua_registrations.cpp"
$CMD $DEFS gen_lua_constant_definitions "$outdir/cpp/lua_constant_definitions.cpp"
+$CMD $DEFS gen_fluent_builder_descriptors "$outdir/cpp/fluent_builder_descriptors.cpp"
$CMD $DEFS gen_lscript_library_bind_pure "$outdir/cpp/lscript_library_bind_pure.cpp"
$CMD $DEFS gen_tree_header_file "$outdir/cpp/lscript_tree.h"
$CMD $DEFS gen_tree_source_file "$outdir/cpp/lscript_tree.cpp"
diff --git a/generated/cpp/fluent_builder_descriptors.cpp b/generated/cpp/fluent_builder_descriptors.cpp
new file mode 100644
index 00000000..53eb671a
--- /dev/null
+++ b/generated/cpp/fluent_builder_descriptors.cpp
@@ -0,0 +1,123 @@
+// http-params
+static const FluentParamDescriptor kHTTPRequestParamsDescs[] = {
+ {"method", 's', 0},
+ {"mimetype", 's', 1},
+ {"body_maxlength", 'i', 2},
+ {"verify_cert", 'b', 3},
+ {"verbose_throttle", 'b', 4},
+ {"custom_header", 'M', 5},
+ {"pragma_no_cache", 'b', 6},
+ {"user_agent", 's', 7},
+ {"accept", 'N', 8},
+ {"extended_error", 'b', 9},
+};
+static FluentBuilderDef* kHTTPRequestParamsDef = fluent_builder_def_build(kHTTPRequestParamsDescs, std::size(kHTTPRequestParamsDescs));
+auto request = [](lua_State* L) -> int {
+ const auto* def = (const FluentBuilderDef*)lua_tolightuserdata(L, lua_upvalueindex(1));
+ slua_fluent_serialize(L, 2, def);
+ int rules_idx = lua_gettop(L);
+ lua_rawgetfield(L, LUA_BASEGLOBALSINDEX, "ll");
+ lua_rawgetfield(L, -1, "HTTPRequest");
+ lua_pushvalue(L, 1);
+ lua_pushvalue(L, rules_idx);
+ if (lua_isnoneornil(L, 3)) lua_pushliteral(L, ""); else lua_pushvalue(L, 3);
+ lua_call(L, 3, 1);
+ return 1;
+};
+slua_register_fluent_fn(L, "llhttp", "request", request, kHTTPRequestParamsDef);
+
+// particle-params
+static const FluentParamDescriptor kParticleParamsDescs[] = {
+ {"flags", 'i', 0},
+ {"color_begin", 'v', 1},
+ {"alpha_begin", 'f', 2},
+ {"color_end", 'v', 3},
+ {"alpha_end", 'f', 4},
+ {"scale_begin", 'v', 5},
+ {"scale_end", 'v', 6},
+ {"part_max_age", 'f', 7},
+ {"accel", 'v', 8},
+ {"pattern", 'i', 9},
+ {"angle_inner", 'f', 10},
+ {"angle_outer", 'f', 11},
+ {"texture", 'a', 12},
+ {"burst_rate", 'f', 13},
+ {"burst_count", 'i', 15},
+ {"burst_radius", 'f', 16},
+ {"burst_speed_min", 'f', 17},
+ {"burst_speed_max", 'f', 18},
+ {"src_max_age", 'f', 19},
+ {"target_key", 'k', 20},
+ {"omega", 'v', 21},
+ {"angle_begin", 'f', 22},
+ {"angle_end", 'f', 23},
+ {"blend_func_source", 'i', 24},
+ {"blend_func_dest", 'i', 25},
+ {"glow_begin", 'f', 26},
+ {"glow_end", 'f', 27},
+};
+static const FluentFlagDescriptor kParticleParamFlagDescs[] = {
+ {"color_interp", 0x1, 0},
+ {"scale_interp", 0x2, 0},
+ {"bounce", 0x4, 0},
+ {"wind", 0x8, 0},
+ {"follow", 0x10, 0},
+ {"follow_velocity", 0x20, 0},
+ {"target_pos", 0x40, 0},
+ {"target_linear", 0x80, 0},
+ {"emissive", 0x100, 0},
+ {"ribbon", 0x400, 0},
+};
+static FluentBuilderDef* kParticleParamsDef = []() {
+ auto* d = fluent_builder_def_build(kParticleParamsDescs, std::size(kParticleParamsDescs));
+ fluent_builder_def_add_flags(d, kParticleParamFlagDescs, std::size(kParticleParamFlagDescs));
+ return d;
+}();
+auto particle_system = [](lua_State* L) -> int {
+ const auto* def = (const FluentBuilderDef*)lua_tolightuserdata(L, lua_upvalueindex(1));
+ int link = lua_isnoneornil(L, 2) ? SLUA_LINK_THIS : luaL_checkinteger(L, 2);
+ slua_fluent_serialize(L, 1, def);
+ int rules_idx = lua_gettop(L);
+ lua_rawgetfield(L, LUA_BASEGLOBALSINDEX, "ll");
+ lua_rawgetfield(L, -1, "LinkParticleSystem");
+ lua_pushinteger(L, link);
+ lua_pushvalue(L, rules_idx);
+ lua_call(L, 2, 0);
+ return 0;
+};
+slua_register_fluent_fn(L, "llprim", "particleSystem", particle_system, kParticleParamsDef);
+
+// prim-media-params
+static const FluentParamDescriptor kPrimMediaParamsDescs[] = {
+ {"alt_image_enable", 'b', 0},
+ {"controls", 'i', 1},
+ {"current_url", 's', 2},
+ {"home_url", 's', 3},
+ {"auto_loop", 'b', 4},
+ {"auto_play", 'b', 5},
+ {"auto_scale", 'b', 6},
+ {"auto_zoom", 'b', 7},
+ {"first_click_interact", 'b', 8},
+ {"width_pixels", 'i', 9},
+ {"height_pixels", 'i', 10},
+ {"whitelist_enable", 'b', 11},
+ {"whitelist", 'C', 12},
+ {"perms_interact", 'i', 13},
+ {"perms_control", 'i', 14},
+};
+static FluentBuilderDef* kPrimMediaParamsDef = fluent_builder_def_build(kPrimMediaParamsDescs, std::size(kPrimMediaParamsDescs));
+auto set_media = [](lua_State* L) -> int {
+ const auto* def = (const FluentBuilderDef*)lua_tolightuserdata(L, lua_upvalueindex(1));
+ int face = luaL_checkinteger(L, 1);
+ int link = lua_isnoneornil(L, 3) ? SLUA_LINK_THIS : luaL_checkinteger(L, 3);
+ slua_fluent_serialize(L, 2, def);
+ int rules_idx = lua_gettop(L);
+ lua_rawgetfield(L, LUA_BASEGLOBALSINDEX, "ll");
+ lua_rawgetfield(L, -1, "SetLinkMedia");
+ lua_pushinteger(L, link);
+ lua_pushinteger(L, face);
+ lua_pushvalue(L, rules_idx);
+ lua_call(L, 3, 1);
+ return 1;
+};
+slua_register_fluent_fn(L, "llprim", "setMedia", set_media, kPrimMediaParamsDef);
\ No newline at end of file
diff --git a/generated/experimental/enums.txt b/generated/experimental/enums.txt
index f4122b62..27e3f4f4 100644
--- a/generated/experimental/enums.txt
+++ b/generated/experimental/enums.txt
@@ -814,11 +814,11 @@ enum ParticleParam {
PART_END_GLOW = 27
};
enum ParticleSourcePattern {
- DROP = 0x1
- EXPLODE = 0x2
- ANGLE = 0x4
- ANGLE_CONE = 0x8
- ANGLE_CONE_EMPTY = 0x10
+ DROP = 1
+ EXPLODE = 2
+ ANGLE = 4
+ ANGLE_CONE = 8
+ ANGLE_CONE_EMPTY = 16
};
enum PassMode {
IF_NOT_HANDLED = 0
diff --git a/generated/lsl_keywords_pretty.xml b/generated/lsl_keywords_pretty.xml
index 2f1fbbc4..d2c10a18 100644
--- a/generated/lsl_keywords_pretty.xml
+++ b/generated/lsl_keywords_pretty.xml
@@ -2470,7 +2470,7 @@ This file is auto-generated by https://github.com/secondlife/lsl-definitions. --
HTTP_CUSTOM_HEADER