cleaned more stuff
This commit is contained in:
@@ -8,4 +8,5 @@ target_sources(${DUSK_TARGET_NAME}
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
mesh.c
|
mesh.c
|
||||||
quad.c
|
quad.c
|
||||||
|
meshrenderer.c
|
||||||
)
|
)
|
27
archive/dusksdl2/display/mesh/meshrenderer.c
Normal file
27
archive/dusksdl2/display/mesh/meshrenderer.c
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "meshrenderer.h"
|
||||||
|
|
||||||
|
meshrenderer_t MESH_RENDERER_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
||||||
|
ecscomponent_t MESH_RENDERER_COMPONENT = ecsComponentInit(
|
||||||
|
MESH_RENDERER_DATA,
|
||||||
|
((ecscomponentcallbacks_t){
|
||||||
|
.init = NULL,
|
||||||
|
.entityAdd = NULL,
|
||||||
|
.entityRemove = NULL
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
void meshRendererDraw(const ecsid_t id) {
|
||||||
|
if (!meshRendererHas(id)) return;
|
||||||
|
|
||||||
|
meshrenderer_t *renderer = meshRendererGet(id);
|
||||||
|
if (!renderer || !renderer->mesh) return;
|
||||||
|
|
||||||
|
meshDraw(renderer->mesh, 0, -1);
|
||||||
|
}
|
33
archive/dusksdl2/display/mesh/meshrenderer.h
Normal file
33
archive/dusksdl2/display/mesh/meshrenderer.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "ecs/ecscomponent.h"
|
||||||
|
#include "display/mesh/mesh.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mesh_t *mesh;
|
||||||
|
} meshrenderer_t;
|
||||||
|
|
||||||
|
extern meshrenderer_t MESH_RENDERER_DATA[ECS_ENTITY_COUNT_MAX];
|
||||||
|
extern ecscomponent_t MESH_RENDERER_COMPONENT;
|
||||||
|
|
||||||
|
#define meshRendererAdd(id) \
|
||||||
|
((meshrenderer_t*)ecsComponentDataAdd(&MESH_RENDERER_COMPONENT, id))
|
||||||
|
#define meshRendererGet(id) \
|
||||||
|
((meshrenderer_t*)ecsComponentDataGet(&MESH_RENDERER_COMPONENT, id))
|
||||||
|
#define meshRendererHas(id) \
|
||||||
|
(ecsComponentDataHas(&MESH_RENDERER_COMPONENT, id))
|
||||||
|
#define meshRendererRemove(id) \
|
||||||
|
ecsComponentDataRemove(&MESH_RENDERER_COMPONENT, id)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the mesh for the given entity.
|
||||||
|
*
|
||||||
|
* @param id The ID of the entity with the mesh renderer component.
|
||||||
|
*/
|
||||||
|
void meshRendererDraw(const ecsid_t id);
|
@@ -3,10 +3,13 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
find_package(cglm REQUIRED)
|
||||||
|
|
||||||
# Libs
|
# Libs
|
||||||
target_link_libraries(${DUSK_TARGET_NAME}
|
target_link_libraries(${DUSK_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
m
|
m
|
||||||
|
cglm
|
||||||
)
|
)
|
||||||
|
|
||||||
# Includes
|
# Includes
|
||||||
|
@@ -6,6 +6,78 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
#include "display/display.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
||||||
ecscomponent_t CAMERA_COMPONENT = ecsComponentInit(CAMERA_DATA, NULL);
|
ecscomponent_t CAMERA_COMPONENT = ecsComponentInit(
|
||||||
|
CAMERA_DATA,
|
||||||
|
((ecscomponentcallbacks_t){
|
||||||
|
.init = NULL,
|
||||||
|
.entityAdd = cameraEntityAdded
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
ecsid_t CAMERA_MAIN = -1;
|
||||||
|
|
||||||
|
void cameraEntityAdded(const ecsid_t id) {
|
||||||
|
if(CAMERA_MAIN == -1) CAMERA_MAIN = id;
|
||||||
|
|
||||||
|
camera_t *cam = cameraGet(id);
|
||||||
|
cam->type = CAMERA_TYPE_ORTHOGRAPHIC;
|
||||||
|
cam->perspective.fov = glm_rad(75.0f);
|
||||||
|
cam->nearClip = 0.1f;
|
||||||
|
cam->farClip = 1000.0f;
|
||||||
|
cam->clearColor = COLOR_CORNFLOWER_BLUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraPush(const ecsid_t id) {
|
||||||
|
assertTrue(cameraHas(id), "Not a camera component");
|
||||||
|
|
||||||
|
camera_t *cam = cameraGet(id);
|
||||||
|
|
||||||
|
mat4 projection;
|
||||||
|
switch(cam->type) {
|
||||||
|
case CAMERA_TYPE_ORTHOGRAPHIC:
|
||||||
|
glm_ortho(
|
||||||
|
cam->orthographic.left,
|
||||||
|
cam->orthographic.right,
|
||||||
|
cam->orthographic.bottom,
|
||||||
|
cam->orthographic.top,
|
||||||
|
cam->nearClip,
|
||||||
|
cam->farClip,
|
||||||
|
projection
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAMERA_TYPE_PERSPECTIVE:
|
||||||
|
glm_perspective(
|
||||||
|
cam->perspective.fov,
|
||||||
|
4.0f / 3.0f,
|
||||||
|
cam->nearClip,
|
||||||
|
cam->farClip,
|
||||||
|
projection
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DUSK_DISPLAY_SDL2
|
||||||
|
glPushMatrix();
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glLoadMatrixf((const GLfloat*)projection);
|
||||||
|
|
||||||
|
glClearColor(
|
||||||
|
cam->clearColor.r / 255.0f,
|
||||||
|
cam->clearColor.g / 255.0f,
|
||||||
|
cam->clearColor.b / 255.0f,
|
||||||
|
cam->clearColor.a / 255.0f
|
||||||
|
);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void cameraPop(void) {
|
||||||
|
#if DUSK_DISPLAY_SDL2
|
||||||
|
glPopMatrix();
|
||||||
|
#endif
|
||||||
|
}
|
@@ -7,42 +7,59 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "ecs/ecscomponent.h"
|
#include "ecs/ecscomponent.h"
|
||||||
|
#include "display/color.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CAMERA_TYPE_PERSPECTIVE,
|
||||||
|
CAMERA_TYPE_ORTHOGRAPHIC
|
||||||
|
} cameraprojectiontype_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float_t view[16]; // 4x4 matrix for view transformation
|
cameraprojectiontype_t type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float_t fov;
|
||||||
|
} perspective;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float_t left;
|
||||||
|
float_t right;
|
||||||
|
float_t top;
|
||||||
|
float_t bottom;
|
||||||
|
} orthographic;
|
||||||
|
};
|
||||||
|
|
||||||
|
float_t nearClip;
|
||||||
|
float_t farClip;
|
||||||
|
color_t clearColor;
|
||||||
} camera_t;
|
} camera_t;
|
||||||
|
|
||||||
extern camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX];
|
extern camera_t CAMERA_DATA[ECS_ENTITY_COUNT_MAX];
|
||||||
extern ecscomponent_t CAMERA_COMPONENT;
|
extern ecscomponent_t CAMERA_COMPONENT;
|
||||||
extern ecsid_t CAMERA_MAIN;
|
extern ecsid_t CAMERA_MAIN;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the camera component.
|
|
||||||
*
|
|
||||||
* @param id The ID of the entity to initialize the camera for.
|
|
||||||
*/
|
|
||||||
#define cameraAdd(id) ((camera_t*)ecsComponentDataAdd(&CAMERA_COMPONENT, id))
|
#define cameraAdd(id) ((camera_t*)ecsComponentDataAdd(&CAMERA_COMPONENT, id))
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the camera component data for a specific entity.
|
|
||||||
*
|
|
||||||
* @param id The ID of the entity to get the camera data for.
|
|
||||||
* @return Pointer to the camera data for the entity.
|
|
||||||
*/
|
|
||||||
#define cameraGet(id) ((camera_t*)ecsComponentDataGet(&CAMERA_COMPONENT, id))
|
#define cameraGet(id) ((camera_t*)ecsComponentDataGet(&CAMERA_COMPONENT, id))
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the camera component has data for a specific entity.
|
|
||||||
*
|
|
||||||
* @param id The ID of the entity to check.
|
|
||||||
* @return True if the camera component has data for the entity, false otherwise.
|
|
||||||
*/
|
|
||||||
#define cameraHas(id) ecsComponentDataHas(&CAMERA_COMPONENT, id)
|
#define cameraHas(id) ecsComponentDataHas(&CAMERA_COMPONENT, id)
|
||||||
|
#define cameraRemove(id) ecsComponentDataRemove(&CAMERA_COMPONENT, id)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the camera component data for a specific entity.
|
* Callback function called when a new entity is added to the camera component.
|
||||||
|
* Initializes the camera data for the entity.
|
||||||
*
|
*
|
||||||
* @param id The ID of the entity to remove the camera data for.
|
* @param id The ID of the newly added entity.
|
||||||
*/
|
*/
|
||||||
#define cameraRemove(id) ecsComponentDataRemove(&CAMERA_COMPONENT, id)
|
void cameraEntityAdded(const ecsid_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes the camera's view matrix onto the matrix stack.
|
||||||
|
*
|
||||||
|
* @param id The ID of the camera entity to use.
|
||||||
|
*/
|
||||||
|
void cameraPush(const ecsid_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops the camera's view matrix off the matrix stack.
|
||||||
|
*/
|
||||||
|
void cameraPop(void);
|
106
src/display/color.h
Normal file
106
src/display/color.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
|
typedef float_t colorchannelf_t;
|
||||||
|
typedef uint8_t colorchannelb_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
colorchannelf_t r;
|
||||||
|
colorchannelf_t g;
|
||||||
|
colorchannelf_t b;
|
||||||
|
} color3f_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
colorchannelf_t r;
|
||||||
|
colorchannelf_t g;
|
||||||
|
colorchannelf_t b;
|
||||||
|
colorchannelf_t a;
|
||||||
|
} color4f_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
colorchannelb_t r;
|
||||||
|
colorchannelb_t g;
|
||||||
|
colorchannelb_t b;
|
||||||
|
} color3b_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
colorchannelb_t r;
|
||||||
|
colorchannelb_t g;
|
||||||
|
colorchannelb_t b;
|
||||||
|
colorchannelb_t a;
|
||||||
|
} color4b_t;
|
||||||
|
|
||||||
|
typedef color4b_t color_t;
|
||||||
|
|
||||||
|
#define color3f(r, g, b) ((color3f_t){r, g, b})
|
||||||
|
#define color4f(r, g, b, a) ((color4f_t){r, g, b, a})
|
||||||
|
#define color3b(r, g, b) ((color3b_t){r, g, b})
|
||||||
|
#define color4b(r, g, b, a) ((color4b_t){r, g, b, a})
|
||||||
|
#define color(r, g, b, a) ((color_t){r, g, b, a})
|
||||||
|
|
||||||
|
#define COLOR_WHITE_3F color3f(1.0f, 1.0f, 1.0f)
|
||||||
|
#define COLOR_WHITE_4F color4f(1.0f, 1.0f, 1.0f, 1.0f)
|
||||||
|
#define COLOR_WHITE_3B color3b(255, 255, 255)
|
||||||
|
#define COLOR_WHITE_4B color4b(255, 255, 255, 255)
|
||||||
|
#define COLOR_WHITE color(255, 255, 255, 255)
|
||||||
|
|
||||||
|
#define COLOR_BLACK_3F color3f(0.0f, 0.0f, 0.0f)
|
||||||
|
#define COLOR_BLACK_4F color4f(0.0f, 0.0f, 0.0f, 1.0f)
|
||||||
|
#define COLOR_BLACK_3B color3b(0, 0, 0)
|
||||||
|
#define COLOR_BLACK_4B color4b(0, 0, 0, 255)
|
||||||
|
#define COLOR_BLACK color(0, 0, 0, 255)
|
||||||
|
|
||||||
|
#define COLOR_RED_3F color3f(1.0f, 0.0f, 0.0f)
|
||||||
|
#define COLOR_RED_4F color4f(1.0f, 0.0f, 0.0f, 1.0f)
|
||||||
|
#define COLOR_RED_3B color3b(255, 0, 0)
|
||||||
|
#define COLOR_RED_4B color4b(255, 0, 0, 255)
|
||||||
|
#define COLOR_RED color(255, 0, 0, 255)
|
||||||
|
|
||||||
|
#define COLOR_GREEN_3F color3f(0.0f, 1.0f, 0.0f)
|
||||||
|
#define COLOR_GREEN_4F color4f(0.0f, 1.0f, 0.0f, 1.0f)
|
||||||
|
#define COLOR_GREEN_3B color3b(0, 255, 0)
|
||||||
|
#define COLOR_GREEN_4B color4b(0, 255, 0, 255)
|
||||||
|
#define COLOR_GREEN color(0, 255, 0, 255)
|
||||||
|
|
||||||
|
#define COLOR_BLUE_3F color3f(0.0f, 0.0f, 1.0f)
|
||||||
|
#define COLOR_BLUE_4F color4f(0.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
#define COLOR_BLUE_3B color3b(0, 0, 255)
|
||||||
|
#define COLOR_BLUE_4B color4b(0, 0, 255, 255)
|
||||||
|
#define COLOR_BLUE color(0, 0, 255, 255)
|
||||||
|
|
||||||
|
#define COLOR_YELLOW_3F color3f(1.0f, 1.0f, 0.0f)
|
||||||
|
#define COLOR_YELLOW_4F color4f(1.0f, 1.0f, 0.0f, 1.0f)
|
||||||
|
#define COLOR_YELLOW_3B color3b(255, 255, 0)
|
||||||
|
#define COLOR_YELLOW_4B color4b(255, 255, 0, 255)
|
||||||
|
#define COLOR_YELLOW color(255, 255, 0, 255)
|
||||||
|
|
||||||
|
#define COLOR_CYAN_3F color3f(0.0f, 1.0f, 1.0f)
|
||||||
|
#define COLOR_CYAN_4F color4f(0.0f, 1.0f, 1.0f, 1.0f)
|
||||||
|
#define COLOR_CYAN_3B color3b(0, 255, 255)
|
||||||
|
#define COLOR_CYAN_4B color4b(0, 255, 255, 255)
|
||||||
|
#define COLOR_CYAN color(0, 255, 255, 255)
|
||||||
|
|
||||||
|
#define COLOR_MAGENTA_3F color3f(1.0f, 0.0f, 1.0f)
|
||||||
|
#define COLOR_MAGENTA_4F color4f(1.0f, 0.0f, 1.0f, 1.0f)
|
||||||
|
#define COLOR_MAGENTA_3B color3b(255, 0, 255)
|
||||||
|
#define COLOR_MAGENTA_4B color4b(255, 0, 255, 255)
|
||||||
|
#define COLOR_MAGENTA color(255, 0, 255, 255)
|
||||||
|
|
||||||
|
#define COLOR_TRANSPARENT_3F color3f(0.0f, 0.0f, 0.0f)
|
||||||
|
#define COLOR_TRANSPARENT_4F color4f(0.0f, 0.0f, 0.0f, 0.0f)
|
||||||
|
#define COLOR_TRANSPARENT_3B color3b(0, 0, 0)
|
||||||
|
#define COLOR_TRANSPARENT_4B color4b(0, 0, 0, 0)
|
||||||
|
#define COLOR_TRANSPARENT color(0, 0, 0, 0)
|
||||||
|
|
||||||
|
#define COLOR_CORNFLOWER_BLUE_3F color3f(0.39f, 0.58f, 0.93f)
|
||||||
|
#define COLOR_CORNFLOWER_BLUE_4F color4f(0.39f, 0.58f, 0.93f, 1.0f)
|
||||||
|
#define COLOR_CORNFLOWER_BLUE_3B color3b(100, 149, 237)
|
||||||
|
#define COLOR_CORNFLOWER_BLUE_4B color4b(100, 149, 237, 255)
|
||||||
|
#define COLOR_CORNFLOWER_BLUE color(100, 149, 237, 255)
|
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "display/display.h"
|
#include "display/display.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
|
#include "display/camera.h"
|
||||||
#include "display/mesh/mesh.h"
|
#include "display/mesh/mesh.h"
|
||||||
|
|
||||||
display_t DISPLAY;
|
display_t DISPLAY;
|
||||||
@@ -82,11 +82,21 @@ errorret_t displayUpdate(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_SwapWindow(DISPLAY.window);
|
// Set viewport size.
|
||||||
|
int32_t windowWidth, windowHeight;
|
||||||
|
SDL_GetWindowSize(DISPLAY.window, &windowWidth, &windowHeight);
|
||||||
|
glViewport(0, 0, windowWidth, windowHeight);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(CAMERA_MAIN != -1) {
|
||||||
|
cameraPush(CAMERA_MAIN);
|
||||||
meshDraw(&mesh, 0, -1);
|
meshDraw(&mesh, 0, -1);
|
||||||
|
cameraPop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DUSK_DISPLAY_SDL2
|
||||||
|
SDL_GL_SwapWindow(DISPLAY.window);
|
||||||
|
#endif
|
||||||
|
|
||||||
// For now, we just return an OK error.
|
// For now, we just return an OK error.
|
||||||
errorOk();
|
errorOk();
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
#include <cglm/cglm.h>
|
||||||
|
|
||||||
typedef bool bool_t;
|
typedef bool bool_t;
|
||||||
typedef int int_t;
|
typedef int int_t;
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
#include "display/display.h"
|
#include "display/display.h"
|
||||||
#include "ecs/ecssystem.h"
|
#include "ecs/ecssystem.h"
|
||||||
#include "scene/scenetree.h"
|
#include "scene/node.h"
|
||||||
|
|
||||||
#include "scene/test/scenetest.h"
|
#include "scene/test/scenetest.h"
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ errorret_t engineInit(void) {
|
|||||||
errorChain(displayInit());
|
errorChain(displayInit());
|
||||||
|
|
||||||
ecsid_t sceneTest = sceneTestAdd();
|
ecsid_t sceneTest = sceneTestAdd();
|
||||||
sceneTreeChildAdd(ECS_SYSTEM.root, sceneTest);
|
nodeChildAdd(ECS_SYSTEM.root, sceneTest);
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
# Sources
|
# Sources
|
||||||
target_sources(${DUSK_TARGET_NAME}
|
target_sources(${DUSK_TARGET_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
scenetree.c
|
node.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
|
127
src/scene/node.c
Normal file
127
src/scene/node.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
// Copyright (c) 2025 Dominic Masters
|
||||||
|
//
|
||||||
|
// This software is released under the MIT License.
|
||||||
|
// https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
node_t NODE_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
||||||
|
ecscomponent_t NODE_COMPONENT = ecsComponentInit(
|
||||||
|
NODE_DATA,
|
||||||
|
((ecscomponentcallbacks_t){
|
||||||
|
.init = nodeInit,
|
||||||
|
.entityAdd = nodeEntityAdded,
|
||||||
|
.entityRemove = nodeEntityRemoved
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
ecsid_t nodeParentGet(const ecsid_t child) {
|
||||||
|
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
||||||
|
if(!nodeHas(child)) return -1;
|
||||||
|
return NODE_DATA[child].parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nodeChildGetAll(const ecsid_t id, ecsid_t *children) {
|
||||||
|
if(!nodeHas(id)) return 0;
|
||||||
|
if(children == NULL) return NODE_DATA[id].childCount;
|
||||||
|
|
||||||
|
memoryCopy(
|
||||||
|
children,
|
||||||
|
NODE_DATA[id].children,
|
||||||
|
sizeof(ecsid_t) * NODE_DATA[id].childCount
|
||||||
|
);
|
||||||
|
|
||||||
|
return NODE_DATA[id].childCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeChildAdd(const ecsid_t parent, const ecsid_t child) {
|
||||||
|
if(!nodeHas(parent)) nodeAdd(parent);
|
||||||
|
if(!nodeHas(child)) nodeAdd(child);
|
||||||
|
|
||||||
|
node_t *parentNode = &NODE_DATA[parent];
|
||||||
|
assertTrue(parentNode->childCount < SCENE_ITEM_CHILD_MAX, "Parent full.");
|
||||||
|
|
||||||
|
// Add child to parent's children array
|
||||||
|
parentNode->children[parentNode->childCount] = child;
|
||||||
|
parentNode->childCount++;
|
||||||
|
|
||||||
|
// Set child's parent
|
||||||
|
NODE_DATA[child].parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeChildRemove(const ecsid_t parent, const ecsid_t child) {
|
||||||
|
assertTrue(nodeHas(parent), "NODE ECS lacks Parent.");
|
||||||
|
assertTrue(nodeHas(child), "NODE ECS lacks Child.");
|
||||||
|
|
||||||
|
node_t *childNode = &NODE_DATA[child];
|
||||||
|
node_t *parentNode = &NODE_DATA[parent];
|
||||||
|
assertTrue(childNode->parent == parent, "Child does not belong to parent");
|
||||||
|
assertTrue(parentNode->childCount > 0, "Parent has no children");
|
||||||
|
|
||||||
|
// Remove child from parent's children array
|
||||||
|
for (uint8_t i = 0; i < parentNode->childCount; i++) {
|
||||||
|
if (parentNode->children[i] == child) {
|
||||||
|
// Shift remaining children down
|
||||||
|
for (uint8_t j = i; j < parentNode->childCount - 1; j++) {
|
||||||
|
parentNode->children[j] = parentNode->children[j + 1];
|
||||||
|
}
|
||||||
|
parentNode->childCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear child's parent
|
||||||
|
childNode->parent = -1;
|
||||||
|
|
||||||
|
if(childNode->childCount == 0) nodeRemove(child);
|
||||||
|
if(parentNode->childCount == 0) nodeRemove(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeChildRemoveAll(const ecsid_t parent) {
|
||||||
|
assertTrue(nodeHas(parent), "NODE ECS lacks Parent.");
|
||||||
|
|
||||||
|
node_t *parentNode = &NODE_DATA[parent];
|
||||||
|
for(uint8_t i = 0; i < parentNode->childCount; i++) {
|
||||||
|
ecsid_t child = parentNode->children[i];
|
||||||
|
NODE_DATA[child].parent = -1;
|
||||||
|
|
||||||
|
if(NODE_DATA[child].childCount == 0) nodeRemove(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeRemove(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t nodeChildInTree(const ecsid_t parent, const ecsid_t child) {
|
||||||
|
assertTrue(nodeHas(parent), "NODE ECS lacks Parent.");
|
||||||
|
assertTrue(nodeHas(child), "NODE ECS lacks Child.");
|
||||||
|
|
||||||
|
assertTrue(parent >= 0 && parent < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
|
||||||
|
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
||||||
|
assertTrue(parent != child, "Child cannot be a child of itself.");
|
||||||
|
|
||||||
|
node_t *childNode = &NODE_DATA[child];
|
||||||
|
while(childNode) {
|
||||||
|
if(childNode->parent == parent) return true;
|
||||||
|
if(childNode->parent == -1) break; // No parent means we've reached the root
|
||||||
|
childNode = &NODE_DATA[childNode->parent];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeInit(void) {
|
||||||
|
for(ecsid_t i = 0; i < ECS_ENTITY_COUNT_MAX; i++) {
|
||||||
|
NODE_DATA[i].parent = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeEntityAdded(const ecsid_t id) {
|
||||||
|
NODE_DATA[id].parent = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nodeEntityRemoved(const ecsid_t id) {
|
||||||
|
if(NODE_DATA[id].parent == -1) return;
|
||||||
|
nodeChildRemove(NODE_DATA[id].parent, id);
|
||||||
|
}
|
@@ -14,17 +14,21 @@ typedef struct {
|
|||||||
ecsid_t children[SCENE_ITEM_CHILD_MAX];
|
ecsid_t children[SCENE_ITEM_CHILD_MAX];
|
||||||
uint8_t childCount;
|
uint8_t childCount;
|
||||||
ecsid_t parent;
|
ecsid_t parent;
|
||||||
} scenetreenode_t;
|
|
||||||
|
|
||||||
extern scenetreenode_t SCENE_TREE_DATA[ECS_ENTITY_COUNT_MAX];
|
vec3 position;
|
||||||
extern ecscomponent_t SCENE_TREE_COMPONENT;
|
vec3 rotation;
|
||||||
|
vec3 scale;
|
||||||
|
} node_t;
|
||||||
|
|
||||||
/**
|
extern node_t NODE_DATA[ECS_ENTITY_COUNT_MAX];
|
||||||
* Initialize the scene tree.
|
extern ecscomponent_t NODE_COMPONENT;
|
||||||
*
|
|
||||||
* This will initialize the ECS system and prepare the scene tree for use.
|
#define nodeHas(id) ecsComponentDataHas(&NODE_COMPONENT, id)
|
||||||
*/
|
#define nodeGet(id) \
|
||||||
void sceneTreeInit(void);
|
((node_t*)ecsComponentDataGet(&NODE_COMPONENT, id))
|
||||||
|
#define nodeAdd(id) \
|
||||||
|
((node_t*)ecsComponentDataAdd(&NODE_COMPONENT, id))
|
||||||
|
#define nodeRemove(id) ecsComponentDataRemove(&NODE_COMPONENT, id)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new scene item in the scene tree.
|
* Create a new scene item in the scene tree.
|
||||||
@@ -32,7 +36,7 @@ void sceneTreeInit(void);
|
|||||||
*
|
*
|
||||||
* @return The ID of the newly created scene item.
|
* @return The ID of the newly created scene item.
|
||||||
*/
|
*/
|
||||||
ecsid_t sceneTreeCreate(void);
|
ecsid_t nodeCreate(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the parent of a given scene item.
|
* Get the parent of a given scene item.
|
||||||
@@ -40,7 +44,7 @@ ecsid_t sceneTreeCreate(void);
|
|||||||
* @param id The ID of the scene item.
|
* @param id The ID of the scene item.
|
||||||
* @return The ID of the parent scene item, or -1 if it has no parent.
|
* @return The ID of the parent scene item, or -1 if it has no parent.
|
||||||
*/
|
*/
|
||||||
ecsid_t sceneTreeParentGet(const ecsid_t child);
|
ecsid_t nodeParentGet(const ecsid_t child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the children of a given scene item. If children is NULL only the count
|
* Get the children of a given scene item. If children is NULL only the count
|
||||||
@@ -50,7 +54,7 @@ ecsid_t sceneTreeParentGet(const ecsid_t child);
|
|||||||
* @param children Pointer to an array where the children IDs will be stored.
|
* @param children Pointer to an array where the children IDs will be stored.
|
||||||
* @return The number of children found.
|
* @return The number of children found.
|
||||||
*/
|
*/
|
||||||
uint8_t sceneTreeChildGetAll(const ecsid_t id, ecsid_t *children);
|
uint8_t nodeChildGetAll(const ecsid_t id, ecsid_t *children);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a child to a parent in the scene tree.
|
* Add a child to a parent in the scene tree.
|
||||||
@@ -58,7 +62,7 @@ uint8_t sceneTreeChildGetAll(const ecsid_t id, ecsid_t *children);
|
|||||||
* @param parent The ID of the parent scene item.
|
* @param parent The ID of the parent scene item.
|
||||||
* @param child The ID of the child scene item to add.
|
* @param child The ID of the child scene item to add.
|
||||||
*/
|
*/
|
||||||
void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child);
|
void nodeChildAdd(const ecsid_t parent, const ecsid_t child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a child from a parent in the scene tree.
|
* Remove a child from a parent in the scene tree.
|
||||||
@@ -66,14 +70,14 @@ void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child);
|
|||||||
* @param prnt The ID of the parent scene item.
|
* @param prnt The ID of the parent scene item.
|
||||||
* @param child The ID of the child scene item to remove.
|
* @param child The ID of the child scene item to remove.
|
||||||
*/
|
*/
|
||||||
void sceneTreeChildRemove(const ecsid_t prnt, const ecsid_t child);
|
void nodeChildRemove(const ecsid_t prnt, const ecsid_t child);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all children from a parent in the scene tree.
|
* Remove all children from a parent in the scene tree.
|
||||||
*
|
*
|
||||||
* @param parent The ID of the parent scene item.
|
* @param parent The ID of the parent scene item.
|
||||||
*/
|
*/
|
||||||
void sceneTreeChildRemoveAll(const ecsid_t parent);
|
void nodeChildRemoveAll(const ecsid_t parent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the child is within the parent's children, recursively.
|
* Returns true if the child is within the parent's children, recursively.
|
||||||
@@ -82,7 +86,14 @@ void sceneTreeChildRemoveAll(const ecsid_t parent);
|
|||||||
* @param child The ID of the child scene item to check.
|
* @param child The ID of the child scene item to check.
|
||||||
* @return True if the child is in the parent's children, false otherwise.
|
* @return True if the child is in the parent's children, false otherwise.
|
||||||
*/
|
*/
|
||||||
bool_t sceneTreeChildInTree(const ecsid_t parent, const ecsid_t child);
|
bool_t nodeChildInTree(const ecsid_t parent, const ecsid_t child);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the scene tree.
|
||||||
|
*
|
||||||
|
* This will initialize the ECS system and prepare the scene tree for use.
|
||||||
|
*/
|
||||||
|
void nodeInit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for when an entity is added to the ECS.
|
* Callback for when an entity is added to the ECS.
|
||||||
@@ -90,7 +101,7 @@ bool_t sceneTreeChildInTree(const ecsid_t parent, const ecsid_t child);
|
|||||||
*
|
*
|
||||||
* @param id The ID of the entity being added.
|
* @param id The ID of the entity being added.
|
||||||
*/
|
*/
|
||||||
void sceneTreeEntityAdded(const ecsid_t id);
|
void nodeEntityAdded(const ecsid_t id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for when an entity is removed from the ECS.
|
* Callback for when an entity is removed from the ECS.
|
||||||
@@ -98,4 +109,4 @@ void sceneTreeEntityAdded(const ecsid_t id);
|
|||||||
*
|
*
|
||||||
* @param id The ID of the entity being removed.
|
* @param id The ID of the entity being removed.
|
||||||
*/
|
*/
|
||||||
void sceneTreeEntityRemoved(const ecsid_t id);
|
void nodeEntityRemoved(const ecsid_t id);
|
@@ -1,160 +0,0 @@
|
|||||||
// Copyright (c) 2025 Dominic Masters
|
|
||||||
//
|
|
||||||
// This software is released under the MIT License.
|
|
||||||
// https://opensource.org/licenses/MIT
|
|
||||||
|
|
||||||
#include "scenetree.h"
|
|
||||||
#include "util/memory.h"
|
|
||||||
#include "assert/assert.h"
|
|
||||||
|
|
||||||
scenetreenode_t SCENE_TREE_DATA[ECS_ENTITY_COUNT_MAX] = { 0 };
|
|
||||||
ecscomponent_t SCENE_TREE_COMPONENT = ecsComponentInit(
|
|
||||||
SCENE_TREE_DATA,
|
|
||||||
((ecscomponentcallbacks_t){
|
|
||||||
.init = sceneTreeInit,
|
|
||||||
.entityAdd = sceneTreeEntityAdded,
|
|
||||||
.entityRemove = sceneTreeEntityRemoved
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
void sceneTreeInit(void) {
|
|
||||||
// Default all items to have no parent
|
|
||||||
for (ecsid_t i = 0; i < ECS_ENTITY_COUNT_MAX; i++) {
|
|
||||||
SCENE_TREE_DATA[i].parent = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ecsid_t sceneTreeParentGet(const ecsid_t child) {
|
|
||||||
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
|
||||||
if(!ecsComponentDataHas(&SCENE_TREE_COMPONENT, child)) return -1;
|
|
||||||
return SCENE_TREE_DATA[child].parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t sceneTreeChildGetAll(const ecsid_t id, ecsid_t *children) {
|
|
||||||
if(!ecsComponentDataHas(&SCENE_TREE_COMPONENT, id)) return 0;
|
|
||||||
if(children == NULL) return SCENE_TREE_DATA[id].childCount;
|
|
||||||
|
|
||||||
memoryCopy(
|
|
||||||
children,
|
|
||||||
SCENE_TREE_DATA[id].children,
|
|
||||||
sizeof(ecsid_t) * SCENE_TREE_DATA[id].childCount
|
|
||||||
);
|
|
||||||
|
|
||||||
return SCENE_TREE_DATA[id].childCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sceneTreeChildAdd(const ecsid_t parent, const ecsid_t child) {
|
|
||||||
if(!ecsComponentDataHas(&SCENE_TREE_COMPONENT, parent)) {
|
|
||||||
ecsComponentDataAdd(&SCENE_TREE_COMPONENT, parent);
|
|
||||||
}
|
|
||||||
if(!ecsComponentDataHas(&SCENE_TREE_COMPONENT, child)) {
|
|
||||||
ecsComponentDataAdd(&SCENE_TREE_COMPONENT, child);
|
|
||||||
}
|
|
||||||
|
|
||||||
scenetreenode_t *parentNode = &SCENE_TREE_DATA[parent];
|
|
||||||
assertTrue(parentNode->childCount < SCENE_ITEM_CHILD_MAX, "Parent full.");
|
|
||||||
|
|
||||||
// Add child to parent's children array
|
|
||||||
parentNode->children[parentNode->childCount] = child;
|
|
||||||
parentNode->childCount++;
|
|
||||||
|
|
||||||
// Set child's parent
|
|
||||||
SCENE_TREE_DATA[child].parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sceneTreeChildRemove(
|
|
||||||
const ecsid_t parent,
|
|
||||||
const ecsid_t child
|
|
||||||
) {
|
|
||||||
assertTrue(
|
|
||||||
ecsComponentDataHas(&SCENE_TREE_COMPONENT, parent),
|
|
||||||
"SCENE TREE ECS lacks Parent."
|
|
||||||
);
|
|
||||||
assertTrue(
|
|
||||||
ecsComponentDataHas(&SCENE_TREE_COMPONENT, child),
|
|
||||||
"SCENE TREE ECS lacks Child."
|
|
||||||
);
|
|
||||||
|
|
||||||
scenetreenode_t *childNode = &SCENE_TREE_DATA[child];
|
|
||||||
scenetreenode_t *parentNode = &SCENE_TREE_DATA[parent];
|
|
||||||
assertTrue(childNode->parent == parent, "Child does not belong to parent");
|
|
||||||
assertTrue(parentNode->childCount > 0, "Parent has no children");
|
|
||||||
|
|
||||||
// Remove child from parent's children array
|
|
||||||
for (uint8_t i = 0; i < parentNode->childCount; i++) {
|
|
||||||
if (parentNode->children[i] == child) {
|
|
||||||
// Shift remaining children down
|
|
||||||
for (uint8_t j = i; j < parentNode->childCount - 1; j++) {
|
|
||||||
parentNode->children[j] = parentNode->children[j + 1];
|
|
||||||
}
|
|
||||||
parentNode->childCount--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear child's parent
|
|
||||||
childNode->parent = -1;
|
|
||||||
|
|
||||||
if(childNode->childCount == 0) {
|
|
||||||
ecsComponentDataRemove(&SCENE_TREE_COMPONENT, child);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(parentNode->childCount == 0) {
|
|
||||||
ecsComponentDataRemove(&SCENE_TREE_COMPONENT, parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sceneTreeChildRemoveAll(const ecsid_t parent) {
|
|
||||||
assertTrue(
|
|
||||||
ecsComponentDataHas(&SCENE_TREE_COMPONENT, parent),
|
|
||||||
"SCENE TREE ECS lacks Parent."
|
|
||||||
);
|
|
||||||
|
|
||||||
scenetreenode_t *parentNode = &SCENE_TREE_DATA[parent];
|
|
||||||
for(uint8_t i = 0; i < parentNode->childCount; i++) {
|
|
||||||
ecsid_t child = parentNode->children[i];
|
|
||||||
SCENE_TREE_DATA[child].parent = -1;
|
|
||||||
|
|
||||||
if(SCENE_TREE_DATA[child].childCount == 0) {
|
|
||||||
ecsComponentDataRemove(&SCENE_TREE_COMPONENT, child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ecsComponentDataRemove(&SCENE_TREE_COMPONENT, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool_t sceneTreeChildInTree(
|
|
||||||
const ecsid_t parent,
|
|
||||||
const ecsid_t child
|
|
||||||
) {
|
|
||||||
assertTrue(
|
|
||||||
ecsComponentDataHas(&SCENE_TREE_COMPONENT, parent),
|
|
||||||
"SCENE TREE ECS lacks Parent."
|
|
||||||
);
|
|
||||||
assertTrue(
|
|
||||||
ecsComponentDataHas(&SCENE_TREE_COMPONENT, child),
|
|
||||||
"SCENE TREE ECS lacks Child."
|
|
||||||
);
|
|
||||||
|
|
||||||
assertTrue(parent >= 0 && parent < ECS_ENTITY_COUNT_MAX, "Invalid parent ID");
|
|
||||||
assertTrue(child >= 0 && child < ECS_ENTITY_COUNT_MAX, "Invalid child ID");
|
|
||||||
assertTrue(parent != child, "Child cannot be a child of itself.");
|
|
||||||
|
|
||||||
scenetreenode_t *childNode = &SCENE_TREE_DATA[child];
|
|
||||||
while(childNode) {
|
|
||||||
if(childNode->parent == parent) return true;
|
|
||||||
if(childNode->parent == -1) break; // No parent means we've reached the root
|
|
||||||
childNode = &SCENE_TREE_DATA[childNode->parent];
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sceneTreeEntityAdded(const ecsid_t id) {
|
|
||||||
SCENE_TREE_DATA[id].parent = -1; // Default parent to -1 (no parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
void sceneTreeEntityRemoved(const ecsid_t id) {
|
|
||||||
if(SCENE_TREE_DATA[id].parent == -1) return;
|
|
||||||
sceneTreeChildRemove(SCENE_TREE_DATA[id].parent, id);
|
|
||||||
}
|
|
@@ -6,16 +6,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scenetest.h"
|
#include "scenetest.h"
|
||||||
#include "scene/scenetree.h"
|
#include "scene/node.h"
|
||||||
#include "display/camera.h"
|
#include "display/camera.h"
|
||||||
|
#include "display/display.h"
|
||||||
|
|
||||||
ecsid_t sceneTestAdd(void) {
|
ecsid_t sceneTestAdd(void) {
|
||||||
ecsid_t id = ecsEntityAdd();
|
ecsid_t id = ecsEntityAdd();
|
||||||
|
|
||||||
// Initialize the entity with a camera component
|
// Initialize the entity with a camera component
|
||||||
ecsid_t camera = ecsEntityAdd();
|
ecsid_t camera = ecsEntityAdd();
|
||||||
sceneTreeChildAdd(id, camera);
|
nodeChildAdd(id, camera);
|
||||||
camera_t *camData = cameraAdd(camera);
|
camera_t *camData = cameraAdd(camera);
|
||||||
|
camData->type = CAMERA_TYPE_ORTHOGRAPHIC;
|
||||||
|
camData->orthographic.left = 0.0f;
|
||||||
|
camData->orthographic.right = 1.0f;
|
||||||
|
camData->orthographic.top = 0.0f;
|
||||||
|
camData->orthographic.bottom = 1.0f;
|
||||||
|
camData->nearClip = -1.0f;
|
||||||
|
camData->farClip = 1.0f;
|
||||||
|
|
||||||
// Optionally, you can set other properties or components here
|
// Optionally, you can set other properties or components here
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user