Added scene reloading & switching
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
//the overarching scene
|
//the overarching scene
|
||||||
|
import engine;
|
||||||
import node;
|
import node;
|
||||||
|
|
||||||
//debugging tools
|
//debugging tools
|
||||||
@@ -42,6 +43,13 @@ fn onDraw(node: opaque) {
|
|||||||
stepCounter = 0;
|
stepCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn onMouseButtonDown(node: opaque, x: int, y: int, button: string) {
|
||||||
|
//reload the scene on click
|
||||||
|
if (button == "left") {
|
||||||
|
loadRootNode("scripts:/scene.toy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//global accessors
|
//global accessors
|
||||||
fn getTileWidth(node: opaque): int { return 64; }
|
fn getTileWidth(node: opaque): int { return 64; }
|
||||||
fn getTileHeight(node: opaque): int { return 64; }
|
fn getTileHeight(node: opaque): int { return 64; }
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ static void fatalError(char* message) {
|
|||||||
void Box_initEngine() {
|
void Box_initEngine() {
|
||||||
//clear
|
//clear
|
||||||
engine.rootNode = NULL;
|
engine.rootNode = NULL;
|
||||||
|
engine.nextRootNodeFilename = TOY_TO_NULL_LITERAL;
|
||||||
engine.running = false;
|
engine.running = false;
|
||||||
engine.window = NULL;
|
engine.window = NULL;
|
||||||
engine.renderer = NULL;
|
engine.renderer = NULL;
|
||||||
@@ -69,23 +70,22 @@ void Box_initEngine() {
|
|||||||
const unsigned char* tb = Toy_compileString((const char*)source, &size);
|
const unsigned char* tb = Toy_compileString((const char*)source, &size);
|
||||||
free((void*)source);
|
free((void*)source);
|
||||||
|
|
||||||
|
//TODO: inner-interpreter
|
||||||
Toy_runInterpreter(&engine.interpreter, tb, size);
|
Toy_runInterpreter(&engine.interpreter, tb, size);
|
||||||
|
|
||||||
//init the node-tree
|
|
||||||
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Box_freeEngine() {
|
void Box_freeEngine() {
|
||||||
//clear existing root node
|
//clear existing root node
|
||||||
if (engine.rootNode != NULL) {
|
if (engine.rootNode != NULL) {
|
||||||
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
||||||
|
|
||||||
Box_freeEngineNode(engine.rootNode);
|
Box_freeEngineNode(engine.rootNode);
|
||||||
|
|
||||||
engine.rootNode = NULL;
|
engine.rootNode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!TOY_IS_NULL(engine.nextRootNodeFilename)) {
|
||||||
|
Toy_freeLiteral(engine.nextRootNodeFilename);
|
||||||
|
}
|
||||||
|
|
||||||
Toy_freeInterpreter(&engine.interpreter);
|
Toy_freeInterpreter(&engine.interpreter);
|
||||||
|
|
||||||
//free events
|
//free events
|
||||||
@@ -101,6 +101,64 @@ void Box_freeEngine() {
|
|||||||
engine.window = NULL;
|
engine.window = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void execLoadRootNode() {
|
||||||
|
//if a new root node is NOT needed, skip out
|
||||||
|
if (TOY_IS_NULL(engine.nextRootNodeFilename)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//free the existing root node
|
||||||
|
if (engine.rootNode != NULL) {
|
||||||
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
||||||
|
Box_freeEngineNode(engine.rootNode);
|
||||||
|
engine.rootNode = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//compile the new root node
|
||||||
|
size_t size = 0;
|
||||||
|
const unsigned char* source = Toy_readFile(Toy_toCString(TOY_AS_STRING(engine.nextRootNodeFilename)), &size);
|
||||||
|
const unsigned char* tb = Toy_compileString((const char*)source, &size);
|
||||||
|
free((void*)source);
|
||||||
|
|
||||||
|
//allocate the new root node
|
||||||
|
engine.rootNode = TOY_ALLOCATE(Box_EngineNode, 1);
|
||||||
|
|
||||||
|
//BUGFIX: make an inner-interpreter
|
||||||
|
Toy_Interpreter inner;
|
||||||
|
|
||||||
|
//init the inner interpreter manually
|
||||||
|
Toy_initLiteralArray(&inner.literalCache);
|
||||||
|
inner.scope = Toy_pushScope(engine.interpreter.scope);
|
||||||
|
inner.bytecode = tb;
|
||||||
|
inner.length = size;
|
||||||
|
inner.count = 0;
|
||||||
|
inner.codeStart = -1;
|
||||||
|
inner.depth = engine.interpreter.depth + 1;
|
||||||
|
inner.panic = false;
|
||||||
|
Toy_initLiteralArray(&inner.stack);
|
||||||
|
inner.hooks = engine.interpreter.hooks;
|
||||||
|
Toy_setInterpreterPrint(&inner, engine.interpreter.printOutput);
|
||||||
|
Toy_setInterpreterAssert(&inner, engine.interpreter.assertOutput);
|
||||||
|
Toy_setInterpreterError(&inner, engine.interpreter.errorOutput);
|
||||||
|
|
||||||
|
Box_initEngineNode(engine.rootNode, &inner, tb, size);
|
||||||
|
|
||||||
|
//immediately call onLoad() after running the script - for loading other nodes
|
||||||
|
Box_callEngineNode(engine.rootNode, &inner, "onLoad", NULL);
|
||||||
|
|
||||||
|
//manual cleanup
|
||||||
|
inner.scope = Toy_popScope(inner.scope);
|
||||||
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeLiteral(engine.nextRootNodeFilename);
|
||||||
|
engine.nextRootNodeFilename = TOY_TO_NULL_LITERAL;
|
||||||
|
|
||||||
|
//init the new node-tree
|
||||||
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onInit", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void execEvents() {
|
static void execEvents() {
|
||||||
Toy_LiteralArray args; //save some allocation by reusing this
|
Toy_LiteralArray args; //save some allocation by reusing this
|
||||||
Toy_initLiteralArray(&args);
|
Toy_initLiteralArray(&args);
|
||||||
@@ -336,7 +394,7 @@ static void execEvents() {
|
|||||||
Toy_freeLiteralArray(&args);
|
Toy_freeLiteralArray(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void execStep() {
|
static void execStep() {
|
||||||
if (engine.rootNode != NULL) {
|
if (engine.rootNode != NULL) {
|
||||||
//steps
|
//steps
|
||||||
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onStep", NULL);
|
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onStep", NULL);
|
||||||
@@ -355,6 +413,8 @@ void Box_execEngine() {
|
|||||||
clock_t delta = (double) CLOCKS_PER_SEC / 60.0;
|
clock_t delta = (double) CLOCKS_PER_SEC / 60.0;
|
||||||
|
|
||||||
while (engine.running) {
|
while (engine.running) {
|
||||||
|
execLoadRootNode();
|
||||||
|
|
||||||
execEvents();
|
execEvents();
|
||||||
|
|
||||||
//calc the time passed
|
//calc the time passed
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
typedef struct Box_private_engine {
|
typedef struct Box_private_engine {
|
||||||
//engine stuff
|
//engine stuff
|
||||||
Box_EngineNode* rootNode;
|
Box_EngineNode* rootNode;
|
||||||
|
Toy_Literal nextRootNodeFilename;
|
||||||
clock_t simTime;
|
clock_t simTime;
|
||||||
clock_t realTime;
|
clock_t realTime;
|
||||||
bool running;
|
bool running;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ void Box_initEngineNode(Box_EngineNode* node, Toy_Interpreter* interpreter, cons
|
|||||||
// node->freeMemory = freeMemory;
|
// node->freeMemory = freeMemory;
|
||||||
node->functions = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
node->functions = TOY_ALLOCATE(Toy_LiteralDictionary, 1);
|
||||||
node->parent = NULL;
|
node->parent = NULL;
|
||||||
|
node->scope = NULL;
|
||||||
node->tag = OPAQUE_TAG_ENGINE_NODE;
|
node->tag = OPAQUE_TAG_ENGINE_NODE;
|
||||||
node->children = NULL;
|
node->children = NULL;
|
||||||
node->capacity = 0;
|
node->capacity = 0;
|
||||||
@@ -64,7 +65,7 @@ void Box_freeEngineNode(Box_EngineNode* node) {
|
|||||||
return; //NO-OP
|
return; //NO-OP
|
||||||
}
|
}
|
||||||
|
|
||||||
//free and tombstone this node
|
//free this node's children
|
||||||
for (int i = 0; i < node->count; i++) {
|
for (int i = 0; i < node->count; i++) {
|
||||||
Box_freeEngineNode(node->children[i]);
|
Box_freeEngineNode(node->children[i]);
|
||||||
}
|
}
|
||||||
@@ -77,6 +78,10 @@ void Box_freeEngineNode(Box_EngineNode* node) {
|
|||||||
TOY_FREE(Toy_LiteralDictionary, node->functions);
|
TOY_FREE(Toy_LiteralDictionary, node->functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->scope != NULL) {
|
||||||
|
Toy_popScope(node->scope);
|
||||||
|
}
|
||||||
|
|
||||||
if (node->texture != NULL) {
|
if (node->texture != NULL) {
|
||||||
Box_freeTextureEngineNode(node);
|
Box_freeTextureEngineNode(node);
|
||||||
}
|
}
|
||||||
@@ -99,7 +104,6 @@ void Box_freeChildEngineNode(Box_EngineNode* node, int index) {
|
|||||||
|
|
||||||
//free the node
|
//free the node
|
||||||
if (childNode != NULL) {
|
if (childNode != NULL) {
|
||||||
Box_callRecursiveEngineNode(childNode, &engine.interpreter, "onFree", NULL);
|
|
||||||
Box_freeEngineNode(childNode);
|
Box_freeEngineNode(childNode);
|
||||||
node->childCount--;
|
node->childCount--;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ typedef struct Box_private_engineNode {
|
|||||||
//point to the parent
|
//point to the parent
|
||||||
Box_EngineNode* parent;
|
Box_EngineNode* parent;
|
||||||
|
|
||||||
|
//BUGFIX: hold the node's scope so it can be popped
|
||||||
|
Toy_Scope* scope;
|
||||||
|
|
||||||
//my opaque type tag
|
//my opaque type tag
|
||||||
int tag;
|
int tag;
|
||||||
|
|
||||||
|
|||||||
@@ -130,56 +130,9 @@ static int nativeLoadRootNode(Toy_Interpreter* interpreter, Toy_LiteralArray* ar
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//clear existing root node
|
//set the signal that a new node is needed
|
||||||
if (engine.rootNode != NULL) {
|
engine.nextRootNodeFilename = Toy_copyLiteral(filePathLiteral);
|
||||||
Box_callRecursiveEngineNode(engine.rootNode, &engine.interpreter, "onFree", NULL);
|
|
||||||
|
|
||||||
Box_freeEngineNode(engine.rootNode);
|
|
||||||
TOY_FREE(Box_EngineNode, engine.rootNode);
|
|
||||||
|
|
||||||
engine.rootNode = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
//load the new root node
|
|
||||||
size_t size = 0;
|
|
||||||
const unsigned char* source = Toy_readFile(Toy_toCString(TOY_AS_STRING(filePathLiteral)), &size);
|
|
||||||
const unsigned char* tb = Toy_compileString((const char*)source, &size);
|
|
||||||
free((void*)source);
|
|
||||||
|
|
||||||
Box_EngineNode* rootNode = TOY_ALLOCATE(Box_EngineNode, 1);
|
|
||||||
|
|
||||||
//BUGFIX: make an inner-interpreter
|
|
||||||
Toy_Interpreter inner;
|
|
||||||
|
|
||||||
//init the inner interpreter manually
|
|
||||||
Toy_initLiteralArray(&inner.literalCache);
|
|
||||||
inner.scope = Toy_pushScope(interpreter->scope);
|
|
||||||
inner.bytecode = tb;
|
|
||||||
inner.length = size;
|
|
||||||
inner.count = 0;
|
|
||||||
inner.codeStart = -1;
|
|
||||||
inner.depth = interpreter->depth + 1;
|
|
||||||
inner.panic = false;
|
|
||||||
Toy_initLiteralArray(&inner.stack);
|
|
||||||
inner.hooks = interpreter->hooks;
|
|
||||||
Toy_setInterpreterPrint(&inner, interpreter->printOutput);
|
|
||||||
Toy_setInterpreterAssert(&inner, interpreter->assertOutput);
|
|
||||||
Toy_setInterpreterError(&inner, interpreter->errorOutput);
|
|
||||||
|
|
||||||
Box_initEngineNode(rootNode, &inner, tb, size);
|
|
||||||
|
|
||||||
//immediately call onLoad() after running the script - for loading other nodes
|
|
||||||
Box_callEngineNode(rootNode, &engine.interpreter, "onLoad", NULL);
|
|
||||||
|
|
||||||
//NOW it's non-null
|
|
||||||
engine.rootNode = rootNode;
|
|
||||||
|
|
||||||
//cleanup
|
|
||||||
Toy_popScope(inner.scope);
|
|
||||||
inner.scope = NULL;
|
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
|
||||||
Toy_freeLiteral(filePathLiteral);
|
Toy_freeLiteral(filePathLiteral);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -71,13 +71,15 @@ static int nativeLoadNode(Toy_Interpreter* interpreter, Toy_LiteralArray* argume
|
|||||||
Box_initEngineNode(node, &inner, tb, size);
|
Box_initEngineNode(node, &inner, tb, size);
|
||||||
|
|
||||||
//immediately call onLoad() after running the script - for loading other nodes
|
//immediately call onLoad() after running the script - for loading other nodes
|
||||||
Box_callEngineNode(node, &engine.interpreter, "onLoad", NULL);
|
Box_callEngineNode(node, &inner, "onLoad", NULL);
|
||||||
|
|
||||||
// return the node
|
// return the node
|
||||||
Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
Toy_Literal nodeLiteral = TOY_TO_OPAQUE_LITERAL(node, node->tag);
|
||||||
Toy_pushLiteralArray(&interpreter->stack, nodeLiteral);
|
Toy_pushLiteralArray(&interpreter->stack, nodeLiteral);
|
||||||
|
|
||||||
//cleanup (NOT the scope - that needs to hang around)
|
//cleanup (NOT the scope - that needs to hang around)
|
||||||
|
node->scope = inner.scope;
|
||||||
|
|
||||||
Toy_freeLiteralArray(&inner.stack);
|
Toy_freeLiteralArray(&inner.stack);
|
||||||
Toy_freeLiteralArray(&inner.literalCache);
|
Toy_freeLiteralArray(&inner.literalCache);
|
||||||
Toy_freeLiteral(filePathLiteral);
|
Toy_freeLiteral(filePathLiteral);
|
||||||
@@ -246,6 +248,8 @@ static int nativeFreeChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* a
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: differentiate between onFree() and freeing memory
|
||||||
|
Box_callRecursiveEngineNode(node, interpreter, "onFree", NULL);
|
||||||
Box_freeChildEngineNode(node, idx);
|
Box_freeChildEngineNode(node, idx);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
|
|||||||
Reference in New Issue
Block a user