From 4fb5375d0d8087d7239ea78b1ae8b9876e88d873 Mon Sep 17 00:00:00 2001 From: ManIsCat2 <137772623+ManIsCat2@users.noreply.github.com> Date: Wed, 20 Aug 2025 06:16:32 +0330 Subject: [PATCH] GEO_BONE GeoLayout command (#913) --- autogen/lua_definitions/constants.lua | 6 ++ autogen/lua_definitions/manual.lua | 2 +- autogen/lua_definitions/structs.lua | 7 +++ data/dynos_bin_geo.cpp | 22 +++++++ docs/lua/constants.md | 2 + docs/lua/structs.md | 15 +++++ include/geo_commands.h | 29 +++++++++ include/types.h | 17 +++--- src/engine/geo_layout.c | 42 +++++++++++++ src/engine/geo_layout.h | 1 + src/engine/graph_node.c | 24 ++++++++ src/engine/graph_node.h | 18 ++++++ src/game/rendering_graph_node.c | 85 ++++++++++++++++++++++++++- src/pc/lua/smlua_cobject_autogen.c | 11 ++++ src/pc/lua/smlua_cobject_autogen.h | 1 + src/pc/lua/smlua_constants_autogen.c | 2 + src/pc/lua/smlua_functions.c | 1 + 17 files changed, 273 insertions(+), 12 deletions(-) diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index ff8b13b77..84747083a 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -3071,6 +3071,9 @@ GRAPH_NODE_TYPE_HELD_OBJ = (0x02E | GRAPH_NODE_TYPE_FUNCTIONAL) --- @type integer GRAPH_NODE_TYPE_CULLING_RADIUS = 0x02F +--- @type integer +GRAPH_NODE_TYPE_BONE = 0x030 + --- @type integer GFX_NUM_MASTER_LISTS = 8 @@ -11050,6 +11053,9 @@ ANIM_FLAG_6 = (1 << 6) --- @type integer ANIM_FLAG_7 = (1 << 7) +--- @type integer +ANIM_FLAG_BONE_TRANS = (1 << 8) + --- @type integer OBJECT_MAX_BHV_STACK = 16 diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua index 1e9cbe212..c3ee4c52d 100644 --- a/autogen/lua_definitions/manual.lua +++ b/autogen/lua_definitions/manual.lua @@ -450,7 +450,7 @@ function get_exclamation_box_contents() end --- @param node GraphNode | FnGraphNode ---- @return GraphNode | GraphNodeAnimatedPart | GraphNodeBackground | GraphNodeBillboard | GraphNodeCamera | GraphNodeCullingRadius | GraphNodeDisplayList | GraphNodeGenerated | GraphNodeHeldObject | GraphNodeLevelOfDetail | GraphNodeMasterList | GraphNodeObject | GraphNodeObjectParent | GraphNodeOrthoProjection | GraphNodePerspective | GraphNodeRotation | GraphNodeScale | GraphNodeShadow | GraphNodeStart | GraphNodeSwitchCase | GraphNodeTranslation | GraphNodeTranslationRotation +--- @return GraphNode | GraphNodeAnimatedPart | GraphNodeBackground | GraphNodeBillboard | GraphNodeCamera | GraphNodeCullingRadius | GraphNodeDisplayList | GraphNodeGenerated | GraphNodeHeldObject | GraphNodeLevelOfDetail | GraphNodeMasterList | GraphNodeObject | GraphNodeObjectParent | GraphNodeOrthoProjection | GraphNodePerspective | GraphNodeRotation | GraphNodeScale | GraphNodeShadow | GraphNodeStart | GraphNodeSwitchCase | GraphNodeTranslation | GraphNodeTranslationRotation | GraphNodeBone --- Returns the specific GraphNode(...) the node is part of. --- Basically the reverse of `.node` or `.fnNode` function cast_graph_node(node) diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 54de3519e..1ad7bd471 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -870,6 +870,13 @@ --- @field public node GraphNode --- @field public translation Vec3s +--- @class GraphNodeBone +--- @field public displayList Pointer_Gfx +--- @field public node GraphNode +--- @field public rotation Vec3s +--- @field public scale Vec3f +--- @field public translation Vec3s + --- @class GraphNodeCamera --- @field public fnNode FnGraphNode --- @field public focus Vec3f diff --git a/data/dynos_bin_geo.cpp b/data/dynos_bin_geo.cpp index 07ee2c612..9645da1da 100644 --- a/data/dynos_bin_geo.cpp +++ b/data/dynos_bin_geo.cpp @@ -273,6 +273,26 @@ static s64 ParseGeoSymbolArg(GfxData* aGfxData, DataNode* aNode, u64& return; \ } +#define geo_symbol_11(symb, n) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg1 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg2 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg3 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg4 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg5 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg6 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg7 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg8 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg9 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg10 = ParseGeoSymbolArg(aGfxData, aNode, aTokenIndex); \ + if (n != 0) { aGfxData->mPointerList.Add(aHead + n); } \ + GeoLayout _Gl[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, _Arg5, _Arg6, _Arg7, _Arg8, _Arg9, _Arg10) }; \ + memcpy(aHead, _Gl, sizeof(_Gl)); \ + aHead += (sizeof(_Gl) / sizeof(_Gl[0])); \ + return; \ + } + static void ParseGeoSymbol(GfxData* aGfxData, DataNode* aNode, GeoLayout*& aHead, u64& aTokenIndex, Array& aSwitchNodes) { const String& _Symbol = aNode->mTokens[aTokenIndex++]; @@ -322,6 +342,8 @@ static void ParseGeoSymbol(GfxData* aGfxData, DataNode* aNode, GeoLay geo_symbol_0(GEO_NOP_1E); geo_symbol_0(GEO_NOP_1F); geo_symbol_1(GEO_CULLING_RADIUS, 0); + geo_symbol_8(GEO_BONE, 4); + geo_symbol_11(GEO_BONE_WITH_SCALE, 7); // Geo function node if (_Symbol == "GEO_ASM") { diff --git a/docs/lua/constants.md b/docs/lua/constants.md index bf017800f..4cdd52dde 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -1359,6 +1359,7 @@ - GRAPH_NODE_TYPE_BACKGROUND - GRAPH_NODE_TYPE_HELD_OBJ - GRAPH_NODE_TYPE_CULLING_RADIUS +- GRAPH_NODE_TYPE_BONE - GFX_NUM_MASTER_LISTS - GEO_CONTEXT_CREATE - GEO_CONTEXT_RENDER @@ -4666,6 +4667,7 @@ - ANIM_FLAG_5 - ANIM_FLAG_6 - ANIM_FLAG_7 +- ANIM_FLAG_BONE_TRANS - OBJECT_MAX_BHV_STACK - OBJECT_NUM_REGULAR_FIELDS - OBJECT_NUM_CUSTOM_FIELDS diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 416d673b6..fb28a89f4 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -42,6 +42,7 @@ - [GraphNodeAnimatedPart](#GraphNodeAnimatedPart) - [GraphNodeBackground](#GraphNodeBackground) - [GraphNodeBillboard](#GraphNodeBillboard) +- [GraphNodeBone](#GraphNodeBone) - [GraphNodeCamera](#GraphNodeCamera) - [GraphNodeCullingRadius](#GraphNodeCullingRadius) - [GraphNodeDisplayList](#GraphNodeDisplayList) @@ -1292,6 +1293,20 @@
+## [GraphNodeBone](#GraphNodeBone) + +| Field | Type | Access | +| ----- | ---- | ------ | +| displayList | `Pointer` <`Gfx`> | | +| node | [GraphNode](structs.md#GraphNode) | read-only | +| rotation | [Vec3s](structs.md#Vec3s) | read-only | +| scale | [Vec3f](structs.md#Vec3f) | read-only | +| translation | [Vec3s](structs.md#Vec3s) | read-only | + +[:arrow_up_small:](#) + +
+ ## [GraphNodeCamera](#GraphNodeCamera) | Field | Type | Access | diff --git a/include/geo_commands.h b/include/geo_commands.h index 253ee2de6..515c004b2 100644 --- a/include/geo_commands.h +++ b/include/geo_commands.h @@ -481,5 +481,34 @@ enum SkyBackgroundParams { CMD_BBH(0x23, 0x00, param), \ CMD_W(luaTokenIndex) +/** + * 0x24: Create a scene graph node that is rotated by the object's animation + an initial rotation with optional default scale + * 0x01: u8 params/drawingLayer + * 0b1000_0000 if set, enable scale and drawingLayer field + * 0b0000_1111 drawingLayer + * 0x02-0x03: unused + * 0x04: s16 xTranslation + * 0x06: s16 yTranslation + * 0x08: s16 zTranslation + * 0x0A: s16 xRotation + * 0x0C: s16 yRotation + * 0x0E: s16 zRotation + * if MSbit of params is set: + * 0x10: u32 xScale + * 0x14: u32 yScale + * 0x18: u32 zScale + * 0x1C: displayList: display list segmented address + * else: + * 0x10: displayList: display list segmented address + */ +#define GEO_BONE(layer, tx, ty, tz, rx, ry, rz, displayList) \ + CMD_BBH(0x24, (0x00 | layer), 0x0000), \ + CMD_HHHHHH(tx, ty, tz, rx, ry, rz), \ + CMD_PTR(displayList) +#define GEO_BONE_WITH_SCALE(layer, tx, ty, tz, rx, ry, rz, sx, sy, sz, displayList) \ + CMD_BBH(0x24, (0x80 | layer), 0x0000), \ + CMD_HHHHHH(tx, ty, tz, rx, ry, rz), \ + CMD_W(sx), CMD_W(sy), CMD_W(sz), \ + CMD_PTR(displayList) #endif // GEO_COMMANDS_H diff --git a/include/types.h b/include/types.h index c5cecc02f..70c697636 100644 --- a/include/types.h +++ b/include/types.h @@ -103,14 +103,15 @@ struct VblankHandler OSMesg msg; }; -#define ANIM_FLAG_NOLOOP (1 << 0) // 0x01 -#define ANIM_FLAG_BACKWARD (1 << 1) // 0x02 -#define ANIM_FLAG_2 (1 << 2) // 0x04 -#define ANIM_FLAG_HOR_TRANS (1 << 3) // 0x08 -#define ANIM_FLAG_VERT_TRANS (1 << 4) // 0x10 -#define ANIM_FLAG_5 (1 << 5) // 0x20 -#define ANIM_FLAG_6 (1 << 6) // 0x40 -#define ANIM_FLAG_7 (1 << 7) // 0x80 +#define ANIM_FLAG_NOLOOP (1 << 0) // 0x01 +#define ANIM_FLAG_BACKWARD (1 << 1) // 0x02 +#define ANIM_FLAG_2 (1 << 2) // 0x04 +#define ANIM_FLAG_HOR_TRANS (1 << 3) // 0x08 +#define ANIM_FLAG_VERT_TRANS (1 << 4) // 0x10 +#define ANIM_FLAG_5 (1 << 5) // 0x20 +#define ANIM_FLAG_6 (1 << 6) // 0x40 +#define ANIM_FLAG_7 (1 << 7) // 0x80 +#define ANIM_FLAG_BONE_TRANS (1 << 8) struct Animation { // TODO: Optimize this later if possible. diff --git a/src/engine/geo_layout.c b/src/engine/geo_layout.c index f12e86552..31465bc62 100644 --- a/src/engine/geo_layout.c +++ b/src/engine/geo_layout.c @@ -47,6 +47,7 @@ GeoLayoutCommandProc GeoLayoutJumpTable[] = { geo_layout_cmd_node_background_ext, geo_layout_cmd_node_switch_case_ext, geo_layout_cmd_node_generated_ext, + geo_layout_cmd_bone, }; struct GraphNode gObjParentGraphNode; @@ -846,6 +847,47 @@ void geo_layout_cmd_node_generated_ext(void) { gGeoLayoutCommand += 0x08 << CMD_SIZE_SHIFT; } +/* + 0x24: Create a scene graph node that is rotated by the object's animation + an initial rotation. +*/ +void geo_layout_cmd_bone(void) { + struct GraphNodeBone *graphNode; + Vec3s translation; + Vec3s rotation; + s32 params = cur_geo_cmd_u8(0x01); + s32 drawingLayer = params; + Vec3f scale; + vec3f_copy(scale, gVec3fOne); + + void *displayList; + s16 *cmdPos = (s16 *) gGeoLayoutCommand; + + cmdPos = read_vec3s(translation, &cmdPos[2]); + cmdPos = read_vec3s(rotation, &cmdPos[0]); + if (params & 0x80) { + drawingLayer &= 0x0F; + + vec3f_set(scale, + cur_geo_cmd_u32(0x10) / 65536.0f, + cur_geo_cmd_u32(0x14) / 65536.0f, + cur_geo_cmd_u32(0x18) / 65536.0f + ); + cmdPos += 6 << CMD_SIZE_SHIFT; + } + displayList = *(void **) &cmdPos[0]; + cmdPos += 2 << CMD_SIZE_SHIFT; + + graphNode = init_graph_node_bone( + gGraphNodePool, NULL, + drawingLayer, displayList, + translation, rotation, + scale); + + register_scene_graph_node(&graphNode->node); + + gGeoLayoutCommand = (u8 *) cmdPos; +} + struct GraphNode *process_geo_layout(struct DynamicPool *pool, void *segptr) { // set by register_scene_graph_node when gCurGraphNodeIndex is 0 // and gCurRootGraphNode is NULL diff --git a/src/engine/geo_layout.h b/src/engine/geo_layout.h index a7cbaef5b..bdb01f0fb 100644 --- a/src/engine/geo_layout.h +++ b/src/engine/geo_layout.h @@ -84,6 +84,7 @@ void geo_layout_cmd_node_culling_radius(void); void geo_layout_cmd_node_background_ext(void); void geo_layout_cmd_node_switch_case_ext(void); void geo_layout_cmd_node_generated_ext(void); +void geo_layout_cmd_bone(void); struct GraphNode *process_geo_layout(struct DynamicPool *a0, void *segptr); diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index d3c1ccbd8..c9c0023f6 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -551,6 +551,30 @@ struct GraphNodeHeldObject *init_graph_node_held_object(struct DynamicPool *pool return graphNode; } +/** + * Allocates and returns a newly created bone node with initial rotation/translation + */ +struct GraphNodeBone *init_graph_node_bone(struct DynamicPool *pool, + struct GraphNodeBone *graphNode, + s32 drawingLayer, void *displayList, + Vec3s translation, Vec3s rotation, + Vec3f scale) { + if (pool != NULL) { + graphNode = dynamic_pool_alloc(pool, sizeof(struct GraphNodeBone)); + } + + if (graphNode != NULL) { + init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_BONE); + vec3s_copy(graphNode->translation, translation); + vec3s_copy(graphNode->rotation, rotation); + vec3f_copy(graphNode->scale, scale); + graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); + } + + return graphNode; +} + /** * Adds 'childNode' to the end of the list children from 'parent' */ diff --git a/src/engine/graph_node.h b/src/engine/graph_node.h index 4f2a63374..c044fa548 100644 --- a/src/engine/graph_node.h +++ b/src/engine/graph_node.h @@ -51,6 +51,7 @@ #define GRAPH_NODE_TYPE_BACKGROUND (0x02C | GRAPH_NODE_TYPE_FUNCTIONAL) #define GRAPH_NODE_TYPE_HELD_OBJ (0x02E | GRAPH_NODE_TYPE_FUNCTIONAL) #define GRAPH_NODE_TYPE_CULLING_RADIUS 0x02F +#define GRAPH_NODE_TYPE_BONE 0x030 // The number of master lists. A master list determines the order and render // mode with which display lists are drawn. @@ -377,6 +378,18 @@ struct GraphNodeCullingRadius u8 pad1E[2]; }; +/** + * GraphNodeAnimatedPart with initial rotation and scale values. + */ +struct GraphNodeBone +{ + struct GraphNode node; + Gfx *displayList; + Vec3s translation; + Vec3s rotation; + Vec3f scale; +}; + extern struct GraphNodeMasterList *gCurGraphNodeMasterList; extern struct GraphNodePerspective *gCurGraphNodeCamFrustum; extern struct GraphNodeCamera *gCurGraphNodeCamera; @@ -433,6 +446,11 @@ struct GraphNodeBackground *init_graph_node_background(struct DynamicPool *pool, struct GraphNodeHeldObject *init_graph_node_held_object(struct DynamicPool *pool, struct GraphNodeHeldObject *sp1c, struct Object *objNode, Vec3s translation, GraphNodeFunc nodeFunc, s32 playerIndex); +struct GraphNodeBone *init_graph_node_bone(struct DynamicPool *pool, + struct GraphNodeBone *graphNode, + s32 drawingLayer, void *displayList, + Vec3s translation, Vec3s rotation, + Vec3f scale); struct GraphNode *geo_add_child(struct GraphNode *parent, struct GraphNode *childNode); struct GraphNode* geo_remove_child_from_parent(struct GraphNode* parent, struct GraphNode* graphNode); struct GraphNode *geo_remove_child(struct GraphNode *graphNode); diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 16e704c5e..0edbfbf2f 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -1086,9 +1086,14 @@ static void anim_process(Vec3f translation, Vec3s rotation, u8 *animType, s16 an } if (*animType == ANIM_TYPE_ROTATION) { - rotation[0] = retrieve_animation_value(gCurAnim, animFrame, animAttribute); - rotation[1] = retrieve_animation_value(gCurAnim, animFrame, animAttribute); - rotation[2] = retrieve_animation_value(gCurAnim, animFrame, animAttribute); + // GEO_ANIMATED_PART: rotation = (0 + AnimValue) + // GEO_BONE: rotation = (BoneRotation + AnimValue) + rotation[0] += retrieve_animation_value(gCurAnim, animFrame, animAttribute); + rotation[1] += retrieve_animation_value(gCurAnim, animFrame, animAttribute); + rotation[2] += retrieve_animation_value(gCurAnim, animFrame, animAttribute); + if (gCurAnim->flags & ANIM_FLAG_BONE_TRANS) { + *animType = ANIM_TYPE_TRANSLATION; + } } } @@ -1707,6 +1712,77 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) { } } +/** + * Render an animated part with initial rotation and scale values. + */ +static void geo_process_bone(struct GraphNodeBone *node) { + if (gCurMarioBodyState && !gCurGraphNodeHeldObject) { + gCurMarioBodyState->currAnimPart++; + } + + Mat4 matrix; + Vec3s rotation; + Vec3f translation; + Vec3f scale; + + // Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\. + if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; } + + u16 *animAttribute = gCurrAnimAttribute; + u8 animType = gCurAnimType; + + // current frame + vec3s_copy(rotation, node->rotation); + vec3s_to_vec3f(translation, node->translation); + vec3f_copy(scale, node->scale); + anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute); + mtxf_rotate_xyz_and_translate(matrix, translation, rotation); + mtxf_scale_vec3f(matrix, matrix, scale); + mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]); + + // previous frame + geo_update_interpolation(node->translation, node->rotation, node->scale, + if (geo_should_interpolate(interp)) { + vec3s_copy(rotation, interp->rotation); + vec3s_to_vec3f(translation, interp->translation); + vec3f_copy(scale, interp->scale); + } else { + vec3s_copy(rotation, node->rotation); + vec3s_to_vec3f(translation, node->translation); + vec3f_copy(scale, node->scale); + } + anim_process(translation, rotation, &animType, gPrevAnimFrame, &animAttribute); + mtxf_rotate_xyz_and_translate(matrix, translation, rotation); + mtxf_scale_vec3f(matrix, matrix, scale); + mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]); + ); + + // Increment the matrix stack, If we fail to do so. Just return. + if (!increment_mat_stack()) { return; } + + // Mario anim part pos + if (gCurMarioBodyState && !gCurGraphNodeHeldObject && gCurMarioBodyState->currAnimPart > MARIO_ANIM_PART_NONE && gCurMarioBodyState->currAnimPart < MARIO_ANIM_PART_MAX) { + get_pos_from_transform_mtx( + gCurMarioBodyState->animPartsPos[gCurMarioBodyState->currAnimPart], + gMatStack[gMatStackIndex], + *gCurGraphNodeCamera->matrixPtr + ); + } + + if (gCurGraphNodeMarioState != NULL) { + Vec3f translated = { 0 }; + get_pos_from_transform_mtx(translated, gMatStack[gMatStackIndex], *gCurGraphNodeCamera->matrixPtr); + gCurGraphNodeMarioState->minimumBoneY = fmin(gCurGraphNodeMarioState->minimumBoneY, translated[1] - gCurGraphNodeMarioState->marioObj->header.gfx.pos[1]); + } + if (node->displayList != NULL) { + geo_append_display_list(node->displayList, node->node.flags >> 8); + } + if (node->node.children != NULL) { + geo_process_node_and_siblings(node->node.children); + } + gMatStackIndex--; +} + /** * Processes the children of the given GraphNode if it has any */ @@ -1830,6 +1906,9 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) { case GRAPH_NODE_TYPE_HELD_OBJ: geo_process_held_object((struct GraphNodeHeldObject *) curGraphNode); break; + case GRAPH_NODE_TYPE_BONE: + geo_process_bone((struct GraphNodeBone *) curGraphNode); + break; default: geo_try_process_children((struct GraphNode *) curGraphNode); break; diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 0cf64b9fa..9f5241721 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -1125,6 +1125,15 @@ static struct LuaObjectField sGraphNodeBillboardFields[LUA_GRAPH_NODE_BILLBOARD_ { "translation", LVT_COBJECT, offsetof(struct GraphNodeBillboard, translation), true, LOT_VEC3S, 1, sizeof(Vec3s) }, }; +#define LUA_GRAPH_NODE_BONE_FIELD_COUNT 5 +static struct LuaObjectField sGraphNodeBoneFields[LUA_GRAPH_NODE_BONE_FIELD_COUNT] = { + { "displayList", LVT_COBJECT_P, offsetof(struct GraphNodeBone, displayList), false, LOT_GFX, 1, sizeof(Gfx*) }, + { "node", LVT_COBJECT, offsetof(struct GraphNodeBone, node), true, LOT_GRAPHNODE, 1, sizeof(struct GraphNode) }, + { "rotation", LVT_COBJECT, offsetof(struct GraphNodeBone, rotation), true, LOT_VEC3S, 1, sizeof(Vec3s) }, + { "scale", LVT_COBJECT, offsetof(struct GraphNodeBone, scale), true, LOT_VEC3F, 1, sizeof(Vec3f) }, + { "translation", LVT_COBJECT, offsetof(struct GraphNodeBone, translation), true, LOT_VEC3S, 1, sizeof(Vec3s) }, +}; + #define LUA_GRAPH_NODE_CAMERA_FIELD_COUNT 10 static struct LuaObjectField sGraphNodeCameraFields[LUA_GRAPH_NODE_CAMERA_FIELD_COUNT] = { // { "config", LVT_???, offsetof(struct GraphNodeCamera, config), false, LOT_???, 1, sizeof(union { ... }) }, <--- UNIMPLEMENTED @@ -2914,6 +2923,7 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN] { LOT_GRAPHNODEANIMATEDPART, sGraphNodeAnimatedPartFields, LUA_GRAPH_NODE_ANIMATED_PART_FIELD_COUNT }, { LOT_GRAPHNODEBACKGROUND, sGraphNodeBackgroundFields, LUA_GRAPH_NODE_BACKGROUND_FIELD_COUNT }, { LOT_GRAPHNODEBILLBOARD, sGraphNodeBillboardFields, LUA_GRAPH_NODE_BILLBOARD_FIELD_COUNT }, + { LOT_GRAPHNODEBONE, sGraphNodeBoneFields, LUA_GRAPH_NODE_BONE_FIELD_COUNT }, { LOT_GRAPHNODECAMERA, sGraphNodeCameraFields, LUA_GRAPH_NODE_CAMERA_FIELD_COUNT }, { LOT_GRAPHNODECULLINGRADIUS, sGraphNodeCullingRadiusFields, LUA_GRAPH_NODE_CULLING_RADIUS_FIELD_COUNT }, { LOT_GRAPHNODEDISPLAYLIST, sGraphNodeDisplayListFields, LUA_GRAPH_NODE_DISPLAY_LIST_FIELD_COUNT }, @@ -3043,6 +3053,7 @@ const char *sLuaLotNames[] = { [LOT_GRAPHNODEANIMATEDPART] = "GraphNodeAnimatedPart", [LOT_GRAPHNODEBACKGROUND] = "GraphNodeBackground", [LOT_GRAPHNODEBILLBOARD] = "GraphNodeBillboard", + [LOT_GRAPHNODEBONE] = "GraphNodeBone", [LOT_GRAPHNODECAMERA] = "GraphNodeCamera", [LOT_GRAPHNODECULLINGRADIUS] = "GraphNodeCullingRadius", [LOT_GRAPHNODEDISPLAYLIST] = "GraphNodeDisplayList", diff --git a/src/pc/lua/smlua_cobject_autogen.h b/src/pc/lua/smlua_cobject_autogen.h index a2235142d..b5ec35d19 100644 --- a/src/pc/lua/smlua_cobject_autogen.h +++ b/src/pc/lua/smlua_cobject_autogen.h @@ -63,6 +63,7 @@ enum LuaObjectAutogenType { LOT_GRAPHNODEANIMATEDPART, LOT_GRAPHNODEBACKGROUND, LOT_GRAPHNODEBILLBOARD, + LOT_GRAPHNODEBONE, LOT_GRAPHNODECAMERA, LOT_GRAPHNODECULLINGRADIUS, LOT_GRAPHNODEDISPLAYLIST, diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 5aad39d60..7f1ac1552 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1568,6 +1568,7 @@ char gSmluaConstants[] = "" "GRAPH_NODE_TYPE_BACKGROUND=(0x02C | GRAPH_NODE_TYPE_FUNCTIONAL)\n" "GRAPH_NODE_TYPE_HELD_OBJ=(0x02E | GRAPH_NODE_TYPE_FUNCTIONAL)\n" "GRAPH_NODE_TYPE_CULLING_RADIUS=0x02F\n" +"GRAPH_NODE_TYPE_BONE=0x030\n" "GFX_NUM_MASTER_LISTS=8\n" "GEO_CONTEXT_CREATE=0\n" "GEO_CONTEXT_RENDER=1\n" @@ -4575,6 +4576,7 @@ char gSmluaConstants[] = "" "ANIM_FLAG_5=(1 << 5)\n" "ANIM_FLAG_6=(1 << 6)\n" "ANIM_FLAG_7=(1 << 7)\n" +"ANIM_FLAG_BONE_TRANS=(1 << 8)\n" "OBJECT_MAX_BHV_STACK=16\n" "OBJECT_NUM_REGULAR_FIELDS=0x50\n" "OBJECT_NUM_CUSTOM_FIELDS=0x40\n" diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index d9c926bf1..1aba4cb47 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -883,6 +883,7 @@ static GraphNodeLot graphNodeLots[] = { { GRAPH_NODE_TYPE_SWITCH_CASE, LOT_GRAPHNODESWITCHCASE }, { GRAPH_NODE_TYPE_TRANSLATION, LOT_GRAPHNODETRANSLATION }, { GRAPH_NODE_TYPE_TRANSLATION_ROTATION, LOT_GRAPHNODETRANSLATIONROTATION }, + { GRAPH_NODE_TYPE_BONE, LOT_GRAPHNODEBONE }, }; int smlua_func_cast_graph_node(lua_State* L) {