diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua
index 3478f1235..5b2e0d9d4 100644
--- a/autogen/lua_definitions/constants.lua
+++ b/autogen/lua_definitions/constants.lua
@@ -9164,7 +9164,10 @@ HOOK_ON_GEO_PROCESS = 48
HOOK_BEFORE_GEO_PROCESS = 49
--- @type LuaHookedEventType
-HOOK_MAX = 50
+HOOK_ON_GEO_PROCESS_CHILDREN = 50
+
+--- @type LuaHookedEventType
+HOOK_MAX = 51
--- @class LuaModMenuElementType
diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua
index b8ccd9e33..ec06b4008 100644
--- a/autogen/lua_definitions/manual.lua
+++ b/autogen/lua_definitions/manual.lua
@@ -31,6 +31,16 @@ gCharacters = {}
--- - Index 0 always refers to the local player
gControllers = {}
+--- @type Pointer_Mat4[]
+--- Matrix stack used during geo process
+--- - Only has an effect when used in a geo process hook
+gMatStack = {}
+
+--- @type Pointer_Mat4[]
+--- Matrix stack used during geo process
+--- - Only has an effect when used in a geo process hook
+gMatStackPrev = {}
+
--- @type GlobalTextures
--- Struct containing HUD glyph textures
gTextures = {}
diff --git a/docs/lua/constants.md b/docs/lua/constants.md
index e25a9f9a0..bd8c28bed 100644
--- a/docs/lua/constants.md
+++ b/docs/lua/constants.md
@@ -3337,7 +3337,8 @@
| HOOK_ON_DJUI_THEME_CHANGED | 47 |
| HOOK_ON_GEO_PROCESS | 48 |
| HOOK_BEFORE_GEO_PROCESS | 49 |
-| HOOK_MAX | 50 |
+| HOOK_ON_GEO_PROCESS_CHILDREN | 50 |
+| HOOK_MAX | 51 |
### [enum LuaModMenuElementType](#LuaModMenuElementType)
| Identifier | Value |
diff --git a/docs/lua/globals.md b/docs/lua/globals.md
index 651840f28..20bfacbd1 100644
--- a/docs/lua/globals.md
+++ b/docs/lua/globals.md
@@ -44,6 +44,20 @@ The `gControllers[]` table is an array from `0` to `(MAX_PLAYERS - 1)` that cont
+## [gMatStack](#gMatStack)
+The `gMatStack[]` table is an array from `0` to `(MATRIX_STACK_SIZE - 1)` that contains `Mat4`s used by geo process.
+
+[:arrow_up_small:](#)
+
+
+
+## [gMatStackPrev](#gMatStackPrev)
+The `gMatStackPrev[]` table is similar to [gMatStack](#gMatStack) for interpolation.
+
+[:arrow_up_small:](#)
+
+
+
## [gTextures](#gTextures)
The `gTextures` table contains references to textures. Listed in [GlobalTextures](structs.md#GlobalTextures).
@@ -126,7 +140,7 @@ The `gGlobalSyncTable` is a table used for networking. Any field set inside of t
## [gPlayerSyncTable](#gPlayerSyncTable)
-The `gPlayerSyncTable[]` is an array from 0 to `(MAX_PLAYERS - 1)` that is used for networking. Any field set inside of this table is automatically synchronized with all other clients.
+The `gPlayerSyncTable[]` is an array from 0 to `(MAX_PLAYERS - 1)` that is used for networking. Any field set inside of this table is automatically synchronized with all other clients.
It is indexed by the local `playerIndex`, so `gPlayerSyncTable[0]` is always for the local player.
diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c
index fb9d7808a..0cf4a7d6f 100644
--- a/src/game/rendering_graph_node.c
+++ b/src/game/rendering_graph_node.c
@@ -43,7 +43,6 @@
*
*/
-#define MATRIX_STACK_SIZE 64
#define DISPLAY_LIST_HEAP_SIZE 32000
f32 gProjectionMaxNearValue = 5;
@@ -1512,6 +1511,8 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
// processed instead of all children like usual
if (parent != NULL) {
iterateChildren = (parent->type != GRAPH_NODE_TYPE_SWITCH_CASE);
+
+ if (parent->hookProcess) smlua_call_event_hooks_graph_node_and_int_param(HOOK_ON_GEO_PROCESS_CHILDREN, parent, gMatStackIndex);
}
do {
@@ -1538,7 +1539,7 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
}
if (curGraphNode->flags & GRAPH_RENDER_ACTIVE) {
- if (curGraphNode->hookProcess) smlua_call_event_hooks_graph_node_and_int_param(HOOK_BEFORE_GEO_PROCESS, curGraphNode, curGraphNode->hookProcess);
+ if (curGraphNode->hookProcess) smlua_call_event_hooks_graph_node_and_int_param(HOOK_BEFORE_GEO_PROCESS, curGraphNode, gMatStackIndex);
if (curGraphNode->flags & GRAPH_RENDER_CHILDREN_FIRST) {
geo_try_process_children(curGraphNode);
} else {
@@ -1606,7 +1607,7 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
break;
}
}
- if (curGraphNode->hookProcess) smlua_call_event_hooks_graph_node_and_int_param(HOOK_ON_GEO_PROCESS, curGraphNode, curGraphNode->hookProcess);
+ if (curGraphNode->hookProcess) smlua_call_event_hooks_graph_node_and_int_param(HOOK_ON_GEO_PROCESS, curGraphNode, gMatStackIndex + 1);
} else {
if (curGraphNode && curGraphNode->type == GRAPH_NODE_TYPE_OBJECT) {
((struct GraphNodeObject *) curGraphNode)->throwMatrix = NULL;
diff --git a/src/game/rendering_graph_node.h b/src/game/rendering_graph_node.h
index 1e9889689..76183200c 100644
--- a/src/game/rendering_graph_node.h
+++ b/src/game/rendering_graph_node.h
@@ -5,6 +5,10 @@
#include "engine/graph_node.h"
+#define MATRIX_STACK_SIZE 64
+extern Mat4 gMatStack[MATRIX_STACK_SIZE];
+extern Mat4 gMatStackPrev[MATRIX_STACK_SIZE];
+
extern f32 gProjectionMaxNearValue;
extern s16 gProjectionVanillaNearValue;
extern s16 gProjectionVanillaFarValue;
diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c
index c946e4163..48a9f0ecd 100644
--- a/src/pc/lua/smlua_cobject.c
+++ b/src/pc/lua/smlua_cobject.c
@@ -6,6 +6,7 @@
#include "game/first_person_cam.h"
#include "game/hardcoded.h"
#include "game/scroll_targets.h"
+#include "game/rendering_graph_node.h"
#include "audio/external.h"
#include "object_fields.h"
#include "pc/djui/djui_hud_utils.h"
@@ -663,6 +664,10 @@ void smlua_cobject_init_globals(void) {
EXPOSE_GLOBAL_ARRAY(LOT_CONTROLLER, gControllers, MAX_PLAYERS);
+ EXPOSE_GLOBAL_ARRAY(LOT_MAT4, gMatStack, MATRIX_STACK_SIZE);
+
+ EXPOSE_GLOBAL_ARRAY(LOT_MAT4, gMatStackPrev, MATRIX_STACK_SIZE);
+
// Structs
EXPOSE_GLOBAL_WITH_NAME(LOT_GLOBALTEXTURES, gGlobalTextures, "gTextures");
diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c
index 7ef77bea6..9ca19213b 100644
--- a/src/pc/lua/smlua_constants_autogen.c
+++ b/src/pc/lua/smlua_constants_autogen.c
@@ -3204,7 +3204,8 @@ char gSmluaConstants[] = ""
"HOOK_ON_DJUI_THEME_CHANGED = 47\n"
"HOOK_ON_GEO_PROCESS = 48\n"
"HOOK_BEFORE_GEO_PROCESS = 49\n"
-"HOOK_MAX = 50\n"
+"HOOK_ON_GEO_PROCESS_CHILDREN = 50\n"
+"HOOK_MAX = 51\n"
"ACTION_HOOK_EVERY_FRAME = 0\n"
"ACTION_HOOK_GRAVITY = 1\n"
"ACTION_HOOK_MAX = 2\n"
diff --git a/src/pc/lua/smlua_hooks.c b/src/pc/lua/smlua_hooks.c
index a56c6f38c..1db3a0ead 100644
--- a/src/pc/lua/smlua_hooks.c
+++ b/src/pc/lua/smlua_hooks.c
@@ -1049,7 +1049,7 @@ void smlua_call_event_hooks_graph_node_object_and_int_param(enum LuaHookedEventT
}
}
-void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hookType, struct GraphNode* node, s32 param) {
+void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hookType, struct GraphNode* node, s16 matIndex) {
lua_State* L = gLuaState;
if (L == NULL) { return; }
struct LuaHookedEvent* hook = &sHookedEvents[hookType];
@@ -1060,8 +1060,8 @@ void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hoo
// push graph node
smlua_push_object(L, LOT_GRAPHNODE, node);
- // push param
- lua_pushinteger(L, param);
+ // push mat index
+ lua_pushinteger(L, matIndex);
// call the callback
if (0 != smlua_call_hook(L, 2, 0, 0, hook->mod[i])) {
diff --git a/src/pc/lua/smlua_hooks.h b/src/pc/lua/smlua_hooks.h
index db46cc509..aa52c937e 100644
--- a/src/pc/lua/smlua_hooks.h
+++ b/src/pc/lua/smlua_hooks.h
@@ -61,6 +61,7 @@ enum LuaHookedEventType {
HOOK_ON_DJUI_THEME_CHANGED,
HOOK_ON_GEO_PROCESS,
HOOK_BEFORE_GEO_PROCESS,
+ HOOK_ON_GEO_PROCESS_CHILDREN,
HOOK_MAX,
};
@@ -115,6 +116,7 @@ static const char* LuaHookedEventTypeName[] = {
"HOOK_ON_DJUI_THEME_CHANGED",
"HOOK_ON_GEO_PROCESS",
"HOOK_BEFORE_GEO_PROCESS",
+ "HOOK_ON_GEO_PROCESS_CHILDREN",
"HOOK_MAX"
};
@@ -191,7 +193,7 @@ bool smlua_call_event_hooks_mario_param_and_int_ret_int(enum LuaHookedEventType
bool smlua_call_event_hooks_mario_param_ret_float(enum LuaHookedEventType hookType, struct MarioState* m, f32* returnValue);
bool smlua_call_event_hooks_mario_param_and_int_and_int_ret_int(enum LuaHookedEventType hookType, struct MarioState* m, s32 param, u32 args, s32* returnValue);
void smlua_call_event_hooks_graph_node_object_and_int_param(enum LuaHookedEventType hookType, struct GraphNodeObject* node, s32 param);
-void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hookType, struct GraphNode* node, s32 param);
+void smlua_call_event_hooks_graph_node_and_int_param(enum LuaHookedEventType hookType, struct GraphNode* node, s16 matIndex);
void smlua_call_event_hooks_on_seq_load(enum LuaHookedEventType hookType, u32 player, u32 seqId, s32 loadAsync, s16* returnValue);
const char *smlua_call_event_hooks_int_ret_bool_and_string(enum LuaHookedEventType hookType, s32 param, bool* returnValue);
void smlua_call_event_hooks_string_param(enum LuaHookedEventType hookType, const char* string);