From d3a3896efea71b82c82535df483d835f6db5082f Mon Sep 17 00:00:00 2001 From: Ratstail91 Date: Tue, 28 Feb 2023 04:22:37 +1100 Subject: [PATCH] Moved more polyfill code into the engine proper --- Airport.vcxproj | 3 +- assets/scripts/children_test.toy | 30 ++++++ .../scripts/{frames.toy => frames_test.toy} | 0 assets/scripts/init.toy | 2 +- assets/scripts/tilemap/layer-background.toy | 5 - assets/scripts/tilemap/layer-walls.toy | 5 - assets/scripts/tilemap/tilemap.toy | 6 +- box/box_engine_node.c | 58 +++++++----- box/box_engine_node.h | 6 ++ box/lib_node.c | 91 +++++++++++++------ 10 files changed, 139 insertions(+), 67 deletions(-) create mode 100644 assets/scripts/children_test.toy rename assets/scripts/{frames.toy => frames_test.toy} (100%) diff --git a/Airport.vcxproj b/Airport.vcxproj index 0977a38..f3d6c6e 100644 --- a/Airport.vcxproj +++ b/Airport.vcxproj @@ -22,8 +22,9 @@ + - + diff --git a/assets/scripts/children_test.toy b/assets/scripts/children_test.toy new file mode 100644 index 0000000..84397a6 --- /dev/null +++ b/assets/scripts/children_test.toy @@ -0,0 +1,30 @@ +import node; + +//util to generate and init a child node of a given parent +fn makeChild(parent: opaque, fname: string) { + var child: opaque = loadNode(fname); + parent.pushNode(child); + child.initNode(); + return child; +} + +fn onInit(node: opaque) { + for (var i = 0; i < 20; i++) { + node.makeChild("scripts:/tilemap/tile.toy"); + } + + node.freeChildNode(10); + var n = node.getChildNode(10); + + for (var i = 0; i < 20; i++) { + //this would originally prune tombstones... + node.makeChild("scripts:/tilemap/tile.toy"); + } + + print node.getChildNodeCount(); + + var m = node.getChildNode(10); + + print n; + print m; +} \ No newline at end of file diff --git a/assets/scripts/frames.toy b/assets/scripts/frames_test.toy similarity index 100% rename from assets/scripts/frames.toy rename to assets/scripts/frames_test.toy diff --git a/assets/scripts/init.toy b/assets/scripts/init.toy index eddaf2c..8241504 100644 --- a/assets/scripts/init.toy +++ b/assets/scripts/init.toy @@ -28,4 +28,4 @@ mapInputEventToKeyUp("character_right", "right"); //event, keysym initWindow("Airport Game", 1080, 720, false); //kick off the logic of the scene graph -loadRootNode("scripts:/scene.toy"); +loadRootNode("scripts:/children_test.toy"); diff --git a/assets/scripts/tilemap/layer-background.toy b/assets/scripts/tilemap/layer-background.toy index ca4e38d..76b43f2 100644 --- a/assets/scripts/tilemap/layer-background.toy +++ b/assets/scripts/tilemap/layer-background.toy @@ -2,8 +2,6 @@ import standard; import node; -var childCounter: int = 0; - //TODO: reference these from a global source (root?) var tileWidth: int const = 64; var tileHeight: int const = 64; @@ -23,9 +21,6 @@ fn makeChildSprite(parent: opaque, spriteName: string) { child.loadTexture("sprites:/" + spriteName); - //BUGFIX - childCounter++; - return child; } diff --git a/assets/scripts/tilemap/layer-walls.toy b/assets/scripts/tilemap/layer-walls.toy index d11dff7..288d265 100644 --- a/assets/scripts/tilemap/layer-walls.toy +++ b/assets/scripts/tilemap/layer-walls.toy @@ -2,8 +2,6 @@ import standard; import node; -var childCounter: int = 0; - //TODO: reference these from a global source (root?) var tileWidth: int const = 64; var tileHeight: int const = 64; @@ -23,9 +21,6 @@ fn makeChildSprite(parent: opaque, spriteName: string) { child.loadTexture("sprites:/" + spriteName); - //BUGFIX - childCounter++; - return child; } diff --git a/assets/scripts/tilemap/tilemap.toy b/assets/scripts/tilemap/tilemap.toy index f81e7c0..22e3763 100644 --- a/assets/scripts/tilemap/tilemap.toy +++ b/assets/scripts/tilemap/tilemap.toy @@ -2,9 +2,6 @@ import standard; import node; -//TODO: get child count -var childCounter: int = 0; - var camX: float = 0; var camY: float = 0; @@ -33,7 +30,6 @@ fn makeChild(parent: opaque, fname: string) { fn loadLayer(node: opaque, layerName: string) { //load the given layer as a child var layerNode = node.makeChild("scripts:/tilemap/" + layerName); - childCounter++; } var stepCounter = 0; @@ -49,7 +45,7 @@ fn onDraw(node: opaque) { stepCounter = 0; //iterate over each layer, passing in the screen dimensions - for (var c = 0; c < childCounter; c++) { + for (var c = 0; c < node.getChildNodeCount(); c++) { node.getChildNode(c).callNodeFn("drawLayer", camX, camY, screenWidth, screenHeight, c * 4.0); } } diff --git a/box/box_engine_node.c b/box/box_engine_node.c index 5a05f1b..c181be6 100644 --- a/box/box_engine_node.c +++ b/box/box_engine_node.c @@ -12,6 +12,7 @@ void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, cons node->children = NULL; node->capacity = 0; node->count = 0; + node->childCount = 0; node->texture = NULL; node->rect = ((SDL_Rect) { 0, 0, 0, 0 }); node->frames = 0; @@ -40,7 +41,7 @@ void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, cons } void Box_pushEngineNode(Box_EngineNode* node, Box_EngineNode* child) { - //push to the array (prune tombstones when expanding/copying) + //push to the array if (node->count + 1 > node->capacity) { int oldCapacity = node->capacity; @@ -48,25 +49,14 @@ void Box_pushEngineNode(Box_EngineNode* node, Box_EngineNode* child) { node->children = TOY_GROW_ARRAY(Box_EngineNode*, node->children, oldCapacity, node->capacity); } - //prune tombstones (experimental) - int counter = 0; - for (int i = 0; i < node->capacity; i++) { - if (i >= node->count) { - node->count = counter; - break; - } - - //move down - if (node->children[i] != NULL) { - node->children[counter++] = node->children[i]; - } - } - //assign node->children[node->count++] = child; //reverse-assign child->parent = node; + + //count + node->childCount++; } void Box_freeEngineNode(Box_EngineNode* node) { @@ -95,6 +85,28 @@ void Box_freeEngineNode(Box_EngineNode* node) { TOY_FREE(Box_EngineNode, node); } +Box_EngineNode* Box_getChildEngineNode(Box_EngineNode* node, int index) { + if (index < 0 || index > node->count) { + return NULL; + } + + return node->children[index]; +} + +void Box_freeChildEngineNode(Box_EngineNode* node, int index) { + //get the child node + Box_EngineNode* childNode = node->children[index]; + + //free the node + if (childNode != NULL) { + Box_callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL); + Box_freeEngineNode(childNode); + node->childCount--; + } + + node->children[index] = NULL; +} + Toy_Literal Box_callEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args) { Toy_Literal ret = TOY_TO_NULL_LITERAL; @@ -188,6 +200,10 @@ void Box_callRecursiveEngineNode(Box_EngineNode* node, Toy_Interpreter* interpre Toy_freeLiteral(key); } +int Box_getChildCountEngineNode(Box_EngineNode* node) { + return node->childCount; +} + int Box_loadTextureEngineNode(Box_EngineNode* node, const char* fname) { SDL_Surface* surface = IMG_Load(fname); @@ -223,28 +239,28 @@ void Box_setRectEngineNode(Box_EngineNode* node, SDL_Rect rect) { node->rect = rect; } -BOX_API SDL_Rect Box_getRectEngineNode(Box_EngineNode* node) { +SDL_Rect Box_getRectEngineNode(Box_EngineNode* node) { return node->rect; } -BOX_API void Box_setFramesEngineNode(Box_EngineNode* node, int frames) { +void Box_setFramesEngineNode(Box_EngineNode* node, int frames) { node->frames = frames; node->currentFrame = 0; //just in case } -BOX_API int Box_getFramesEngineNode(Box_EngineNode* node) { +int Box_getFramesEngineNode(Box_EngineNode* node) { return node->frames; } -BOX_API void Box_setCurrentFrameEngineNode(Box_EngineNode* node, int currentFrame) { +void Box_setCurrentFrameEngineNode(Box_EngineNode* node, int currentFrame) { node->currentFrame = currentFrame; } -BOX_API int Box_getCurrentFrameEngineNode(Box_EngineNode* node) { +int Box_getCurrentFrameEngineNode(Box_EngineNode* node) { return node->currentFrame; } -BOX_API void Box_incrementCurrentFrame(Box_EngineNode* node) { +void Box_incrementCurrentFrame(Box_EngineNode* node) { node->currentFrame++; if (node->currentFrame >= node->frames) { node->currentFrame = 0; diff --git a/box/box_engine_node.h b/box/box_engine_node.h index b17f7a1..5be8d87 100644 --- a/box/box_engine_node.h +++ b/box/box_engine_node.h @@ -29,6 +29,7 @@ typedef struct Box_private_engineNode { Box_EngineNode** children; int capacity; int count; //includes tombstones + int childCount; //rendering-specific features SDL_Texture* texture; @@ -41,6 +42,9 @@ BOX_API void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpret BOX_API void Box_pushEngineNode(Box_EngineNode* node, Box_EngineNode* child); //push to the array (prune tombstones when expanding/copying) BOX_API void Box_freeEngineNode(Box_EngineNode* node); //free this node and all children +BOX_API Box_EngineNode* Box_getChildEngineNode(Box_EngineNode* node, int index); +BOX_API void Box_freeChildEngineNode(Box_EngineNode* node, int index); + BOX_API Toy_Literal Box_callEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args); BOX_API Toy_Literal Box_callEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and only this node, if it exists @@ -48,6 +52,8 @@ BOX_API Toy_Literal Box_callEngineNode(Box_EngineNode* node, Toy_Interpreter* in BOX_API void Box_callRecursiveEngineNodeLiteral(Box_EngineNode* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args); BOX_API void Box_callRecursiveEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and all children, if it exists +BOX_API int Box_getChildCountEngineNode(Box_EngineNode* node); + BOX_API int Box_loadTextureEngineNode(Box_EngineNode* node, const char* fname); BOX_API void Box_freeTextureEngineNode(Box_EngineNode* node); diff --git a/box/lib_node.c b/box/lib_node.c index 2830aff..9531289 100644 --- a/box/lib_node.c +++ b/box/lib_node.c @@ -191,12 +191,19 @@ static int nativeGetChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* ar return -1; } - Box_EngineNode* childNode = parentNode->children[intIndex]; - Toy_Literal child = TOY_TO_OPAQUE_LITERAL(childNode, childNode->tag); + Box_EngineNode* childNode = Box_getChildEngineNode(parentNode, intIndex); + Toy_Literal child; + + if (childNode == NULL) { + child = TOY_TO_NULL_LITERAL; + } + else { + child = TOY_TO_OPAQUE_LITERAL(childNode, childNode->tag); + } Toy_pushLiteralArray(&interpreter->stack, child); - //no return value + //cleanup Toy_freeLiteral(parent); Toy_freeLiteral(child); Toy_freeLiteral(index); @@ -210,46 +217,37 @@ static int nativeFreeChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* a return -1; } - Toy_Literal index = Toy_popLiteralArray(arguments); - Toy_Literal node = Toy_popLiteralArray(arguments); + Toy_Literal indexLiteral = Toy_popLiteralArray(arguments); + Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); - Toy_Literal nodeIdn = node; //annoying - if (TOY_IS_IDENTIFIER(node) && Toy_parseIdentifierToValue(interpreter, &node)) { - Toy_freeLiteral(nodeIdn); + Toy_Literal nodeLiteralIdn = nodeLiteral; //annoying + if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { + Toy_freeLiteral(nodeLiteralIdn); } //check argument types - if (!TOY_IS_OPAQUE(node) || !TOY_IS_INTEGER(index)) { + if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_INTEGER(indexLiteral)) { interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n"); - Toy_freeLiteral(node); + Toy_freeLiteral(nodeLiteral); return -1; } - Box_EngineNode* parentNode = TOY_AS_OPAQUE(node); - int idx = TOY_AS_INTEGER(index); + Box_EngineNode* node = TOY_AS_OPAQUE(nodeLiteral); + int idx = TOY_AS_INTEGER(indexLiteral); //check bounds - if (idx < 0 || idx >= parentNode->count) { + if (idx < 0 || idx >= node->count) { interpreter->errorOutput("Node index out of bounds in freeChildNode\n"); - Toy_freeLiteral(node); - Toy_freeLiteral(index); + Toy_freeLiteral(nodeLiteral); + Toy_freeLiteral(indexLiteral); return -1; } - //get the child node - Box_EngineNode* childNode = parentNode->children[idx]; - - //free the node - if (childNode != NULL) { - Box_callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL); - Box_freeEngineNode(childNode); - } - - parentNode->children[idx] = NULL; + Box_freeChildEngineNode(node, idx); //cleanup - Toy_freeLiteral(node); - Toy_freeLiteral(index); + Toy_freeLiteral(nodeLiteral); + Toy_freeLiteral(indexLiteral); return 0; } @@ -291,6 +289,40 @@ static int nativeGetParentNode(Toy_Interpreter* interpreter, Toy_LiteralArray* a return 1; } +static int nativeGetChildNodeCount(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + //checks + if (arguments->count != 1) { + interpreter->errorOutput("Incorrect number of arguments passed to getChildNodeCount\n"); + return -1; + } + + Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments); + + Toy_Literal nodeLiteralIdn = nodeLiteral; + if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) { + Toy_freeLiteral(nodeLiteralIdn); + } + + if (!TOY_IS_OPAQUE(nodeLiteral)) { + interpreter->errorOutput("Incorrect argument type passed to getChildNodeCount\n"); + Toy_freeLiteral(nodeLiteral); + return -1; + } + + //get the count + Box_EngineNode* node = TOY_AS_OPAQUE(nodeLiteral); + int childCount = Box_getChildCountEngineNode(node); + Toy_Literal childCountLiteral = TOY_TO_INTEGER_LITERAL(childCount); + + Toy_pushLiteralArray(&interpreter->stack, childCountLiteral); + + //no return value + Toy_freeLiteral(nodeLiteral); + Toy_freeLiteral(childCountLiteral); + + return 0; +} + static int nativeLoadTexture(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { if (arguments->count != 2) { interpreter->errorOutput("Incorrect number of arguments passed to loadTexture\n"); @@ -797,6 +829,7 @@ int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Liter {"getChildNode", nativeGetChildNode}, {"freeChildNode", nativeFreeChildNode}, {"getParentNode", nativeGetParentNode}, + {"getChildNodeCount", nativeGetChildNodeCount}, {"loadTexture", nativeLoadTexture}, {"freeTexture", nativeFreeTexture}, {"setNodeRect", nativeSetNodeRect}, @@ -808,8 +841,8 @@ int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Liter {"incrementCurrentNodeFrame", nativeIncrementCurrentNodeFrame}, {"drawNode", nativeDrawNode}, {"callNodeFn", nativeCallNodeFn}, - - //TODO: get rect, get node var, create empty node, get child count, get root node + + //TODO: get rect, get node var, create empty node, get root node {NULL, NULL}, };