Remove GRAPH_NODE_TYPE_FUNCTIONAL define & restore functionality using an alternative method. (#557)

Fixes Mirror Mario and similar things.
This commit is contained in:
Arceveti
2023-01-20 00:59:18 -05:00
committed by GitHub
parent 9bec16d2f0
commit 7551748a35
5 changed files with 40 additions and 75 deletions

View File

@@ -123,11 +123,6 @@
*/
// #define FIX_REFLECT_MTX
/**
* This improves performance a bit, and does not seem to break anything.
*/
#define DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
/**
* Disables all object shadows. You'll probably only want this either as a last resort for performance or if you're making a super stylized hack.
*/

View File

@@ -603,7 +603,6 @@ struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild) {
return parent;
}
#ifndef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
/**
* Helper function for geo_call_global_function_nodes that recursively
* traverses the scene graph and calls the functions of global nodes.
@@ -612,11 +611,19 @@ void geo_call_global_function_nodes_helper(struct GraphNode *graphNode, s32 call
struct GraphNode **globalPtr;
struct GraphNode *curNode = graphNode;
struct FnGraphNode *asFnNode;
s16 type;
do {
asFnNode = (struct FnGraphNode *) curNode;
if (curNode->type & GRAPH_NODE_TYPE_FUNCTIONAL) {
type = curNode->type;
// Whether the type's corresponding struct has a FnGraphNode fnNode struct.
if (type == GRAPH_NODE_TYPE_PERSPECTIVE
|| type == GRAPH_NODE_TYPE_SWITCH_CASE
|| type == GRAPH_NODE_TYPE_CAMERA
|| type == GRAPH_NODE_TYPE_GENERATED_LIST
|| type == GRAPH_NODE_TYPE_BACKGROUND
|| type == GRAPH_NODE_TYPE_HELD_OBJ) {
if (asFnNode->func != NULL) {
asFnNode->func(callContext, curNode, NULL);
}
@@ -669,10 +676,9 @@ void geo_call_global_function_nodes(struct GraphNode *graphNode, s32 callContext
geo_call_global_function_nodes_helper(graphNode->children, callContext);
}
gCurGraphNodeRoot = 0;
gCurGraphNodeRoot = NULL;
}
}
#endif
/**
* When objects are cleared, this is called on all object nodes (loaded or unloaded).

View File

@@ -50,7 +50,6 @@ enum GraphRenderFlags {
#define GET_GRAPH_NODE_LAYER(flags) ((flags & GRAPH_RENDER_LAYERS_MASK) >> GRAPH_RENDER_FLAGS_SIZE)
#endif
#ifdef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
// The discriminant for different types of geo nodes
enum GraphNodeTypes {
GRAPH_NODE_TYPE_ORTHO_PROJECTION,
@@ -76,38 +75,6 @@ enum GraphNodeTypes {
GRAPH_NODE_TYPE_ROOT,
GRAPH_NODE_TYPE_START,
};
#else
// Whether the node type has a function pointer of type GraphNodeFunc
#define GRAPH_NODE_TYPE_FUNCTIONAL (1 << 8)
// The discriminant for different types of geo nodes
enum GraphNodeTypes {
GRAPH_NODE_TYPE_ROOT = 0x01,
GRAPH_NODE_TYPE_ORTHO_PROJECTION = 0x02,
GRAPH_NODE_TYPE_PERSPECTIVE = (0x03 | GRAPH_NODE_TYPE_FUNCTIONAL),
GRAPH_NODE_TYPE_MASTER_LIST = 0x04,
GRAPH_NODE_TYPE_START = 0x0A,
GRAPH_NODE_TYPE_LEVEL_OF_DETAIL = 0x0B,
GRAPH_NODE_TYPE_SWITCH_CASE = (0x0C | GRAPH_NODE_TYPE_FUNCTIONAL),
GRAPH_NODE_TYPE_CAMERA = (0x14 | GRAPH_NODE_TYPE_FUNCTIONAL),
GRAPH_NODE_TYPE_TRANSLATION_ROTATION = 0x15,
GRAPH_NODE_TYPE_TRANSLATION = 0x16,
GRAPH_NODE_TYPE_ROTATION = 0x17,
GRAPH_NODE_TYPE_OBJECT = 0x18,
GRAPH_NODE_TYPE_ANIMATED_PART = 0x19,
GRAPH_NODE_TYPE_BILLBOARD = 0x1A,
GRAPH_NODE_TYPE_DISPLAY_LIST = 0x1B,
GRAPH_NODE_TYPE_SCALE = 0x1C,
GRAPH_NODE_TYPE_SHADOW = 0x28,
GRAPH_NODE_TYPE_OBJECT_PARENT = 0x29,
GRAPH_NODE_TYPE_GENERATED_LIST = (0x2A | GRAPH_NODE_TYPE_FUNCTIONAL),
GRAPH_NODE_TYPE_BACKGROUND = (0x2C | GRAPH_NODE_TYPE_FUNCTIONAL),
GRAPH_NODE_TYPE_HELD_OBJ = (0x2E | GRAPH_NODE_TYPE_FUNCTIONAL),
GRAPH_NODE_TYPE_CULLING_RADIUS = 0x2F,
GRAPH_NODE_TYPES_MASK = 0xFF,
};
#endif
// Passed as first argument to a GraphNodeFunc to give information about in
// which context it was called and what it is expected to do.
@@ -426,10 +393,8 @@ struct GraphNodeHeldObject *init_graph_node_held_object (struct
struct GraphNode *geo_add_child (struct GraphNode *parent, struct GraphNode *childNode);
struct GraphNode *geo_remove_child (struct GraphNode *graphNode);
struct GraphNode *geo_make_first_child(struct GraphNode *newFirstChild);
#ifndef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
void geo_call_global_function_nodes_helper(struct GraphNode *graphNode, s32 callContext);
void geo_call_global_function_nodes (struct GraphNode *graphNode, s32 callContext);
#endif
void geo_reset_object_node(struct GraphNodeObject *graphNode);
void geo_obj_init(struct GraphNodeObject *graphNode, void *sharedChild, Vec3f pos, Vec3s angle);
void geo_obj_init_spawninfo(struct GraphNodeObject *graphNode, struct SpawnInfo *spawn);

View File

@@ -212,18 +212,14 @@ void clear_area_graph_nodes(void) {
s32 i;
if (gCurrentArea != NULL) {
#ifndef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
geo_call_global_function_nodes(&gCurrentArea->graphNode->node, GEO_CONTEXT_AREA_UNLOAD);
#endif
gCurrentArea = NULL;
gWarpTransition.isActive = FALSE;
}
for (i = 0; i < AREA_COUNT; i++) {
if (gAreaData[i].graphNode != NULL) {
#ifndef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
geo_call_global_function_nodes(&gAreaData[i].graphNode->node, GEO_CONTEXT_AREA_INIT);
#endif
gAreaData[i].graphNode = NULL;
}
}
@@ -248,18 +244,14 @@ void load_area(s32 index) {
}
load_obj_warp_nodes();
#ifndef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
geo_call_global_function_nodes(&gCurrentArea->graphNode->node, GEO_CONTEXT_AREA_LOAD);
#endif
}
}
void unload_area(void) {
if (gCurrentArea != NULL) {
unload_objects_from_area(0, gCurrentArea->index);
#ifndef DISABLE_GRAPH_NODE_TYPE_FUNCTIONAL
geo_call_global_function_nodes(&gCurrentArea->graphNode->node, GEO_CONTEXT_AREA_UNLOAD);
#endif
gCurrentArea->flags = AREA_FLAG_UNLOAD;
gCurrentArea = NULL;

View File

@@ -1262,6 +1262,34 @@ void geo_try_process_children(struct GraphNode *node) {
}
}
typedef void (*GeoProcessFunc)();
// See enum 'GraphNodeTypes' in 'graph_node.h'.
static GeoProcessFunc GeoProcessJumpTable[] = {
[GRAPH_NODE_TYPE_ORTHO_PROJECTION ] = geo_process_ortho_projection,
[GRAPH_NODE_TYPE_PERSPECTIVE ] = geo_process_perspective,
[GRAPH_NODE_TYPE_MASTER_LIST ] = geo_process_master_list,
[GRAPH_NODE_TYPE_LEVEL_OF_DETAIL ] = geo_process_level_of_detail,
[GRAPH_NODE_TYPE_SWITCH_CASE ] = geo_process_switch,
[GRAPH_NODE_TYPE_CAMERA ] = geo_process_camera,
[GRAPH_NODE_TYPE_TRANSLATION_ROTATION] = geo_process_translation_rotation,
[GRAPH_NODE_TYPE_TRANSLATION ] = geo_process_translation,
[GRAPH_NODE_TYPE_ROTATION ] = geo_process_rotation,
[GRAPH_NODE_TYPE_OBJECT ] = geo_process_object,
[GRAPH_NODE_TYPE_ANIMATED_PART ] = geo_process_animated_part,
[GRAPH_NODE_TYPE_BILLBOARD ] = geo_process_billboard,
[GRAPH_NODE_TYPE_DISPLAY_LIST ] = geo_process_display_list,
[GRAPH_NODE_TYPE_SCALE ] = geo_process_scale,
[GRAPH_NODE_TYPE_SHADOW ] = geo_process_shadow,
[GRAPH_NODE_TYPE_OBJECT_PARENT ] = geo_process_object_parent,
[GRAPH_NODE_TYPE_GENERATED_LIST ] = geo_process_generated_list,
[GRAPH_NODE_TYPE_BACKGROUND ] = geo_process_background,
[GRAPH_NODE_TYPE_HELD_OBJ ] = geo_process_held_object,
[GRAPH_NODE_TYPE_CULLING_RADIUS ] = geo_try_process_children,
[GRAPH_NODE_TYPE_ROOT ] = geo_try_process_children,
[GRAPH_NODE_TYPE_START ] = geo_try_process_children,
};
/**
* Process a generic geo node and its siblings.
* The first argument is the start node, and all its siblings will
@@ -1283,28 +1311,7 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
if (curGraphNode->flags & GRAPH_RENDER_CHILDREN_FIRST) {
geo_try_process_children(curGraphNode);
} else {
switch (curGraphNode->type) {
case GRAPH_NODE_TYPE_ORTHO_PROJECTION: geo_process_ortho_projection ((struct GraphNodeOrthoProjection *) curGraphNode); break;
case GRAPH_NODE_TYPE_PERSPECTIVE: geo_process_perspective ((struct GraphNodePerspective *) curGraphNode); break;
case GRAPH_NODE_TYPE_MASTER_LIST: geo_process_master_list ((struct GraphNodeMasterList *) curGraphNode); break;
case GRAPH_NODE_TYPE_LEVEL_OF_DETAIL: geo_process_level_of_detail ((struct GraphNodeLevelOfDetail *) curGraphNode); break;
case GRAPH_NODE_TYPE_SWITCH_CASE: geo_process_switch ((struct GraphNodeSwitchCase *) curGraphNode); break;
case GRAPH_NODE_TYPE_CAMERA: geo_process_camera ((struct GraphNodeCamera *) curGraphNode); break;
case GRAPH_NODE_TYPE_TRANSLATION_ROTATION: geo_process_translation_rotation((struct GraphNodeTranslationRotation *) curGraphNode); break;
case GRAPH_NODE_TYPE_TRANSLATION: geo_process_translation ((struct GraphNodeTranslation *) curGraphNode); break;
case GRAPH_NODE_TYPE_ROTATION: geo_process_rotation ((struct GraphNodeRotation *) curGraphNode); break;
case GRAPH_NODE_TYPE_OBJECT: geo_process_object ((struct Object *) curGraphNode); break;
case GRAPH_NODE_TYPE_ANIMATED_PART: geo_process_animated_part ((struct GraphNodeAnimatedPart *) curGraphNode); break;
case GRAPH_NODE_TYPE_BILLBOARD: geo_process_billboard ((struct GraphNodeBillboard *) curGraphNode); break;
case GRAPH_NODE_TYPE_DISPLAY_LIST: geo_process_display_list ((struct GraphNodeDisplayList *) curGraphNode); break;
case GRAPH_NODE_TYPE_SCALE: geo_process_scale ((struct GraphNodeScale *) curGraphNode); break;
case GRAPH_NODE_TYPE_SHADOW: geo_process_shadow ((struct GraphNodeShadow *) curGraphNode); break;
case GRAPH_NODE_TYPE_OBJECT_PARENT: geo_process_object_parent ((struct GraphNodeObjectParent *) curGraphNode); break;
case GRAPH_NODE_TYPE_GENERATED_LIST: geo_process_generated_list ((struct GraphNodeGenerated *) curGraphNode); break;
case GRAPH_NODE_TYPE_BACKGROUND: geo_process_background ((struct GraphNodeBackground *) curGraphNode); break;
case GRAPH_NODE_TYPE_HELD_OBJ: geo_process_held_object ((struct GraphNodeHeldObject *) curGraphNode); break;
default: geo_try_process_children ((struct GraphNode *) curGraphNode); break;
}
GeoProcessJumpTable[curGraphNode->type](curGraphNode);
}
} else {
if (curGraphNode->type == GRAPH_NODE_TYPE_OBJECT) {