From ab49c33d86f55d0023b1c46bfcf3a49233ff5985 Mon Sep 17 00:00:00 2001
From: Agent X <44549182+AgentXLP@users.noreply.github.com>
Date: Fri, 14 Mar 2025 22:25:47 -0400
Subject: [PATCH] Expose some cool math functions
---
autogen/common.py | 2 +-
autogen/convert_functions.py | 4 +-
autogen/lua_definitions/functions.lua | 63 +++++++++
docs/lua/functions-4.md | 190 ++++++++++++++++++++++++++
docs/lua/functions.md | 8 ++
src/pc/djui/djui_panel.c | 4 +-
src/pc/lua/smlua_functions_autogen.c | 186 +++++++++++++++++++++++++
src/pc/utils/misc.c | 6 +-
src/pc/utils/misc.h | 12 +-
9 files changed, 465 insertions(+), 10 deletions(-)
diff --git a/autogen/common.py b/autogen/common.py
index b53a56595..e0380f275 100644
--- a/autogen/common.py
+++ b/autogen/common.py
@@ -2,7 +2,7 @@ import os
import re
from vec_types import *
-usf_types = ['u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'f32']
+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']
diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py
index e545b8618..8bbc48fa1 100644
--- a/autogen/convert_functions.py
+++ b/autogen/convert_functions.py
@@ -83,7 +83,6 @@ override_allowed_functions = {
"src/pc/lua/utils/smlua_model_utils.h": [ "smlua_model_util_get_id" ],
"src/game/object_list_processor.h": [ "set_object_respawn_info_bits" ],
"src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*", "geo_get_.*_state" ],
- "src/pc/utils/misc.h": [ "update_all_mario_stars" ],
"src/game/level_update.h": [ "level_trigger_warp", "get_painting_warp_node", "initiate_painting_warp", "warp_special", "lvl_set_current_level", "level_control_timer_running", "fade_into_special_warp", "get_instant_warp" ],
"src/game/area.h": [ "area_get_warp_node" ],
"src/engine/level_script.h": [ "area_create_warp_node" ],
@@ -126,7 +125,8 @@ override_disallowed_functions = {
"src/pc/network/lag_compensation.h": [ "lag_compensation_clear" ],
"src/game/first_person_cam.h": [ "first_person_update" ],
"src/pc/lua/utils/smlua_collision_utils.h": [ "collision_find_surface_on_ray" ],
- "src/engine/behavior_script.h": [ "stub_behavior_script_2", "cur_obj_update" ]
+ "src/engine/behavior_script.h": [ "stub_behavior_script_2", "cur_obj_update" ],
+ "src/pc/utils/misc.h": [ "str_.*", "file_get_line", "delta_interpolate_(normal|rgba|mtx)", "detect_and_skip_mtx_interpolation" ]
}
override_hide_functions = {
diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index ed9a7f276..bfdee94fc 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -6428,6 +6428,69 @@ function vec3s_to_vec3f(dest, a)
-- ...
end
+--- @return number
+--- Gets the current clock elapsed time
+function clock_elapsed()
+ -- ...
+end
+
+--- @return number
+--- Gets the current clock elapsed time with double precision
+function clock_elapsed_f64()
+ -- ...
+end
+
+--- @return integer
+--- Gets the current clock elapsed time in frames
+function clock_elapsed_ticks()
+ -- ...
+end
+
+--- @param a number
+--- @param b number
+--- @param delta number
+--- @return number
+--- Linearly interpolates between `a` and `b` with `delta`
+function delta_interpolate_f32(a, b, delta)
+ -- ...
+end
+
+--- @param a integer
+--- @param b integer
+--- @param delta number
+--- @return integer
+--- Linearly interpolates between `a` and `b` with `delta`
+function delta_interpolate_s32(a, b, delta)
+ -- ...
+end
+
+--- @param res Vec3f
+--- @param a Vec3f
+--- @param b Vec3f
+--- @param delta number
+--- Linearly interpolates `res` between `a` and `b` with `delta`
+function delta_interpolate_vec3f(res, a, b, delta)
+ -- ...
+end
+
+--- @param res Vec3s
+--- @param a Vec3s
+--- @param b Vec3s
+--- @param delta number
+--- Linearly interpolates `res` between `a` and `b` with `delta`
+function delta_interpolate_vec3s(res, a, b, delta)
+ -- ...
+end
+
+--- @param edge0 number
+--- @param edge1 number
+--- @param x number
+--- @return number
+--- Smoothly steps between `edge0` and `edge1` with `x` as delta
+function smooth_step(edge0, edge1, x)
+ -- ...
+end
+
--- Updates every Mario state's star count with the save file total star count
function update_all_mario_stars()
-- ...
diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md
index d82abe843..1da6936e6 100644
--- a/docs/lua/functions-4.md
+++ b/docs/lua/functions-4.md
@@ -5180,6 +5180,196 @@ Converts a 3D signed-integer vector `a` (vec3s) into a 3D floating-point vector
+## [clock_elapsed](#clock_elapsed)
+
+### Description
+Gets the current clock elapsed time
+
+### Lua Example
+`local numberValue = clock_elapsed()`
+
+### Parameters
+- None
+
+### Returns
+- `number`
+
+### C Prototype
+`f32 clock_elapsed(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [clock_elapsed_f64](#clock_elapsed_f64)
+
+### Description
+Gets the current clock elapsed time with double precision
+
+### Lua Example
+`local numberValue = clock_elapsed_f64()`
+
+### Parameters
+- None
+
+### Returns
+- `number`
+
+### C Prototype
+`f64 clock_elapsed_f64(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [clock_elapsed_ticks](#clock_elapsed_ticks)
+
+### Description
+Gets the current clock elapsed time in frames
+
+### Lua Example
+`local integerValue = clock_elapsed_ticks()`
+
+### Parameters
+- None
+
+### Returns
+- `integer`
+
+### C Prototype
+`u32 clock_elapsed_ticks(void);`
+
+[:arrow_up_small:](#)
+
+
+
+## [delta_interpolate_f32](#delta_interpolate_f32)
+
+### Description
+Linearly interpolates between `a` and `b` with `delta`
+
+### Lua Example
+`local numberValue = delta_interpolate_f32(a, b, delta)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| a | `number` |
+| b | `number` |
+| delta | `number` |
+
+### Returns
+- `number`
+
+### C Prototype
+`f32 delta_interpolate_f32(f32 a, f32 b, f32 delta);`
+
+[:arrow_up_small:](#)
+
+
+
+## [delta_interpolate_s32](#delta_interpolate_s32)
+
+### Description
+Linearly interpolates between `a` and `b` with `delta`
+
+### Lua Example
+`local integerValue = delta_interpolate_s32(a, b, delta)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| a | `integer` |
+| b | `integer` |
+| delta | `number` |
+
+### Returns
+- `integer`
+
+### C Prototype
+`s32 delta_interpolate_s32(s32 a, s32 b, f32 delta);`
+
+[:arrow_up_small:](#)
+
+
+
+## [delta_interpolate_vec3f](#delta_interpolate_vec3f)
+
+### Description
+Linearly interpolates `res` between `a` and `b` with `delta`
+
+### Lua Example
+`delta_interpolate_vec3f(res, a, b, delta)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| res | [Vec3f](structs.md#Vec3f) |
+| a | [Vec3f](structs.md#Vec3f) |
+| b | [Vec3f](structs.md#Vec3f) |
+| delta | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void delta_interpolate_vec3f(Vec3f res, Vec3f a, Vec3f b, f32 delta);`
+
+[:arrow_up_small:](#)
+
+
+
+## [delta_interpolate_vec3s](#delta_interpolate_vec3s)
+
+### Description
+Linearly interpolates `res` between `a` and `b` with `delta`
+
+### Lua Example
+`delta_interpolate_vec3s(res, a, b, delta)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| res | [Vec3s](structs.md#Vec3s) |
+| a | [Vec3s](structs.md#Vec3s) |
+| b | [Vec3s](structs.md#Vec3s) |
+| delta | `number` |
+
+### Returns
+- None
+
+### C Prototype
+`void delta_interpolate_vec3s(Vec3s res, Vec3s a, Vec3s b, f32 delta);`
+
+[:arrow_up_small:](#)
+
+
+
+## [smooth_step](#smooth_step)
+
+### Description
+Smoothly steps between `edge0` and `edge1` with `x` as delta
+
+### Lua Example
+`local numberValue = smooth_step(edge0, edge1, x)`
+
+### Parameters
+| Field | Type |
+| ----- | ---- |
+| edge0 | `number` |
+| edge1 | `number` |
+| x | `number` |
+
+### Returns
+- `number`
+
+### C Prototype
+`float smooth_step(float edge0, float edge1, float x);`
+
+[:arrow_up_small:](#)
+
+
+
## [update_all_mario_stars](#update_all_mario_stars)
### Description
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index a0ecb56fc..b731f6c13 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -1207,6 +1207,14 @@
- misc.h
+ - [clock_elapsed](functions-4.md#clock_elapsed)
+ - [clock_elapsed_f64](functions-4.md#clock_elapsed_f64)
+ - [clock_elapsed_ticks](functions-4.md#clock_elapsed_ticks)
+ - [delta_interpolate_f32](functions-4.md#delta_interpolate_f32)
+ - [delta_interpolate_s32](functions-4.md#delta_interpolate_s32)
+ - [delta_interpolate_vec3f](functions-4.md#delta_interpolate_vec3f)
+ - [delta_interpolate_vec3s](functions-4.md#delta_interpolate_vec3s)
+ - [smooth_step](functions-4.md#smooth_step)
- [update_all_mario_stars](functions-4.md#update_all_mario_stars)
diff --git a/src/pc/djui/djui_panel.c b/src/pc/djui/djui_panel.c
index 1d0702993..452a12b3a 100644
--- a/src/pc/djui/djui_panel.c
+++ b/src/pc/djui/djui_panel.c
@@ -180,12 +180,12 @@ void djui_panel_update(void) {
}
if (activeBase && removingBase) {
- activeBase->y.value = moveMax - moveMax * smoothstep(0, moveMax, sMoveAmount);
+ activeBase->y.value = moveMax - moveMax * smooth_step(0, moveMax, sMoveAmount);
if (sPanelRemoving) {
removingBase->y.value = activeBase->y.value - 1.0f;
}
} else if (activeBase && parentBase) {
- activeBase->y.value = moveMax * smoothstep(0, moveMax, sMoveAmount) - moveMax;
+ activeBase->y.value = moveMax * smooth_step(0, moveMax, sMoveAmount) - moveMax;
parentBase->y.value = activeBase->y.value + moveMax;
}
}
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 9984421fc..3d680553e 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -19660,6 +19660,184 @@ int smlua_func_vec3s_to_vec3f(lua_State* L) {
// misc.h //
////////////
+int smlua_func_clock_elapsed(UNUSED lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 0) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "clock_elapsed", 0, top);
+ return 0;
+ }
+
+
+ lua_pushnumber(L, clock_elapsed());
+
+ return 1;
+}
+
+int smlua_func_clock_elapsed_f64(UNUSED lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 0) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "clock_elapsed_f64", 0, top);
+ return 0;
+ }
+
+
+ lua_pushnumber(L, clock_elapsed_f64());
+
+ return 1;
+}
+
+int smlua_func_clock_elapsed_ticks(UNUSED lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 0) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "clock_elapsed_ticks", 0, top);
+ return 0;
+ }
+
+
+ lua_pushinteger(L, clock_elapsed_ticks());
+
+ return 1;
+}
+
+int smlua_func_delta_interpolate_f32(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 3) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "delta_interpolate_f32", 3, top);
+ return 0;
+ }
+
+ f32 a = smlua_to_number(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "delta_interpolate_f32"); return 0; }
+ f32 b = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "delta_interpolate_f32"); return 0; }
+ f32 delta = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "delta_interpolate_f32"); return 0; }
+
+ lua_pushnumber(L, delta_interpolate_f32(a, b, delta));
+
+ return 1;
+}
+
+int smlua_func_delta_interpolate_s32(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 3) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "delta_interpolate_s32", 3, top);
+ return 0;
+ }
+
+ s32 a = smlua_to_integer(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "delta_interpolate_s32"); return 0; }
+ s32 b = smlua_to_integer(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "delta_interpolate_s32"); return 0; }
+ f32 delta = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "delta_interpolate_s32"); return 0; }
+
+ lua_pushinteger(L, delta_interpolate_s32(a, b, delta));
+
+ return 1;
+}
+
+int smlua_func_delta_interpolate_vec3f(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 4) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "delta_interpolate_vec3f", 4, top);
+ return 0;
+ }
+
+
+ Vec3f res;
+ smlua_get_vec3f(res, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "delta_interpolate_vec3f"); return 0; }
+
+ Vec3f a;
+ smlua_get_vec3f(a, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "delta_interpolate_vec3f"); return 0; }
+
+ Vec3f b;
+ smlua_get_vec3f(b, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "delta_interpolate_vec3f"); return 0; }
+ f32 delta = smlua_to_number(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "delta_interpolate_vec3f"); return 0; }
+
+ delta_interpolate_vec3f(res, a, b, delta);
+
+ smlua_push_vec3f(res, 1);
+
+ smlua_push_vec3f(a, 2);
+
+ smlua_push_vec3f(b, 3);
+
+ return 1;
+}
+
+int smlua_func_delta_interpolate_vec3s(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 4) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "delta_interpolate_vec3s", 4, top);
+ return 0;
+ }
+
+
+ Vec3s res;
+ smlua_get_vec3s(res, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "delta_interpolate_vec3s"); return 0; }
+
+ Vec3s a;
+ smlua_get_vec3s(a, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "delta_interpolate_vec3s"); return 0; }
+
+ Vec3s b;
+ smlua_get_vec3s(b, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "delta_interpolate_vec3s"); return 0; }
+ f32 delta = smlua_to_number(L, 4);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "delta_interpolate_vec3s"); return 0; }
+
+ delta_interpolate_vec3s(res, a, b, delta);
+
+ smlua_push_vec3s(res, 1);
+
+ smlua_push_vec3s(a, 2);
+
+ smlua_push_vec3s(b, 3);
+
+ return 1;
+}
+
+int smlua_func_smooth_step(lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 3) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smooth_step", 3, top);
+ return 0;
+ }
+
+ float edge0 = smlua_to_number(L, 1);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smooth_step"); return 0; }
+ float edge1 = smlua_to_number(L, 2);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "smooth_step"); return 0; }
+ float x = smlua_to_number(L, 3);
+ if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "smooth_step"); return 0; }
+
+ lua_pushnumber(L, smooth_step(edge0, edge1, x));
+
+ return 1;
+}
+
int smlua_func_update_all_mario_stars(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
@@ -33613,6 +33791,14 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "vec3s_to_vec3f", smlua_func_vec3s_to_vec3f);
// misc.h
+ smlua_bind_function(L, "clock_elapsed", smlua_func_clock_elapsed);
+ smlua_bind_function(L, "clock_elapsed_f64", smlua_func_clock_elapsed_f64);
+ smlua_bind_function(L, "clock_elapsed_ticks", smlua_func_clock_elapsed_ticks);
+ smlua_bind_function(L, "delta_interpolate_f32", smlua_func_delta_interpolate_f32);
+ smlua_bind_function(L, "delta_interpolate_s32", smlua_func_delta_interpolate_s32);
+ smlua_bind_function(L, "delta_interpolate_vec3f", smlua_func_delta_interpolate_vec3f);
+ smlua_bind_function(L, "delta_interpolate_vec3s", smlua_func_delta_interpolate_vec3s);
+ smlua_bind_function(L, "smooth_step", smlua_func_smooth_step);
smlua_bind_function(L, "update_all_mario_stars", smlua_func_update_all_mario_stars);
// mod_storage.h
diff --git a/src/pc/utils/misc.c b/src/pc/utils/misc.c
index d669e92d6..280f54a97 100644
--- a/src/pc/utils/misc.c
+++ b/src/pc/utils/misc.c
@@ -14,7 +14,7 @@
#include "engine/math_util.h"
#include "pc/configfile.h"
-float smoothstep(float edge0, float edge1, float x) {
+float smooth_step(float edge0, float edge1, float x) {
float t = (x - edge0) / (edge1 - edge0);
if (t < 0) { t = 0; }
if (t > 1) { t = 1; }
@@ -121,8 +121,8 @@ next_get:
/////////////////
-f32 delta_interpolate_f32(f32 start, f32 end, f32 delta) {
- return start * (1.0f - delta) + end * delta;
+f32 delta_interpolate_f32(f32 a, f32 b, f32 delta) {
+ return a * (1.0f - delta) + b * delta;
}
s32 delta_interpolate_s32(s32 a, s32 b, f32 delta) {
diff --git a/src/pc/utils/misc.h b/src/pc/utils/misc.h
index 066b1132b..aa487042c 100644
--- a/src/pc/utils/misc.h
+++ b/src/pc/utils/misc.h
@@ -5,19 +5,27 @@
#include "types.h"
#include "PR/gbi.h"
-float smoothstep(float edge0, float edge1, float x);
+/* |description|Smoothly steps between `edge0` and `edge1` with `x` as delta|descriptionEnd| */
+float smooth_step(float edge0, float edge1, float x);
/* |description|Updates every Mario state's star count with the save file total star count|descriptionEnd| */
void update_all_mario_stars(void);
+/* |description|Gets the current clock elapsed time|descriptionEnd| */
f32 clock_elapsed(void);
+/* |description|Gets the current clock elapsed time with double precision|descriptionEnd| */
f64 clock_elapsed_f64(void);
+/* |description|Gets the current clock elapsed time in frames|descriptionEnd| */
u32 clock_elapsed_ticks(void);
void file_get_line(char* buffer, size_t maxLength, FILE* fp);
-f32 delta_interpolate_f32(f32 start, f32 end, f32 delta);
+/* |description|Linearly interpolates between `a` and `b` with `delta`|descriptionEnd| */
+f32 delta_interpolate_f32(f32 a, f32 b, f32 delta);
+/* |description|Linearly interpolates between `a` and `b` with `delta`|descriptionEnd| */
s32 delta_interpolate_s32(s32 a, s32 b, f32 delta);
+/* |description|Linearly interpolates `res` between `a` and `b` with `delta`|descriptionEnd| */
void delta_interpolate_vec3f(Vec3f res, Vec3f a, Vec3f b, f32 delta);
+/* |description|Linearly interpolates `res` between `a` and `b` with `delta`|descriptionEnd| */
void delta_interpolate_vec3s(Vec3s res, Vec3s a, Vec3s b, f32 delta);
void delta_interpolate_normal(s8* res, s8* a, s8* b, f32 delta);
void delta_interpolate_rgba(u8* res, u8* a, u8* b, f32 delta);