From 0775e56c1b5575eee03cdee812371285226ddf72 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 3 Nov 2022 14:11:22 +0100 Subject: [PATCH] Merged EngineNode and RenderNode --- assets/scripts/render.toy | 11 +- assets/scripts/root.toy | 18 +- core/engine.c | 4 +- core/engine_node.c | 53 ++++- core/engine_node.h | 18 +- core/lib_engine.c | 338 ------------------------------ core/{lib_render.c => lib_node.c} | 315 ++++++++++++++++++++++++---- core/lib_node.h | 6 + core/lib_render.h | 6 - core/render_node.c | 89 -------- core/render_node.h | 43 ---- 11 files changed, 365 insertions(+), 536 deletions(-) rename core/{lib_render.c => lib_node.c} (51%) create mode 100644 core/lib_node.h delete mode 100644 core/lib_render.h delete mode 100644 core/render_node.c delete mode 100644 core/render_node.h diff --git a/assets/scripts/render.toy b/assets/scripts/render.toy index 28d4e96..47a58ff 100644 --- a/assets/scripts/render.toy +++ b/assets/scripts/render.toy @@ -1,19 +1,18 @@ import engine; -import render; +import node; fn onInit(node: opaque) { - node.loadTextureRenderNode("assets/sprites/character.png"); + node.loadTextureEngineNode("assets/sprites/character.png"); } fn onStep(node: opaque) { - //print node.getNodeTag(); - //print node.getNodeParent().getNodeTag(); + // } fn onFree(node: opaque) { - node.freeTextureRenderNode(); + node.freeTextureEngineNode(); } fn onDraw(node: opaque) { - node.drawRenderNode(50, 50, 100, 100); + node.drawEngineNode(50, 50, 100, 100); } \ No newline at end of file diff --git a/assets/scripts/root.toy b/assets/scripts/root.toy index 4a274ba..4b35eba 100644 --- a/assets/scripts/root.toy +++ b/assets/scripts/root.toy @@ -1,6 +1,6 @@ -import standard; +//import standard; import engine; -import render; +import node; fn _makeChild(parent: opaque, fname: string, init: bool) { var child: opaque = loadNode(fname); @@ -14,17 +14,17 @@ fn _makeChild(parent: opaque, fname: string, init: bool) { //root node can load the whole scene, and essentially act as the scene object fn onInit(node: opaque) { - //print "root.toy:onInit() called"; + print "root.toy:onInit() called"; //make a child - //node.makeChild("assets/scripts/child.toy", true); //indicate whether to call "init" on the new node or not - //node.makeChild("assets/scripts/child.toy", false); - //node.makeChild("assets/scripts/child.toy", false); + node.makeChild("assets/scripts/child.toy", true); //indicate whether to call "init" on the new node or not + node.makeChild("assets/scripts/child.toy", false); + node.makeChild("assets/scripts/child.toy", false); //actually, grab that first node and free it - //node.freeChildNode(0); //must be done from the parent node, so it's pointer can be nullified + node.freeChildNode(0); //must be done from the parent node, so it's pointer can be nullified - var r = loadRenderNode("assets/scripts/render.toy"); + var r = loadNode("assets/scripts/render.toy"); node.pushNode(r); } @@ -34,5 +34,5 @@ fn onStep(node: opaque) { } fn onFree(node: opaque) { - //print "root.toy:onFree() called"; + print "root.toy:onFree() called"; } diff --git a/core/engine.c b/core/engine.c index d85e2e0..cef5ef7 100644 --- a/core/engine.c +++ b/core/engine.c @@ -1,8 +1,8 @@ #include "engine.h" #include "lib_engine.h" -#include "lib_render.h" #include "lib_input.h" +#include "lib_node.h" #include "lib_standard.h" #include "repl_tools.h" @@ -43,7 +43,7 @@ void initEngine() { //init Toy initInterpreter(&engine.interpreter); injectNativeHook(&engine.interpreter, "engine", hookEngine); - injectNativeHook(&engine.interpreter, "render", hookRender); + injectNativeHook(&engine.interpreter, "node", hookNode); injectNativeHook(&engine.interpreter, "input", hookInput); injectNativeHook(&engine.interpreter, "standard", hookStandard); diff --git a/core/engine_node.c b/core/engine_node.c index 025c336..95b6ea8 100644 --- a/core/engine_node.c +++ b/core/engine_node.c @@ -1,14 +1,16 @@ #include "engine_node.h" +#include "engine.h" + #include "memory.h" -STATIC_ASSERT(sizeof(EngineNode) == 48); -STATIC_ASSERT(sizeof(EngineNodeCallback) == 8); -STATIC_ASSERT(sizeof(LiteralDictionary*) == 8); -STATIC_ASSERT(sizeof(EngineNode*) == 8); -STATIC_ASSERT(sizeof(int) == 4); +STATIC_ASSERT(sizeof(EngineNode) == 72); static void freeMemory(void* ptr) { + EngineNode* node = (EngineNode*)ptr; + //SDL stuff + SDL_DestroyTexture(node->texture); + //free this node type's memory FREE(EngineNode, ptr); } @@ -22,13 +24,14 @@ void initEngineNode(EngineNode* node, Interpreter* interpreter, void* tb, size_t node->children = NULL; node->capacity = 0; node->count = 0; + node->texture = NULL; initLiteralDictionary(node->functions); //run bytecode runInterpreter(interpreter, tb, size); - //grab all top-level function literals + //grab all top-level functions from the dirty interpreter LiteralDictionary* variablesPtr = &interpreter->scope->variables; for (int i = 0; i < variablesPtr->capacity; i++) { @@ -136,3 +139,41 @@ void callEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName) { freeLiteral(key); } + +int loadTextureEngineNode(EngineNode* node, char* fname) { + SDL_Surface* surface = IMG_Load(fname); + + if (surface == NULL) { + return -1; + } + + node->texture = SDL_CreateTextureFromSurface(engine.renderer, surface); + + if (node->texture == NULL) { + return -2; + } + + SDL_FreeSurface(surface); + + int w, h; + SDL_QueryTexture(node->texture, NULL, NULL, &w, &h); + SDL_Rect r = { 0, 0, w, h }; + setRectEngineNode(node, r); + + return 0; +} + +void freeTextureEngineNode(EngineNode* node) { + if (node->texture != NULL) { + SDL_DestroyTexture(node->texture); + node->texture = NULL; + } +} + +void setRectEngineNode(EngineNode* node, SDL_Rect rect) { + node->rect = rect; +} + +void drawEngineNode(EngineNode* node, SDL_Rect dest) { + SDL_RenderCopy(engine.renderer, node->texture, &node->rect, &dest); +} diff --git a/core/engine_node.h b/core/engine_node.h index 2572c17..c871e2a 100644 --- a/core/engine_node.h +++ b/core/engine_node.h @@ -5,6 +5,9 @@ #include "literal_dictionary.h" #include "interpreter.h" +#include +#include + #define OPAQUE_TAG_ENGINE_NODE 1 //forward declare @@ -24,16 +27,29 @@ typedef struct _engineNode { //my opaque type tag int tag; - int _unused; + int _unused0; //use Toy's memory model EngineNode** children; int capacity; int count; //includes tombstones + + //rendering-specific features + SDL_Texture* texture; + SDL_Rect rect; + //TODO: depth } EngineNode; CORE_API void initEngineNode(EngineNode* node, Interpreter* interpreter, void* tb, size_t size); //run bytecode, then grab all top-level function literals CORE_API void pushEngineNode(EngineNode* node, EngineNode* child); //push to the array (prune tombstones when expanding/copying) CORE_API void freeEngineNode(EngineNode* node); //free and tombstone this node +//TODO: replace calling system with a better version CORE_API void callEngineNode(EngineNode* node, Interpreter* interpreter, char* fnName); //call "fnName" on this node, and all children, if it exists + +CORE_API int loadTextureEngineNode(EngineNode* node, char* fname); +CORE_API void freeTextureEngineNode(EngineNode* node); + +CORE_API void setRectEngineNode(EngineNode* node, SDL_Rect rect); +//TODO: getRect +CORE_API void drawEngineNode(EngineNode* node, SDL_Rect dest); diff --git a/core/lib_engine.c b/core/lib_engine.c index da8dcd8..4fa2b32 100644 --- a/core/lib_engine.c +++ b/core/lib_engine.c @@ -147,336 +147,6 @@ static int nativeLoadRootNode(Interpreter* interpreter, LiteralArray* arguments) return 0; } -static int nativeLoadNode(Interpreter* interpreter, LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to loadNode\n"); - return -1; - } - - //extract the arguments - Literal fname = popLiteralArray(arguments); - - Literal fnameIdn = fname; - if (IS_IDENTIFIER(fname) && parseIdentifierToValue(interpreter, &fname)) { - freeLiteral(fnameIdn); - } - - //check argument types - if (!IS_STRING(fname)) { - interpreter->errorOutput("Incorrect argument type passed to loadNode\n"); - freeLiteral(fname); - return -1; - } - - //load the new node - size_t size = 0; - char* source = readFile(AS_STRING(fname), &size); - unsigned char* tb = compileString(source, &size); - free((void*)source); - - EngineNode* node = ALLOCATE(EngineNode, 1); - - //BUGFIX: make an inner-interpreter - Interpreter inner; - - //init the inner interpreter manually - initLiteralArray(&inner.literalCache); - inner.scope = pushScope(NULL); - inner.bytecode = tb; - inner.length = size; - inner.count = 0; - inner.codeStart = -1; - inner.depth = interpreter->depth + 1; - inner.panic = false; - initLiteralArray(&inner.stack); - inner.exports = interpreter->exports; - inner.exportTypes = interpreter->exportTypes; - inner.hooks = interpreter->hooks; - setInterpreterPrint(&inner, interpreter->printOutput); - setInterpreterAssert(&inner, interpreter->assertOutput); - setInterpreterError(&inner, interpreter->errorOutput); - - initEngineNode(node, &inner, tb, size); - - // return the node - Literal nodeLiteral = TO_OPAQUE_LITERAL(node, node->tag); - pushLiteralArray(&interpreter->stack, nodeLiteral); - - //cleanup - freeLiteralArray(&inner.stack); - freeLiteralArray(&inner.literalCache); - freeLiteral(fname); - freeLiteral(nodeLiteral); - - return 1; -} - -static int nativeInitNode(Interpreter* interpreter, LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to initNode\n"); - return -1; - } - - Literal node = popLiteralArray(arguments); - - Literal nodeIdn = node; - if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) { - freeLiteral(nodeIdn); - } - - //check argument types - if (!IS_OPAQUE(node)) { - interpreter->errorOutput("Incorrect argument type passed to initNode\n"); - freeLiteral(node); - return -1; - } - - EngineNode* engineNode = AS_OPAQUE(node); - - //init the new node - callEngineNode(engineNode, &engine.interpreter, "onInit"); - - //cleanup - freeLiteral(node); - return 0; -} - -static int nativeFreeNode(Interpreter* interpreter, LiteralArray* arguments) { - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to freeNode\n"); - return -1; - } - - Literal node = popLiteralArray(arguments); - - Literal nodeIdn = node; - if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) { - freeLiteral(nodeIdn); - } - - //check argument types - if (!IS_OPAQUE(node)) { - interpreter->errorOutput("Incorrect argument type passed to freeNode\n"); - freeLiteral(node); - return -1; - } - - EngineNode* engineNode = AS_OPAQUE(node); - - //free the node - callEngineNode(engineNode, &engine.interpreter, "onFree"); - freeEngineNode(engineNode); - - //cleanup - freeLiteral(node); - return 0; -} - -static int nativeFreeChildNode(Interpreter* interpreter, LiteralArray* arguments) { - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to freeChildNode\n"); - return -1; - } - - Literal index = popLiteralArray(arguments); - Literal node = popLiteralArray(arguments); - - Literal nodeIdn = node; //annoying - if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) { - freeLiteral(nodeIdn); - } - - //check argument types - if (!IS_OPAQUE(node) || !IS_INTEGER(index)) { - interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n"); - freeLiteral(node); - return -1; - } - - EngineNode* parentNode = AS_OPAQUE(node); - int idx = AS_INTEGER(index); - - //check bounds - if (idx < 0 || idx >= parentNode->count) { - interpreter->errorOutput("Node index out of bounds in freeChildNode\n"); - freeLiteral(node); - freeLiteral(index); - return -1; - } - - //get the child node - EngineNode* childNode = parentNode->children[idx]; - - //free the node - if (childNode != NULL) { - callEngineNode(childNode, &engine.interpreter, "onFree"); - freeEngineNode(childNode); - } - - parentNode->children[idx] = NULL; - - //cleanup - freeLiteral(node); - freeLiteral(index); - return 0; -} - -static int nativePushNode(Interpreter* interpreter, LiteralArray* arguments) { - //checks - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to pushNode\n"); - return -1; - } - - Literal child = popLiteralArray(arguments); - Literal parent = popLiteralArray(arguments); - - Literal parentIdn = parent; - if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) { - freeLiteral(parentIdn); - } - - Literal childIdn = child; - if (IS_IDENTIFIER(child) && parseIdentifierToValue(interpreter, &child)) { - freeLiteral(childIdn); - } - - if (!IS_OPAQUE(parent) || !IS_OPAQUE(child)) { - interpreter->errorOutput("Incorrect argument type passed to pushNode\n"); - freeLiteral(parent); - freeLiteral(child); - return -1; - } - - //push the node - EngineNode* parentNode = AS_OPAQUE(parent); - EngineNode* childNode = AS_OPAQUE(child); - - pushEngineNode(parentNode, childNode); - - //no return value - freeLiteral(parent); - freeLiteral(child); - - return 0; -} - -static int nativeGetNode(Interpreter* interpreter, LiteralArray* arguments) { - //checks - if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to getNode\n"); - return -1; - } - - Literal index = popLiteralArray(arguments); - Literal parent = popLiteralArray(arguments); - - Literal parentIdn = parent; - if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) { - freeLiteral(parentIdn); - } - - if (!IS_OPAQUE(parent) || !IS_INTEGER(index)) { - interpreter->errorOutput("Incorrect argument type passed to getNode\n"); - freeLiteral(parent); - freeLiteral(index); - return -1; - } - - //push the node - EngineNode* parentNode = AS_OPAQUE(parent); - int intIndex = AS_INTEGER(index); - - if (intIndex < 0 || intIndex >= parentNode->count) { - interpreter->errorOutput("index out of bounds in getNode\n"); - freeLiteral(parent); - freeLiteral(index); - return -1; - } - - EngineNode* childNode = parentNode->children[intIndex]; - Literal child = TO_OPAQUE_LITERAL(childNode, childNode->tag); - - pushLiteralArray(&interpreter->stack, child); - - //no return value - freeLiteral(parent); - freeLiteral(child); - freeLiteral(index); - - return 1; -} - -static int nativeGetNodeParent(Interpreter* interpreter, LiteralArray* arguments) { - //checks - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeParent\n"); - return -1; - } - - Literal nodeLiteral = popLiteralArray(arguments); - - Literal nodeIdn = nodeLiteral; - if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) { - freeLiteral(nodeIdn); - } - - if (!IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeParent\n"); - freeLiteral(nodeLiteral); - return -1; - } - - //push the node - EngineNode* node = AS_OPAQUE(nodeLiteral); - EngineNode* parent = node->parent; - - Literal parentLiteral = TO_NULL_LITERAL; - if (parent != NULL) { - parentLiteral = TO_OPAQUE_LITERAL(parent, parent->tag); - } - - pushLiteralArray(&interpreter->stack, parentLiteral); - - //cleanup - freeLiteral(parentLiteral); - freeLiteral(nodeLiteral); - - return 1; -} - -static int nativeGetNodeTag(Interpreter* interpreter, LiteralArray* arguments) { - //checks - if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to getNodeTag\n"); - return -1; - } - - Literal nodeLiteral = popLiteralArray(arguments); - - Literal nodeIdn = nodeLiteral; - if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) { - freeLiteral(nodeIdn); - } - - if (!IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to getNodeTag\n"); - freeLiteral(nodeLiteral); - return -1; - } - - //push the tag - Literal tagLiteral = TO_INTEGER_LITERAL( ((EngineNode*)AS_OPAQUE(nodeLiteral))->tag ); - - pushLiteralArray(&interpreter->stack, tagLiteral); - - //cleanup - freeLiteral(nodeLiteral); - freeLiteral(tagLiteral); - - return 1; -} - //call the hook typedef struct Natives { char* name; @@ -488,14 +158,6 @@ int hookEngine(Interpreter* interpreter, Literal identifier, Literal alias) { Natives natives[] = { {"initWindow", nativeInitWindow}, {"loadRootNode", nativeLoadRootNode}, - {"loadNode", nativeLoadNode}, - {"_initNode", nativeInitNode}, - // {"freeNode", nativeFreeNode}, - {"_freeChildNode", nativeFreeChildNode}, - {"_pushNode", nativePushNode}, - {"_getNode", nativeGetNode}, - {"_getNodeParent", nativeGetNodeParent}, - {"_getNodeTag", nativeGetNodeTag}, {NULL, NULL} }; diff --git a/core/lib_render.c b/core/lib_node.c similarity index 51% rename from core/lib_render.c rename to core/lib_node.c index 2d8689b..abb88f8 100644 --- a/core/lib_render.c +++ b/core/lib_node.c @@ -1,15 +1,17 @@ -#include "lib_render.h" -#include "render_node.h" +#include "lib_node.h" #include "engine.h" +#include "engine_node.h" #include "repl_tools.h" #include "memory.h" #include "literal_array.h" -static int nativeLoadRenderNode(Interpreter* interpreter, LiteralArray* arguments) { +#include + +static int nativeLoadNode(Interpreter* interpreter, LiteralArray* arguments) { if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to loadRenderNode\n"); + interpreter->errorOutput("Incorrect number of arguments passed to loadNode\n"); return -1; } @@ -23,7 +25,7 @@ static int nativeLoadRenderNode(Interpreter* interpreter, LiteralArray* argument //check argument types if (!IS_STRING(fname)) { - interpreter->errorOutput("Incorrect argument type passed to loadRenderNode\n"); + interpreter->errorOutput("Incorrect argument type passed to loadNode\n"); freeLiteral(fname); return -1; } @@ -34,7 +36,7 @@ static int nativeLoadRenderNode(Interpreter* interpreter, LiteralArray* argument unsigned char* tb = compileString(source, &size); free((void*)source); - RenderNode* node = ALLOCATE(RenderNode, 1); + EngineNode* node = ALLOCATE(EngineNode, 1); //BUGFIX: make an inner-interpreter Interpreter inner; @@ -56,7 +58,7 @@ static int nativeLoadRenderNode(Interpreter* interpreter, LiteralArray* argument setInterpreterAssert(&inner, interpreter->assertOutput); setInterpreterError(&inner, interpreter->errorOutput); - initRenderNode(node, &inner, tb, size); + initEngineNode(node, &inner, tb, size); // return the node Literal nodeLiteral = TO_OPAQUE_LITERAL(node, node->tag); @@ -71,9 +73,212 @@ static int nativeLoadRenderNode(Interpreter* interpreter, LiteralArray* argument return 1; } -static int nativeLoadTextureRenderNode(Interpreter* interpreter, LiteralArray* arguments) { +static int nativeInitNode(Interpreter* interpreter, LiteralArray* arguments) { + if (arguments->count != 1) { + interpreter->errorOutput("Incorrect number of arguments passed to initNode\n"); + return -1; + } + + Literal node = popLiteralArray(arguments); + + Literal nodeIdn = node; + if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) { + freeLiteral(nodeIdn); + } + + //check argument types + if (!IS_OPAQUE(node)) { + interpreter->errorOutput("Incorrect argument type passed to initNode\n"); + freeLiteral(node); + return -1; + } + + EngineNode* engineNode = AS_OPAQUE(node); + + //init the new node + callEngineNode(engineNode, &engine.interpreter, "onInit"); + + //cleanup + freeLiteral(node); + return 0; +} + +static int nativeFreeChildNode(Interpreter* interpreter, LiteralArray* arguments) { if (arguments->count != 2) { - interpreter->errorOutput("Incorrect number of arguments passed to loadTextureRenderNode\n"); + interpreter->errorOutput("Incorrect number of arguments passed to freeChildNode\n"); + return -1; + } + + Literal index = popLiteralArray(arguments); + Literal node = popLiteralArray(arguments); + + Literal nodeIdn = node; //annoying + if (IS_IDENTIFIER(node) && parseIdentifierToValue(interpreter, &node)) { + freeLiteral(nodeIdn); + } + + //check argument types + if (!IS_OPAQUE(node) || !IS_INTEGER(index)) { + interpreter->errorOutput("Incorrect argument type passed to freeChildNode\n"); + freeLiteral(node); + return -1; + } + + EngineNode* parentNode = AS_OPAQUE(node); + int idx = AS_INTEGER(index); + + //check bounds + if (idx < 0 || idx >= parentNode->count) { + interpreter->errorOutput("Node index out of bounds in freeChildNode\n"); + freeLiteral(node); + freeLiteral(index); + return -1; + } + + //get the child node + EngineNode* childNode = parentNode->children[idx]; + + //free the node + if (childNode != NULL) { + callEngineNode(childNode, &engine.interpreter, "onFree"); + freeEngineNode(childNode); + } + + parentNode->children[idx] = NULL; + + //cleanup + freeLiteral(node); + freeLiteral(index); + return 0; +} + +static int nativePushNode(Interpreter* interpreter, LiteralArray* arguments) { + //checks + if (arguments->count != 2) { + interpreter->errorOutput("Incorrect number of arguments passed to pushNode\n"); + return -1; + } + + Literal child = popLiteralArray(arguments); + Literal parent = popLiteralArray(arguments); + + Literal parentIdn = parent; + if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) { + freeLiteral(parentIdn); + } + + Literal childIdn = child; + if (IS_IDENTIFIER(child) && parseIdentifierToValue(interpreter, &child)) { + freeLiteral(childIdn); + } + + if (!IS_OPAQUE(parent) || !IS_OPAQUE(child)) { + interpreter->errorOutput("Incorrect argument type passed to pushNode\n"); + freeLiteral(parent); + freeLiteral(child); + return -1; + } + + //push the node + EngineNode* parentNode = AS_OPAQUE(parent); + EngineNode* childNode = AS_OPAQUE(child); + + pushEngineNode(parentNode, childNode); + + //no return value + freeLiteral(parent); + freeLiteral(child); + + return 0; +} + +static int nativeGetNodeChild(Interpreter* interpreter, LiteralArray* arguments) { + //checks + if (arguments->count != 2) { + interpreter->errorOutput("Incorrect number of arguments passed to getNode\n"); + return -1; + } + + Literal index = popLiteralArray(arguments); + Literal parent = popLiteralArray(arguments); + + Literal parentIdn = parent; + if (IS_IDENTIFIER(parent) && parseIdentifierToValue(interpreter, &parent)) { + freeLiteral(parentIdn); + } + + if (!IS_OPAQUE(parent) || !IS_INTEGER(index)) { + interpreter->errorOutput("Incorrect argument type passed to getNode\n"); + freeLiteral(parent); + freeLiteral(index); + return -1; + } + + //push the node + EngineNode* parentNode = AS_OPAQUE(parent); + int intIndex = AS_INTEGER(index); + + if (intIndex < 0 || intIndex >= parentNode->count) { + interpreter->errorOutput("index out of bounds in getNode\n"); + freeLiteral(parent); + freeLiteral(index); + return -1; + } + + EngineNode* childNode = parentNode->children[intIndex]; + Literal child = TO_OPAQUE_LITERAL(childNode, childNode->tag); + + pushLiteralArray(&interpreter->stack, child); + + //no return value + freeLiteral(parent); + freeLiteral(child); + freeLiteral(index); + + return 1; +} + +static int nativeGetNodeParent(Interpreter* interpreter, LiteralArray* arguments) { + //checks + if (arguments->count != 1) { + interpreter->errorOutput("Incorrect number of arguments passed to getNodeParent\n"); + return -1; + } + + Literal nodeLiteral = popLiteralArray(arguments); + + Literal nodeIdn = nodeLiteral; + if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) { + freeLiteral(nodeIdn); + } + + if (!IS_OPAQUE(nodeLiteral)) { + interpreter->errorOutput("Incorrect argument type passed to getNodeParent\n"); + freeLiteral(nodeLiteral); + return -1; + } + + //push the node + EngineNode* node = AS_OPAQUE(nodeLiteral); + EngineNode* parent = node->parent; + + Literal parentLiteral = TO_NULL_LITERAL; + if (parent != NULL) { + parentLiteral = TO_OPAQUE_LITERAL(parent, parent->tag); + } + + pushLiteralArray(&interpreter->stack, parentLiteral); + + //cleanup + freeLiteral(parentLiteral); + freeLiteral(nodeLiteral); + + return 1; +} + +static int nativeLoadTextureEngineNode(Interpreter* interpreter, LiteralArray* arguments) { + if (arguments->count != 2) { + interpreter->errorOutput("Incorrect number of arguments passed to loadTextureEngineNode\n"); return -1; } @@ -93,21 +298,21 @@ static int nativeLoadTextureRenderNode(Interpreter* interpreter, LiteralArray* a //check argument types if (!IS_STRING(fname) || !IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to loadTextureRenderNode\n"); + interpreter->errorOutput("Incorrect argument type passed to loadTextureEngineNode\n"); freeLiteral(fname); freeLiteral(nodeLiteral); return -1; } //actually load TODO: number the opaques, and check the numbers - RenderNode* node = (RenderNode*)AS_OPAQUE(nodeLiteral); + EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral); if (node->texture != NULL) { - freeTextureRenderNode(node); + freeTextureEngineNode(node); } - if (loadTextureRenderNode(node, AS_STRING(fname)) != 0) { - interpreter->errorOutput("Failed to load the texture into the RenderNode\n"); + if (loadTextureEngineNode(node, AS_STRING(fname)) != 0) { + interpreter->errorOutput("Failed to load the texture into the EngineNode\n"); freeLiteral(fname); freeLiteral(nodeLiteral); return -1; @@ -119,9 +324,9 @@ static int nativeLoadTextureRenderNode(Interpreter* interpreter, LiteralArray* a return 0; } -static int nativeFreeTextureRenderNode(Interpreter* interpreter, LiteralArray* arguments) { +static int nativeFreeTextureEngineNode(Interpreter* interpreter, LiteralArray* arguments) { if (arguments->count != 1) { - interpreter->errorOutput("Incorrect number of arguments passed to freeTextureRenderNode\n"); + interpreter->errorOutput("Incorrect number of arguments passed to freeTextureEngineNode\n"); return -1; } @@ -135,16 +340,16 @@ static int nativeFreeTextureRenderNode(Interpreter* interpreter, LiteralArray* a //check argument types if (!IS_OPAQUE(nodeLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to freeTextureRenderNode\n"); + interpreter->errorOutput("Incorrect argument type passed to freeTextureEngineNode\n"); freeLiteral(nodeLiteral); return -1; } //actually load TODO: number the opaques, and check the numbers - RenderNode* node = (RenderNode*)AS_OPAQUE(nodeLiteral); + EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral); if (node->texture != NULL) { - freeTextureRenderNode(node); + freeTextureEngineNode(node); } //cleanup @@ -152,9 +357,9 @@ static int nativeFreeTextureRenderNode(Interpreter* interpreter, LiteralArray* a return 0; } -static int nativeSetRectRenderNode(Interpreter* interpreter, LiteralArray* arguments) { +static int nativeSetRectEngineNode(Interpreter* interpreter, LiteralArray* arguments) { if (arguments->count != 5) { - interpreter->errorOutput("Incorrect number of arguments passed to setRectRenderNode\n"); + interpreter->errorOutput("Incorrect number of arguments passed to setRectEngineNode\n"); return -1; } @@ -192,7 +397,7 @@ static int nativeSetRectRenderNode(Interpreter* interpreter, LiteralArray* argum //check argument types if (!IS_OPAQUE(nodeLiteral) || !IS_INTEGER(x) || !IS_INTEGER(y) || !IS_INTEGER(w) || !IS_INTEGER(h)) { - interpreter->errorOutput("Incorrect argument type passed to setRectRenderNode\n"); + interpreter->errorOutput("Incorrect argument type passed to setRectEngineNode\n"); freeLiteral(nodeLiteral); freeLiteral(x); freeLiteral(y); @@ -202,10 +407,10 @@ static int nativeSetRectRenderNode(Interpreter* interpreter, LiteralArray* argum } //actually set - RenderNode* node = (RenderNode*)AS_OPAQUE(nodeLiteral); + EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral); SDL_Rect r = {AS_INTEGER(x), AS_INTEGER(y), AS_INTEGER(w), AS_INTEGER(h)}; - setRectRenderNode(node, r); + setRectEngineNode(node, r); //cleanup freeLiteral(nodeLiteral); @@ -218,9 +423,9 @@ static int nativeSetRectRenderNode(Interpreter* interpreter, LiteralArray* argum //TODO: get x, y, w, h -static int nativeDrawRenderNode(Interpreter* interpreter, LiteralArray* arguments) { +static int nativeDrawEngineNode(Interpreter* interpreter, LiteralArray* arguments) { if (arguments->count != 3 && arguments->count != 5) { - interpreter->errorOutput("Incorrect number of arguments passed to drawRenderNode\n"); + interpreter->errorOutput("Incorrect number of arguments passed to drawEngineNode\n"); return -1; } @@ -262,7 +467,7 @@ static int nativeDrawRenderNode(Interpreter* interpreter, LiteralArray* argument //check argument types if (!IS_OPAQUE(nodeLiteral) || !IS_INTEGER(x) || !IS_INTEGER(y) || (!IS_INTEGER(w) && !IS_NULL(w)) || (!IS_INTEGER(h) && !IS_NULL(h))) { - interpreter->errorOutput("Incorrect argument type passed to drawRenderNode\n"); + interpreter->errorOutput("Incorrect argument type passed to drawEngineNode\n"); freeLiteral(nodeLiteral); freeLiteral(x); freeLiteral(y); @@ -272,7 +477,7 @@ static int nativeDrawRenderNode(Interpreter* interpreter, LiteralArray* argument } //actually render - RenderNode* node = (RenderNode*)AS_OPAQUE(nodeLiteral); + EngineNode* node = (EngineNode*)AS_OPAQUE(nodeLiteral); SDL_Rect r = {AS_INTEGER(x), AS_INTEGER(y), 0, 0}; if (IS_INTEGER(w) && IS_INTEGER(h)) { @@ -284,7 +489,7 @@ static int nativeDrawRenderNode(Interpreter* interpreter, LiteralArray* argument r.h = node->rect.h; } - drawRenderNode(node, r); + drawEngineNode(node, r); //cleanup freeLiteral(nodeLiteral); @@ -295,21 +500,59 @@ static int nativeDrawRenderNode(Interpreter* interpreter, LiteralArray* argument return 0; } +static int nativeGetNodeTag(Interpreter* interpreter, LiteralArray* arguments) { + //checks + if (arguments->count != 1) { + interpreter->errorOutput("Incorrect number of arguments passed to getNodeTag\n"); + return -1; + } + + Literal nodeLiteral = popLiteralArray(arguments); + + Literal nodeIdn = nodeLiteral; + if (IS_IDENTIFIER(nodeLiteral) && parseIdentifierToValue(interpreter, &nodeLiteral)) { + freeLiteral(nodeIdn); + } + + if (!IS_OPAQUE(nodeLiteral)) { + interpreter->errorOutput("Incorrect argument type passed to getNodeTag\n"); + freeLiteral(nodeLiteral); + return -1; + } + + //push the tag + Literal tagLiteral = TO_INTEGER_LITERAL( ((EngineNode*)AS_OPAQUE(nodeLiteral))->tag ); + + pushLiteralArray(&interpreter->stack, tagLiteral); + + //cleanup + freeLiteral(nodeLiteral); + freeLiteral(tagLiteral); + + return 1; +} + //call the hook typedef struct Natives { char* name; NativeFn fn; } Natives; -int hookRender(Interpreter* interpreter, Literal identifier, Literal alias) { +int hookNode(Interpreter* interpreter, Literal identifier, Literal alias) { //build the natives list Natives natives[] = { - {"loadRenderNode", nativeLoadRenderNode}, - {"_loadTextureRenderNode", nativeLoadTextureRenderNode}, - {"_freeTextureRenderNode", nativeFreeTextureRenderNode}, - {"_setRectRenderNode", nativeSetRectRenderNode}, - {"_drawRenderNode", nativeDrawRenderNode}, - {NULL, NULL} + {"loadNode", nativeLoadNode}, + {"_initNode", nativeInitNode}, + {"_freeChildNode", nativeFreeChildNode}, + {"_pushNode", nativePushNode}, + {"_getNodeChild", nativeGetNodeChild}, + {"_getNodeParent", nativeGetNodeParent}, + {"_loadTextureEngineNode", nativeLoadTextureEngineNode}, + {"_freeTextureEngineNode", nativeFreeTextureEngineNode}, + {"_setRectEngineNode", nativeSetRectEngineNode}, + {"_drawEngineNode", nativeDrawEngineNode}, + // {"getNodeTag", nativeGetNodeTag}, //not needed if there's only one node type + {NULL, NULL}, }; //store the library in an aliased dictionary diff --git a/core/lib_node.h b/core/lib_node.h new file mode 100644 index 0000000..b98c24d --- /dev/null +++ b/core/lib_node.h @@ -0,0 +1,6 @@ +#pragma once + +#include "interpreter.h" + +int hookNode(Interpreter* interpreter, Literal identifier, Literal alias); + diff --git a/core/lib_render.h b/core/lib_render.h deleted file mode 100644 index a8d9a3e..0000000 --- a/core/lib_render.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "interpreter.h" - -int hookRender(Interpreter* interpreter, Literal identifier, Literal alias); - diff --git a/core/render_node.c b/core/render_node.c deleted file mode 100644 index b0c306f..0000000 --- a/core/render_node.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "render_node.h" - -#include "engine.h" -#include "memory.h" - -#include - -static void freeMemory(void* ptr) { - RenderNode* node = (RenderNode*)ptr; - - SDL_DestroyTexture(node->texture); - - //free this node type's memory - FREE(RenderNode, ptr); -} - -//duplicate the initEngineNode() functionality, plus extra stuff -void initRenderNode(RenderNode* node, Interpreter* interpreter, void* tb, size_t size) { - //init - node->freeMemory = freeMemory; - node->functions = ALLOCATE(LiteralDictionary, 1); - node->parent = NULL; - node->tag = OPAQUE_TAG_RENDER_NODE; - node->children = NULL; - node->capacity = 0; - node->count = 0; - - node->texture = NULL; - - initLiteralDictionary(node->functions); - - //run bytecode - runInterpreter(interpreter, tb, size); - - //grab all top-level function literals - LiteralDictionary* variablesPtr = &interpreter->scope->variables; - - for (int i = 0; i < variablesPtr->capacity; i++) { - //skip empties and tombstones - if (IS_NULL(variablesPtr->entries[i].key)) { - continue; - } - - //if this variable is a function - _entry* entry = &variablesPtr->entries[i]; - if (IS_FUNCTION(entry->value)) { - //save a copy - setLiteralDictionary(node->functions, entry->key, entry->value); - } - } -} - -int loadTextureRenderNode(RenderNode* node, char* fname) { - SDL_Surface* surface = IMG_Load(fname); - - if (surface == NULL) { - return -1; - } - - node->texture = SDL_CreateTextureFromSurface(engine.renderer, surface); - - if (node->texture == NULL) { - return -2; - } - - SDL_FreeSurface(surface); - - int w, h; - SDL_QueryTexture(node->texture, NULL, NULL, &w, &h); - SDL_Rect r = { 0, 0, w, h }; - setRectRenderNode(node, r); - - return 0; -} - -void freeTextureRenderNode(RenderNode* node) { - if (node->texture != NULL) { - SDL_DestroyTexture(node->texture); - node->texture = NULL; - } -} - -void setRectRenderNode(RenderNode* node, SDL_Rect rect) { - node->rect = rect; -} - -void drawRenderNode(RenderNode* node, SDL_Rect dest) { - SDL_RenderCopy(engine.renderer, node->texture, &node->rect, &dest); -} diff --git a/core/render_node.h b/core/render_node.h deleted file mode 100644 index 038a0a4..0000000 --- a/core/render_node.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "common.h" - -//mimic the engine node -#include "engine_node.h" - -#include - -#define OPAQUE_TAG_RENDER_NODE 2 - -typedef struct _renderNode { - //function for releasing memory - EngineNodeCallback freeMemory; - - //toy functions, stored in a dict for flexibility - LiteralDictionary* functions; - - //point to the parent - EngineNode* parent; - - //my opaque type tag - int tag; - int _unused; - - //use Toy's memory model - EngineNode** children; - int capacity; - int count; //includes tombstones - - //RenderNode-specific features - SDL_Texture* texture; - SDL_Rect rect; - //TODO: depth -} RenderNode; - -CORE_API void initRenderNode(RenderNode* node, Interpreter* interpreter, void* tb, size_t size); -CORE_API int loadTextureRenderNode(RenderNode* node, char* fname); -CORE_API void freeTextureRenderNode(RenderNode* node); - -CORE_API void setRectRenderNode(RenderNode* node, SDL_Rect rect); -//TODO: getRectRenderNode -CORE_API void drawRenderNode(RenderNode* node, SDL_Rect dest);