add backdrop scene default tip

Tue, 29 Apr 2025 21:51:29 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 29 Apr 2025 21:51:29 +0200
changeset 101
febf3dc10011
parent 100
5231da78831e

add backdrop scene

src/ascension/camera.h file | annotate | diff | comparison | revisions
src/ascension/datatypes.h file | annotate | diff | comparison | revisions
src/ascension/scene.h file | annotate | diff | comparison | revisions
src/camera.c file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/scene_node.c file | annotate | diff | comparison | revisions
src/window.c file | annotate | diff | comparison | revisions
test/snake/snake.c file | annotate | diff | comparison | revisions
test/snake/textures/backdrop.png file | annotate | diff | comparison | revisions
--- a/src/ascension/camera.h	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/ascension/camera.h	Tue Apr 29 21:51:29 2025 +0200
@@ -30,9 +30,10 @@
 
 #include "datatypes.h"
 
-typedef asc_recti(*asc_camera_viewport_update_func)(asc_vec2i window_size);
+typedef struct AscCamera AscCamera;
 
-typedef struct AscCamera AscCamera;
+typedef asc_recti(*asc_camera_viewport_update_func)(asc_vec2i window_size);
+typedef void(*asc_camera_projection_update_func)(AscCamera*, asc_vec2i window_size);
 
 struct AscCamera {
     asc_mat4f projection;
@@ -44,8 +45,32 @@
      * If @c NULL, the entire window will be used.
      */
     asc_camera_viewport_update_func viewport_update_func;
+    asc_camera_projection_update_func projection_update_func;
 };
 
+enum AscCameraType {
+    ASC_CAMERA_CUSTOM,
+    ASC_CAMERA_ORTHO,
+    ASC_CAMERA_PERSPECTIVE,
+};
+
+typedef struct {
+    enum AscCameraType type;
+    union {
+        struct {
+            asc_recti rect;
+        } ortho;
+        struct {
+            // TODO: implement
+        } perspective;
+    };
+    asc_camera_viewport_update_func viewport_update_func;
+    asc_camera_projection_update_func projection_update_func;
+} AscCameraParams;
+
+__attribute__((__nonnull__))
+void asc_camera_init(AscCamera *camera, AscCameraParams params);
+
 __attribute__((__nonnull__))
 void asc_camera_ortho(AscCamera *camera, asc_recti rect);
 
@@ -54,6 +79,9 @@
  *
  * @attention The camera MUST have been initialized with asc_camera_ortho() at position (0,0).
  *
+ * @note This function can be used as an asc_camera_projection_update_func to keep the orthographic projection
+ * aligned with the window size (useful for UIs or backdrops).
+ *
  * @param camera the camera
  * @param size the new size
  */
--- a/src/ascension/datatypes.h	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/ascension/datatypes.h	Tue Apr 29 21:51:29 2025 +0200
@@ -59,7 +59,7 @@
 
 typedef struct asc_recti {
     asc_vec2i pos;
-    asc_vec2i size;
+    asc_vec2i size; // TODO: shouldn't sizes be unsigned?
 } asc_recti;
 
 typedef union asc_vec3f {
--- a/src/ascension/scene.h	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/ascension/scene.h	Tue Apr 29 21:51:29 2025 +0200
@@ -37,25 +37,6 @@
     AscSceneNode *root;
 } AscScene;
 
-enum AscCameraType {
-    ASC_CAMERA_CUSTOM,
-    ASC_CAMERA_ORTHO,
-    ASC_CAMERA_PERSPECTIVE,
-};
-
-typedef struct {
-    enum AscCameraType type;
-    union {
-        struct {
-            asc_recti rect;
-        } ortho;
-        struct {
-            // TODO: implement
-        } perspective;
-    };
-    asc_camera_viewport_update_func viewport_update_func;
-} AscCameraParams;
-
 /**
  * Initializes a scene graph.
  *
--- a/src/camera.c	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/camera.c	Tue Apr 29 21:51:29 2025 +0200
@@ -25,8 +25,28 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "ascension/context.h"
 #include "ascension/camera.h"
 
+void asc_camera_init(AscCamera *camera, AscCameraParams params) {
+    if (params.type == ASC_CAMERA_ORTHO) {
+        asc_recti rect = params.ortho.rect;
+        if (rect.size.width <= 0 || rect.size.height <= 0) {
+            rect.size.width = 1;
+            rect.size.height = 1;
+        }
+        asc_camera_ortho(camera, rect);
+    } else if (params.type == ASC_CAMERA_PERSPECTIVE) {
+        // TODO: implement
+        asc_wprintf("Camera type PERSPECTIVE is not yet implemented.");
+    } else {
+        // at least zero all the bytes (law of the least surprise)
+        memset(camera, 0, sizeof(AscCamera));
+    }
+    camera->viewport_update_func = params.viewport_update_func;
+    camera->projection_update_func = params.projection_update_func;
+}
+
 void asc_camera_ortho(AscCamera *camera, asc_recti rect) {
     asc_mat4f_unit(camera->view);
     float left = (float) rect.pos.x;
--- a/src/scene.c	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/scene.c	Tue Apr 29 21:51:29 2025 +0200
@@ -45,16 +45,7 @@
         asc_wprintf("Scene %"PRIxPTR" is already initialized - initialization skipped.", (uintptr_t) scene);
         return;
     }
-    if (camera_params.type == ASC_CAMERA_ORTHO) {
-        asc_camera_ortho(&scene->camera, camera_params.ortho.rect);
-    } else if (camera_params.type == ASC_CAMERA_PERSPECTIVE) {
-        // TODO: implement
-        asc_wprintf("Camera type PERSPECTIVE is not yet implemented.");
-    } else {
-        // at least zero all the bytes (law of the least surprise)
-        memset(&scene->camera, 0, sizeof(AscCamera));
-    }
-    scene->camera.viewport_update_func = camera_params.viewport_update_func;
+    asc_camera_init(&scene->camera, camera_params);
     scene->root = asc_scene_node_empty();
 
     asc_dprintf("Initialized scene %"PRIxPTR, (uintptr_t) scene);
@@ -72,11 +63,15 @@
 
     // if the window resized, we must update the viewport
     if (asc_active_window->resized) {
+        asc_vec2i window_size = asc_active_window->dimensions;
         if (scene->camera.viewport_update_func == NULL) {
             // this assumes the viewport was initialized with zeros!
-            scene->camera.viewport.size = asc_active_window->dimensions;
+            scene->camera.viewport.size = window_size;
         } else {
-            scene->camera.viewport = scene->camera.viewport_update_func(asc_active_window->dimensions);
+            scene->camera.viewport = scene->camera.viewport_update_func(window_size);
+        }
+        if (scene->camera.projection_update_func != NULL) {
+            scene->camera.projection_update_func(&scene->camera, window_size);
         }
     }
 
--- a/src/scene_node.c	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/scene_node.c	Tue Apr 29 21:51:29 2025 +0200
@@ -95,6 +95,7 @@
     );
 }
 
+// TODO: rename in asc_node_add_behavior or just asc_add_behavior()
 void asc_scene_add_behavior(
         AscSceneNode *node,
         asc_scene_update_func behavior
--- a/src/window.c	Mon Apr 28 21:13:01 2025 +0200
+++ b/src/window.c	Tue Apr 29 21:51:29 2025 +0200
@@ -80,7 +80,8 @@
             .type = ASC_CAMERA_ORTHO,
             .ortho.rect = (asc_recti){
                 0, 0, window->dimensions.width, window->dimensions.height
-            }
+            },
+            .projection_update_func = asc_camera_ortho_update_size
         });
         asc_dprintf("Window %u initialized at index %u", window->id, index);
         asc_context.active_window = index;
@@ -157,7 +158,6 @@
     for (unsigned int i = 0; i < ASC_MAX_SCENES; i++) {
         asc_scene_draw(&window->scenes[i]);
     }
-    asc_camera_ortho_update_size(&window->ui.camera, (asc_vec2i){window_width, window_height});
     asc_scene_draw(&window->ui);
 
     // Swap Buffers
--- a/test/snake/snake.c	Mon Apr 28 21:13:01 2025 +0200
+++ b/test/snake/snake.c	Tue Apr 29 21:51:29 2025 +0200
@@ -32,12 +32,15 @@
 
 enum Textures2d {
     TEX_SHIP = 0,
+    TEX_BACKDROP,
     TEX2D_COUNT
 };
 static AscTexture tex2d[TEX2D_COUNT];
 #define TEXTURE_SHIP &tex2d[TEX_SHIP]
+#define TEXTURE_BACKDROP &tex2d[TEX_BACKDROP]
 
-#define MAIN_SCENE asc_window_scene(0)
+#define BACKDROP_SCENE asc_window_scene(0)
+#define MAIN_SCENE asc_window_scene(1)
 
 static void destroy_textures(void *dummy) {
     asc_texture_destroy(tex2d, TEX2D_COUNT);
@@ -46,6 +49,7 @@
 static void init_textures(void) {
     asc_texture_init_2d(tex2d, TEX2D_COUNT);
     asc_texture_from_file(TEXTURE_SHIP, "ship.png");
+    asc_texture_from_file(TEXTURE_BACKDROP, "backdrop.png");
     cxMempoolRegister(asc_active_glctx_mpool, tex2d, destroy_textures);
 }
 
@@ -76,9 +80,24 @@
     }
 }
 
+static void scale_backdrop(AscSceneNode *node) {
+    // scale the backdrop to the size of the window
+    if (asc_active_window->resized) {
+        asc_vec2i window_size = asc_active_window->dimensions;
+        asc_set_scale2d(node, window_size.width, window_size.height);
+        // TODO: implement texture repetition
+    }
+}
+
+static void create_backdrop(void) {
+    AscSceneNode *node = asc_sprite(.texture = TEXTURE_BACKDROP);
+    asc_scene_add_behavior(node, scale_backdrop);
+    asc_scene_add_node(BACKDROP_SCENE, node);
+}
+
 static void create_fps_counter(void) {
     asc_font(ASC_FONT_REGULAR, 12);
-    asc_ink_rgba(128, 128, 128, 196);
+    asc_ink_rgba(224, 224, 224, 196);
     AscSceneNode *node = asc_text();
     asc_scene_add_behavior(node, update_fps_counter);
     asc_add_ui_node(node);
@@ -102,7 +121,6 @@
         .width = 64,
         .height = 64
     );
-
     asc_scene_add_node(MAIN_SCENE, sprite);
 
     // TODO: return something
@@ -149,15 +167,23 @@
     settings.title = "Snake";
     asc_window_initialize(0, &settings);
 
-    // initialize the main scene (a 500x500 game field)
+    // load textures
+    init_textures();
+
+    // initialize the scenes
+    const int game_field_size = 500;
+    asc_scene_init(BACKDROP_SCENE, (AscCameraParams) {
+        .type = ASC_CAMERA_ORTHO,
+        .projection_update_func = asc_camera_ortho_update_size
+    });
     asc_scene_init(MAIN_SCENE, (AscCameraParams) {
         .type = ASC_CAMERA_ORTHO,
-        .ortho.rect = (asc_recti){0, 0, 500, 500},
+        .ortho.rect = (asc_recti){0, 0, game_field_size, game_field_size},
         .viewport_update_func = update_viewport_for_window_resize
     });
 
-    // load textures
-    init_textures();
+    // backdrop for letterbox/pillarbox
+    create_backdrop();
 
     // create UI elements
     create_fps_counter();
Binary file test/snake/textures/backdrop.png has changed

mercurial