Implemented node child sorting
This commit is contained in:
111
box/box_node.c
111
box/box_node.c
@@ -111,6 +111,115 @@ void Box_freeChildNode(Box_Node* node, int index) {
|
||||
node->children[index] = NULL;
|
||||
}
|
||||
|
||||
static void swapUtil(Box_Node** lhs, Box_Node** rhs) {
|
||||
Box_Node* tmp = *lhs;
|
||||
*lhs = *rhs;
|
||||
*rhs = tmp;
|
||||
}
|
||||
|
||||
//copied from lib_standard.c
|
||||
static void recursiveLiteralQuicksortUtil(Toy_Interpreter* interpreter, Box_Node** ptr, int count, Toy_Literal fnCompare) {
|
||||
//base case
|
||||
if (count <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int runner = 0;
|
||||
|
||||
//iterate through the array
|
||||
for (int checker = 0; checker < count - 1; checker++) {
|
||||
//if node is null, it is always sorted to the end
|
||||
if (ptr[checker] == NULL) {
|
||||
swapUtil(&ptr[checker], &ptr[checker + 1]);
|
||||
runner++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ptr[checker + 1] == NULL) {
|
||||
runner++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Toy_LiteralArray arguments;
|
||||
Toy_LiteralArray returns;
|
||||
|
||||
Toy_initLiteralArray(&arguments);
|
||||
Toy_initLiteralArray(&returns);
|
||||
|
||||
Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(ptr[checker], OPAQUE_TAG_NODE));
|
||||
Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(ptr[checker + 1], OPAQUE_TAG_NODE));
|
||||
|
||||
Toy_callLiteralFn(interpreter, fnCompare, &arguments, &returns);
|
||||
|
||||
Toy_Literal lessThan = Toy_popLiteralArray(&returns);
|
||||
|
||||
Toy_freeLiteralArray(&arguments);
|
||||
Toy_freeLiteralArray(&returns);
|
||||
|
||||
if (TOY_IS_TRUTHY(lessThan)) {
|
||||
swapUtil(&ptr[runner++], &ptr[checker]);
|
||||
}
|
||||
|
||||
Toy_freeLiteral(lessThan);
|
||||
}
|
||||
|
||||
//"shift everything up" so the pivot is in the middle
|
||||
swapUtil(&ptr[runner], &ptr[count - 1]);
|
||||
|
||||
//recurse on each end
|
||||
if (runner > 0) {
|
||||
recursiveLiteralQuicksortUtil(interpreter, &ptr[0], runner, fnCompare);
|
||||
}
|
||||
|
||||
if (runner < count) {
|
||||
recursiveLiteralQuicksortUtil(interpreter, &ptr[runner + 1], count - runner - 1, fnCompare);
|
||||
}
|
||||
}
|
||||
|
||||
BOX_API void Box_sortChildrenNode(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal fnCompare) {
|
||||
//check that this node's children aren't already sorted
|
||||
bool sorted = true;
|
||||
for (int checker = 0; checker < node->count - 1 && sorted; checker++) {
|
||||
//NULL (tombstone) is always considered unsorted
|
||||
if (node->children[checker] == NULL || node->children[checker + 1] == NULL) {
|
||||
sorted = false;
|
||||
break;
|
||||
}
|
||||
|
||||
Toy_LiteralArray arguments;
|
||||
Toy_LiteralArray returns;
|
||||
|
||||
Toy_initLiteralArray(&arguments);
|
||||
Toy_initLiteralArray(&returns);
|
||||
|
||||
Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(node->children[checker], OPAQUE_TAG_NODE));
|
||||
Toy_pushLiteralArray(&arguments, TOY_TO_OPAQUE_LITERAL(node->children[checker + 1], OPAQUE_TAG_NODE));
|
||||
|
||||
Toy_callLiteralFn(interpreter, fnCompare, &arguments, &returns);
|
||||
|
||||
Toy_Literal lessThan = Toy_popLiteralArray(&returns);
|
||||
|
||||
Toy_freeLiteralArray(&arguments);
|
||||
Toy_freeLiteralArray(&returns);
|
||||
|
||||
if (!TOY_IS_TRUTHY(lessThan)) {
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
Toy_freeLiteral(lessThan);
|
||||
}
|
||||
|
||||
//sort the children
|
||||
if (!sorted) {
|
||||
recursiveLiteralQuicksortUtil(interpreter, node->children, node->count, fnCompare);
|
||||
}
|
||||
|
||||
//re-count the newly-sorted children
|
||||
for (int i = node->count - 1; node->children[i] == NULL; i--) {
|
||||
node->count--;
|
||||
}
|
||||
}
|
||||
|
||||
Toy_Literal Box_callNodeLiteral(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args) {
|
||||
Toy_Literal ret = TOY_TO_NULL_LITERAL;
|
||||
|
||||
@@ -287,6 +396,6 @@ void Box_setTextNode(Box_Node* node, TTF_Font* font, const char* text, SDL_Color
|
||||
void Box_drawNode(Box_Node* node, SDL_Rect dest) {
|
||||
if (!node->texture) return;
|
||||
SDL_Rect src = node->rect;
|
||||
src.x += src.w * node->currentFrame; //TODO: improve this
|
||||
src.x += src.w * node->currentFrame;
|
||||
SDL_RenderCopy(engine.renderer, node->texture, &src, &dest);
|
||||
}
|
||||
|
||||
@@ -9,13 +9,9 @@
|
||||
|
||||
//forward declare
|
||||
typedef struct Box_private_node Box_Node;
|
||||
// typedef void (*Box_NodeCallback)(void*);
|
||||
|
||||
//the node object, which forms a tree
|
||||
typedef struct Box_private_node {
|
||||
//function for releasing memory NOTE: removed, because it's not needed with only 1 node type - I've left them commented out because I might need them soon
|
||||
// Box_NodeCallback freeMemory;
|
||||
|
||||
//toy functions, stored in a dict for flexibility
|
||||
Toy_LiteralDictionary* functions;
|
||||
|
||||
@@ -36,10 +32,10 @@ typedef struct Box_private_node {
|
||||
|
||||
//rendering-specific features
|
||||
SDL_Texture* texture;
|
||||
SDL_Rect rect;
|
||||
int frames;
|
||||
SDL_Rect rect; //rendered rect
|
||||
int frames; //horizontal-strip based animations
|
||||
int currentFrame;
|
||||
} Box_Node; //TODO: rename this?
|
||||
} Box_Node;
|
||||
|
||||
BOX_API void Box_initNode(Box_Node* node, Toy_Interpreter* interpreter, const unsigned char* tb, size_t size); //run bytecode, then grab all top-level function literals
|
||||
BOX_API void Box_pushNode(Box_Node* node, Box_Node* child); //push to the array (prune tombstones when expanding/copying)
|
||||
@@ -48,6 +44,8 @@ BOX_API void Box_freeNode(Box_Node* node); //free this node and all children
|
||||
BOX_API Box_Node* Box_getChildNode(Box_Node* node, int index);
|
||||
BOX_API void Box_freeChildNode(Box_Node* node, int index);
|
||||
|
||||
BOX_API void Box_sortChildrenNode(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal fnCompare);
|
||||
|
||||
BOX_API Toy_Literal Box_callNodeLiteral(Box_Node* node, Toy_Interpreter* interpreter, Toy_Literal key, Toy_LiteralArray* args);
|
||||
BOX_API Toy_Literal Box_callNode(Box_Node* node, Toy_Interpreter* interpreter, const char* fnName, Toy_LiteralArray* args); //call "fnName" on this node, and only this node, if it exists
|
||||
|
||||
|
||||
@@ -257,6 +257,42 @@ static int nativeFreeChildNode(Toy_Interpreter* interpreter, Toy_LiteralArray* a
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nativeSortChildrenNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
if (arguments->count != 2) {
|
||||
interpreter->errorOutput("Incorrect number of arguments passed to sortChildrenNode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Toy_Literal fnLiteral = Toy_popLiteralArray(arguments);
|
||||
Toy_Literal nodeLiteral = Toy_popLiteralArray(arguments);
|
||||
|
||||
Toy_Literal nodeLiteralIdn = nodeLiteral; //annoying
|
||||
if (TOY_IS_IDENTIFIER(nodeLiteral) && Toy_parseIdentifierToValue(interpreter, &nodeLiteral)) {
|
||||
Toy_freeLiteral(nodeLiteralIdn);
|
||||
}
|
||||
|
||||
Toy_Literal fnLiteralIdn = fnLiteral; //annoying
|
||||
if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) {
|
||||
Toy_freeLiteral(fnLiteralIdn);
|
||||
}
|
||||
|
||||
//check argument types
|
||||
if (!TOY_IS_OPAQUE(nodeLiteral) || !TOY_IS_FUNCTION(fnLiteral)) {
|
||||
interpreter->errorOutput("Incorrect argument type passed to sortChildrenNode\n");
|
||||
Toy_freeLiteral(nodeLiteral);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Box_Node* node = TOY_AS_OPAQUE(nodeLiteral);
|
||||
|
||||
Box_sortChildrenNode(node, interpreter, fnLiteral);
|
||||
|
||||
//cleanup
|
||||
Toy_freeLiteral(nodeLiteral);
|
||||
Toy_freeLiteral(fnLiteral);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nativeGetParentNode(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||
//checks
|
||||
if (arguments->count != 1) {
|
||||
@@ -1099,6 +1135,7 @@ int Box_hookNode(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Liter
|
||||
{"pushNode", nativePushNode},
|
||||
{"getChildNode", nativeGetChildNode},
|
||||
{"freeChildNode", nativeFreeChildNode},
|
||||
{"sortChildrenNode", nativeSortChildrenNode},
|
||||
{"getParentNode", nativeGetParentNode},
|
||||
{"getChildNodeCount", nativeGetChildNodeCount},
|
||||
{"loadNodeTexture", nativeLoadNodeTexture},
|
||||
|
||||
Reference in New Issue
Block a user