Add Node2D

This commit is contained in:
Dendy 2021-02-06 13:16:18 +01:00
parent 643e2e5ba4
commit 9e702bcdbb
4 changed files with 254 additions and 0 deletions

213
src/node/node.c Normal file
View File

@ -0,0 +1,213 @@
#include "node.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
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;
}

30
src/node/node.h Normal file
View File

@ -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_

5
src/node2d/node2d.c Normal file
View File

@ -0,0 +1,5 @@
#include "node2d.h"
NOD_Node *NOD_CreateNode2D(char *name){
return NOD_CreateNodeEX("Node2D", name);
}

6
src/node2d/node2d.h Normal file
View File

@ -0,0 +1,6 @@
#include"../node/node.h"
#include<stdio.h>
NOD_Node *NOD_CreateNode2D(char *name);
void NOD_DestroyNode2D(NOD_Node *node);