Merged EngineNode and RenderNode

This commit is contained in:
2022-11-03 14:11:22 +01:00
parent 4ea1bd572a
commit 0775e56c1b
11 changed files with 365 additions and 536 deletions

View File

@@ -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);
}

View File

@@ -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";
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -5,6 +5,9 @@
#include "literal_dictionary.h"
#include "interpreter.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#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);

View File

@@ -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}
};

View File

@@ -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 <stdlib.h>
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

6
core/lib_node.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include "interpreter.h"
int hookNode(Interpreter* interpreter, Literal identifier, Literal alias);

View File

@@ -1,6 +0,0 @@
#pragma once
#include "interpreter.h"
int hookRender(Interpreter* interpreter, Literal identifier, Literal alias);

View File

@@ -1,89 +0,0 @@
#include "render_node.h"
#include "engine.h"
#include "memory.h"
#include <SDL2/SDL_image.h>
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);
}

View File

@@ -1,43 +0,0 @@
#pragma once
#include "common.h"
//mimic the engine node
#include "engine_node.h"
#include <SDL2/SDL.h>
#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);