From 9e702bcdbbc8cc1d84ce80996a8f51c05c40bc95 Mon Sep 17 00:00:00 2001 From: Dendy Date: Sat, 6 Feb 2021 13:16:18 +0100 Subject: [PATCH] Add Node2D --- src/node/node.c | 213 ++++++++++++++++++++++++++++++++++++++++++++ src/node/node.h | 30 +++++++ src/node2d/node2d.c | 5 ++ src/node2d/node2d.h | 6 ++ 4 files changed, 254 insertions(+) create mode 100644 src/node/node.c create mode 100644 src/node/node.h create mode 100644 src/node2d/node2d.c create mode 100644 src/node2d/node2d.h diff --git a/src/node/node.c b/src/node/node.c new file mode 100644 index 0000000..b12c460 --- /dev/null +++ b/src/node/node.c @@ -0,0 +1,213 @@ +#include "node.h" + +#include +#include +#include + +NOD_Node *NOD_CreateNode(char *name){ + return NOD_CreateNodeEX("Node", name); +} + +NOD_Node *NOD_CreateNodeEX(char* type, char *name){ + NOD_Node *node = malloc(sizeof(NOD_Node)); + + if(node != NULL){ + node->name = name; + node->type = type; + + node->parent = NULL; + node->childv = NULL; + node->childc = 0; + } + + return node; +} + +void NOD_DestroyNode(NOD_Node *node){ + if(node != NULL){ + printf("NOD_Info: Deleting node \"%s\"\n", node->name); + /** Cleanup dependencies on this node by its parent */ + NOD_NodeUnparent(node); + free(node); + } +} + +void NOD_DestroyNodeBranch(NOD_Node *node){ + if(node != NULL){ + for(int i = 0; i < node->childc && node->childv != NULL; i++){ + NOD_DestroyNodeBranch(node->childv[i]); + } + NOD_DestroyNode(node); + } +} + +void NOD_NodeAddChild(NOD_Node *parent, NOD_Node *child){ + if(parent != NULL && child != NULL){ + /** Prevent recursion */ + if(parent == child){ + fprintf(stderr, "NOD_Warning: A node cannot be added to itself.\n"); + return; + } + ///** Don't allow tree-breaking reparenting */ + //NOD_Node *tmp_parent = parent->parent; + //while(tmp_parent != NULL){ + //if(tmp_parent == child){ + //fprintf(stderr, "NOD_Warning: Can't add a parent of a node as its child.\n"); + //return; + //} + //tmp_parent = tmp_parent->parent; + //} + /** Check if child already in vector */ + for(int i = 0; i < parent->childc; i++){ + if(parent->childv[i] == child){ + fprintf(stderr, "NOD_Warning: Adding child \"%s\" already in the vector \"%s\".\n", + child->name, + parent->name); + return; + } + } + + /** If it had a parent before, unparent before reparenting */ + if(child->parent != NULL && child->parent != parent){ + printf("NOD_Info: Reparenting node \"%s\"\n", child->name); + NOD_NodeUnparent(child); + } + + /** Create child vector if it hasn't been used */ + if(parent->childc <= 0 || parent->childv == NULL){ + parent->childv = malloc(sizeof(child)); + + if(parent->childv != NULL){ + parent->childv[0] = child; + parent->childc = 1; + + child->parent = parent; + + return; + } + else{ + fprintf(stderr, + "NOD_Error: Failed to allocate space on \"%s\"for child vector \"%s\"\n", + parent->name, child->name); + } + } + + /** If there is a blank space, use it */ + for(int i = 0; i < parent->childc; i++){ + if(parent->childv[i] == NULL){ + printf("NOD_Info: Reused blank space for child :D\n"); + parent->childv[i] = child; + + child->parent = parent; + + return; + } + } + + /** If not, reallocate vector to fit the child */ + parent->childv = realloc(parent->childv, + sizeof(child) *(parent->childc+1)); + + if(parent->childv != NULL){ + parent->childv[parent->childc] = child; + parent->childc++; + + child->parent = parent; + } + else{ + fprintf(stderr, + "NOD_Error: Failed to reallocate space on \"%s\"for child vector \"%s\"\n", + parent->name, child->name); + } + + } +} + +void NOD_NodeUnparent(NOD_Node *node){ + if(node != NULL && node->parent != NULL){ + NOD_Node *parent = node->parent; + + for(int i = 0; i < parent->childc; i ++){ + if(parent->childv[i] == node){ + parent->childv[i] = NULL; + + /* Free allocated memory if last child */ + if(i + 1 == parent->childc){ + fprintf(stderr, + "NOD_Debug: Freeing last child \"%s\" of vector \"%s\"...\n", + node->name, parent->name); + parent->childv = realloc(parent->childv, sizeof(node) *parent->childc); + parent->childc--; + } + } + } + + node->parent = NULL; + } +} + +int get_child_pos(NOD_Node *node){ + int count = 0; + if(node != NULL && node->parent != NULL){ + for(int i = 0; i < node->parent->childc; i++){ + if(node->parent->childv[i] == node) return count; + count++; + } + return 0; + } + return -1; +} + +void nodetree_print_branch(NOD_Node *node, char* level){ + if(node != NULL){ + + for(int i = 0; level[i] != '\0'; i++){ + if(level[i] == 'y') printf("│ "); + else printf(" "); + } + + if(node->parent != NULL){ + if(get_child_pos(node)+1 != node->parent->childc){ + printf("├─ "); + strcat(level, "y"); + } + else{ + printf("└─ "); + strcat(level, "n"); + } + } + printf("%s (%s)\n", node->name, node->type); + + /** Recurse */ + for(int i = 0; i < node->childc; i++){ + nodetree_print_branch(node->childv[i], level); + } + + if(node->parent != NULL){ + level = (char *)realloc(level, strlen(level) * sizeof(char)); + level[strlen(level)-1] = '\0'; + } + } +} + +void NOD_PrintNodeTree(NOD_Node *node){ + if(node != NULL){ + char* level = strdup(""); + + printf("%s (%s)\n", node->name, node->type); + for(int i = 0; i < node->childc; i++){ + nodetree_print_branch(node->childv[i], level); + } + + free(level); + } +} + +int NOD_NodeChildCount(NOD_Node *node){ + int count = 0; + for(int i = 0; i < node->childc; i++){ + if(node->childv[i] != NULL) count++; + } + + return count; +} diff --git a/src/node/node.h b/src/node/node.h new file mode 100644 index 0000000..2ae159b --- /dev/null +++ b/src/node/node.h @@ -0,0 +1,30 @@ +#ifndef __NODE_H_ +#define __NODE_H_ + +typedef struct node{ + char *name; + char *type; + + /** childc keeps track of allocated space, + not amount of children. For that use + NOD_NodeChildCount */ + int childc; + struct node* *childv; + struct node *parent; + + void* data; + +} NOD_Node; + +NOD_Node *NOD_CreateNode(char *name); +NOD_Node *NOD_CreateNodeEX(char *type, char *name); +void NOD_DestroyNode(NOD_Node *node); +void NOD_DestroyNodeBranch(NOD_Node *node); + +void NOD_NodeAddChild(NOD_Node *parent, NOD_Node *child); +void NOD_NodeUnparent(NOD_Node *child); + +void NOD_PrintNodeTree(NOD_Node *node); +int NOD_NodeChildCount(NOD_Node *node); + +#endif // __NODE_H_ diff --git a/src/node2d/node2d.c b/src/node2d/node2d.c new file mode 100644 index 0000000..fc90969 --- /dev/null +++ b/src/node2d/node2d.c @@ -0,0 +1,5 @@ +#include "node2d.h" + +NOD_Node *NOD_CreateNode2D(char *name){ + return NOD_CreateNodeEX("Node2D", name); +} diff --git a/src/node2d/node2d.h b/src/node2d/node2d.h new file mode 100644 index 0000000..72c9a8f --- /dev/null +++ b/src/node2d/node2d.h @@ -0,0 +1,6 @@ +#include"../node/node.h" + +#include + +NOD_Node *NOD_CreateNode2D(char *name); +void NOD_DestroyNode2D(NOD_Node *node);