--- a/src/ascension/scene_node.h Thu Apr 24 18:41:42 2025 +0200 +++ b/src/ascension/scene_node.h Thu Apr 24 19:53:40 2025 +0200 @@ -39,6 +39,7 @@ typedef void(*asc_scene_update_func)(AscSceneNode*); enum AscRenderGroup { + ASC_RENDER_GROUP_NONE = -1, ASC_RENDER_GROUP_SPRITE_OPAQUE, ASC_RENDER_GROUP_SPRITE_BLEND, ASC_RENDER_GROUP_COUNT @@ -94,4 +95,126 @@ #define ASC_SCENE_NODE_HIDDEN 0x80000000 + +/** + * Creates an empty node that may serve as a container for other nodes. + * + * The free_func of this node will be a simple free(). + * + * @return the new node + */ +AscSceneNode *asc_scene_node_empty(void); + +/** + * Unlinks the node from its parent and frees the entire subtree. + * + * The free_func of this node and all child nodes is called, starting + * with the leaf nodes and terminating with \p node. + * + * @param node the node to unlink + */ +void asc_scene_node_free(AscSceneNode *node); + +/** + * Links a node to a (new) parent. + * + * @param parent the (new) parent + * @param node the node to link + */ +__attribute__((__nonnull__)) +void asc_scene_node_link( + AscSceneNode *restrict parent, + AscSceneNode *restrict node +); + +/** + * Unlinks a node from its parent. + * + * This might be useful to temporarily remove a subtree from a scene. + * To permanently remove the node use asc_scene_node_free(). + * + * @param node the node to unlink + */ +__attribute__((__nonnull__)) +void asc_scene_node_unlink(AscSceneNode *node); + +/** + * Adds a behavior function to the node. + * + * A behavior function MUST NOT be added more than once to the same node. + * This will not be checked. + * + * @param node the node + * @param behavior the behavior function + */ +__attribute__((__nonnull__)) +void asc_scene_add_behavior( + AscSceneNode *node, + asc_scene_update_func behavior +); + +/** + * Removes a behavior function from the node. + * + * If the behavior function is not attached to this node, this function + * does nothing. + * + * @param node the node + * @param behavior the behavior function + */ +__attribute__((__nonnull__)) +void asc_scene_remove_behavior( + AscSceneNode *node, + asc_scene_update_func behavior +); + +__attribute__((__nonnull__)) +void asc_node_update(AscSceneNode *node); + +__attribute__((__nonnull__)) +void asc_node_update_transform(AscSceneNode *node); + + +__attribute__((__nonnull__)) static inline +void asc_set_position(AscSceneNode *node, float x, float y, float z) { + node->position.x = x; + node->position.y = y; + node->position.z = z; + asc_node_update_transform(node); +} + +__attribute__((__nonnull__)) static inline +void asc_set_position2d(AscSceneNode *node, int x, int y) { + node->position.x = (float)x; + node->position.y = (float)y; + node->position.z = 0.f; + asc_node_update_transform(node); +} + +__attribute__((__nonnull__)) static inline +asc_vec2i asc_get_position2d(AscSceneNode *node) { + return (asc_vec2i) {(int) node->position.x, (int) node->position.y}; +} + +__attribute__((__nonnull__)) static inline +void asc_set_scale(AscSceneNode *node, float width, float height, float depth) { + node->scale.width = width; + node->scale.height = height; + node->scale.depth = depth; + asc_node_update_transform(node); +} + +__attribute__((__nonnull__)) static inline +void asc_set_scale2d(AscSceneNode *node, int width, int height) { + node->scale.width = (float)width; + node->scale.height = (float)height; + node->scale.depth = 1.f; + asc_node_update_transform(node); +} + +__attribute__((__nonnull__)) static inline +asc_vec2i asc_get_scale2d(AscSceneNode *node) { + return (asc_vec2i) {(int) node->scale.width, (int) node->scale.height}; +} + #endif