diff --git a/libc3/window/sdl2/demo/lightspeed.c b/libc3/window/sdl2/demo/lightspeed.c
index 5167165..86b6bde 100644
--- a/libc3/window/sdl2/demo/lightspeed.c
+++ b/libc3/window/sdl2/demo/lightspeed.c
@@ -67,6 +67,7 @@ bool lightspeed_render (s_sequence *seq, s_window_sdl2 *window,
uw i;
(void) window;
(void) context;
+ glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
diff --git a/libc3/window/sdl2/demo/macos/Makefile b/libc3/window/sdl2/demo/macos/Makefile
index 21edfcb..8a10e78 100644
--- a/libc3/window/sdl2/demo/macos/Makefile
+++ b/libc3/window/sdl2/demo/macos/Makefile
@@ -25,11 +25,15 @@ IMG_SOURCES = \
../../../../../img/fly-noto.png \
../../../../../img/toast.png \
+FONT_SOURCES = \
+ ../../../../../fonts/Courier\ New \
+
build:
${MAKE} ${APP_PROG}
${MAKE} ${APP}/Contents/Frameworks
rsync -aP --delete ../../../../../lib ${APP}/Contents/
rsync -aP ${IMG_SOURCES} ${APP}/Contents/img/
+ rsync -aP ${FONT_SOURCES} ${APP}/Contents/fonts/
all:
${MAKE} build
@@ -42,6 +46,7 @@ asan:
${MAKE} ${APP_ASAN}/Contents/Frameworks
rsync -aP --delete ../../../../../lib ${APP_ASAN}/Contents/
rsync -aP ${IMG_SOURCES} ${APP_ASAN}/Contents/img/
+ rsync -aP ${FONT_SOURCES} ${APP_ASAN}/Contents/fonts/
clean:
rm -rf ${CLEANFILES}
@@ -54,12 +59,14 @@ cov:
${MAKE} ${APP_COV}/Contents/Frameworks
rsync -aP --delete ../../../../../lib ${APP_COV}/Contents/
rsync -aP ${IMG_SOURCES} ${APP_COV}/Contents/img/
+ rsync -aP ${FONT_SOURCES} ${APP_COV}/Contents/fonts/
debug:
${MAKE} ${APP_PROG_DEBUG}
${MAKE} ${APP_DEBUG}/Contents/Frameworks
rsync -aP --delete ../../../../../lib ${APP_DEBUG}/Contents/
rsync -aP ${IMG_SOURCES} ${APP_DEBUG}/Contents/img/
+ rsync -aP ${FONT_SOURCES} ${APP_DEBUG}/Contents/fonts/
demo: build
time ${APP_PROG}
diff --git a/libc3/window/sdl2/demo/sources.mk b/libc3/window/sdl2/demo/sources.mk
index 37f994f..bbb3873 100644
--- a/libc3/window/sdl2/demo/sources.mk
+++ b/libc3/window/sdl2/demo/sources.mk
@@ -2,9 +2,11 @@
HEADERS = \
bg_rect.h \
lightspeed.h \
+ toasters.h \
SOURCES = \
bg_rect.c \
lightspeed.c \
+ toasters.c \
window_sdl2_demo.c \
diff --git a/libc3/window/sdl2/demo/sources.sh b/libc3/window/sdl2/demo/sources.sh
index 6e630ef..8301e71 100644
--- a/libc3/window/sdl2/demo/sources.sh
+++ b/libc3/window/sdl2/demo/sources.sh
@@ -1,3 +1,3 @@
# sources.sh generated by update_sources
-HEADERS='bg_rect.h lightspeed.h '
-SOURCES='bg_rect.c lightspeed.c window_sdl2_demo.c '
+HEADERS='bg_rect.h lightspeed.h toasters.h '
+SOURCES='bg_rect.c lightspeed.c toasters.c window_sdl2_demo.c '
diff --git a/libc3/window/sdl2/demo/toasters.c b/libc3/window/sdl2/demo/toasters.c
new file mode 100644
index 0000000..45642fd
--- /dev/null
+++ b/libc3/window/sdl2/demo/toasters.c
@@ -0,0 +1,229 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#include <math.h>
+#include <libc3/c3.h>
+#include "../sdl2_sprite.h"
+#include "toasters.h"
+
+static const f64 g_speed_x = 80.0;
+static const f64 g_speed_y = -40.0;
+s_sdl2_sprite g_toast_sprite = {0};
+s_sdl2_sprite g_toaster_sprite = {0};
+
+static bool toasters_render_toasters (s_list **toasters,
+ s_window_sdl2 *window,
+ s_sequence *seq);
+static bool toasters_render_toasts (s_list **toasts,
+ s_window_sdl2 *window,
+ s_sequence *seq);
+
+static s_tag * toast_init (s_tag *toast, f64 x, f64 y)
+{
+ tag_init_map(toast, 2);
+ tag_init_sym(toast->data.map.keys + 0, sym_1("x"));
+ tag_init_f64(toast->data.map.values + 0, x);
+ tag_init_sym(toast->data.map.keys + 1, sym_1("y"));
+ tag_init_f64(toast->data.map.values + 1, y);
+ return toast;
+}
+
+
+static void toast_render (s_tag *toast, s_window_sdl2 *window,
+ s_sequence *seq)
+{
+ f64 *x;
+ f64 *y;
+ if (toast->type == TAG_MAP) {
+ x = &toast->data.map.values[0].data.f64;
+ y = &toast->data.map.values[1].data.f64;
+ *x -= seq->dt * g_speed_x;
+ *y -= seq->dt * g_speed_y;
+ if (*x < -100 || *y > window->h) {
+ tag_clean(toast);
+ toast->type = TAG_VOID;
+ return;
+ }
+ glPushMatrix();
+ glTranslated(*x, *y, 0.0);
+ sdl2_sprite_render(&g_toast_sprite, 0);
+ glPopMatrix();
+ }
+}
+
+static s_tag * toaster_init (s_tag *toaster, f64 y)
+{
+ tag_init_map(toaster, 2);
+ tag_init_sym_1(toaster->data.map.keys + 0, "x");
+ tag_init_f64(toaster->data.map.values + 0, -150);
+ tag_init_sym_1(toaster->data.map.keys + 1, "y");
+ tag_init_f64(toaster->data.map.values + 1, y);
+ return toaster;
+}
+
+static void toaster_render (s_tag *toaster, s_window_sdl2 *window,
+ s_sequence *seq)
+{
+ f64 *x;
+ f64 *y;
+ if (toaster->type == TAG_MAP) {
+ x = &toaster->data.map.values[0].data.f64;
+ y = &toaster->data.map.values[1].data.f64;
+ *x += seq->dt * g_speed_x;
+ *y += seq->dt * g_speed_y;
+ if (*x > window->w || *y < -200) {
+ tag_clean(toaster);
+ toaster->type = TAG_VOID;
+ return;
+ }
+ glPushMatrix();
+ glTranslated(*x, *y, 0.0);
+ sdl2_sprite_render(&g_toaster_sprite,
+ fmod(seq->t * g_toaster_sprite.frame_count,
+ g_toaster_sprite.frame_count));
+ glPopMatrix();
+ }
+}
+
+bool toasters_load (s_sequence *seq,
+ s_window_sdl2 *window)
+{
+ s_map *map;
+ (void) window;
+ tag_map(&seq->tag, 2);
+ map = &seq->tag.data.map;
+ tag_init_sym_1( map->keys + 0, "toasters");
+ tag_init_list(map->values + 0, NULL);
+ tag_init_sym_1( map->keys + 1, "toasts");
+ tag_init_list(map->values + 1, NULL);
+ return true;
+}
+
+bool toasters_render (s_sequence *seq, s_window_sdl2 *window,
+ void *context)
+{
+ s_list **toasters;
+ s_list **toasts;
+ (void) context;
+ glClearColor(0.7f, 0.95f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_TEXTURE_2D);
+ /* io_inspect(&seq->tag); */
+ if (seq->tag.type == TAG_MAP) {
+ toasters = &seq->tag.data.map.values[0].data.list;
+ toasts = &seq->tag.data.map.values[1].data.list;
+ toasters_render_toasts(toasts, window, seq);
+ toasters_render_toasters(toasters, window, seq);
+ }
+ return true;
+}
+
+bool toasters_render_toasts (s_list **toasts, s_window_sdl2 *window,
+ s_sequence *seq)
+{
+ s_list *i;
+ s_list *j;
+ s_map *map;
+ s_list **t = NULL;
+ f64 x;
+ f64 y;
+ assert(toasts);
+ assert(window);
+ assert(seq);
+ y = window->w * g_speed_y / g_speed_x - 210;
+ if (*toasts && (*toasts)->tag.type == TAG_MAP) {
+ t = &(*toasts)->tag.data.map.values[0].data.list;
+ y = (*toasts)->tag.data.map.values[1].data.f64;
+ }
+ while (y < window->h - 100) {
+ y += 170.0;
+ *toasts = list_new_map(2, *toasts);
+ map = &(*toasts)->tag.data.map;
+ tag_init_sym_1(map->keys + 0, "toasts");
+ tag_init_list(map->values + 0, NULL);
+ tag_init_sym_1(map->keys + 1, "y");
+ tag_init_f64(map->values + 1, y);
+ }
+ i = *toasts;
+ while (i) {
+ if (i->tag.type == TAG_MAP) {
+ t = &i->tag.data.map.values[0].data.list;
+ y = i->tag.data.map.values[1].data.f64;
+ x = 0.0;
+ if (*t && (*t)->tag.type == TAG_MAP)
+ x = (*t)->tag.data.map.values[0].data.f64;
+ if (x < window->w - 160.0) {
+ *t = list_new(*t);
+ toast_init(&(*t)->tag, window->w, y);
+ }
+ list_remove_void(t);
+ j = *t;
+ while (j) {
+ toast_render(&j->tag, window, seq);
+ j = list_next(j);
+ }
+ }
+ i = list_next(i);
+ }
+ return true;
+}
+
+bool toasters_render_toasters (s_list **toasters, s_window_sdl2 *window,
+ s_sequence *seq)
+{
+ s_list *i;
+ s_list *j;
+ s_map *map;
+ s_list **t = NULL;
+ f64 x;
+ f64 y;
+ assert(toasters);
+ assert(window);
+ assert(seq);
+ /* io_inspect_list((const s_list **) toasters); */
+ y = -100.0;
+ if (*toasters && (*toasters)->tag.type == TAG_MAP) {
+ t = &(*toasters)->tag.data.map.values[0].data.list;
+ y = (*toasters)->tag.data.map.values[1].data.f64;
+ }
+ while (y < window->h - window->w * g_speed_y / g_speed_x) {
+ y += 170.0;
+ *toasters = list_new_map(2, *toasters);
+ map = &(*toasters)->tag.data.map;
+ tag_init_sym_1(map->keys + 0, "toasters");
+ tag_init_list(map->values + 0, NULL);
+ tag_init_sym_1(map->keys + 1, "y");
+ tag_init_f64(map->values + 1, y);
+ }
+ i = *toasters;
+ while (i) {
+ if (i->tag.type == TAG_MAP) {
+ t = &i->tag.data.map.values[0].data.list;
+ y = i->tag.data.map.values[1].data.f64;
+ x = 1000.0;
+ if (*t && (*t)->tag.type == TAG_MAP)
+ x = (*t)->tag.data.map.values[0].data.f64;
+ if (x > 60.0) {
+ *t = list_new(*t);
+ toaster_init(&(*t)->tag, y);
+ }
+ list_remove_void(t);
+ j = *t;
+ while (j) {
+ toaster_render(&j->tag, window, seq);
+ j = list_next(j);
+ }
+ }
+ i = list_next(i);
+ }
+ return true;
+}
diff --git a/libc3/window/sdl2/demo/toasters.h b/libc3/window/sdl2/demo/toasters.h
new file mode 100644
index 0000000..ed562ec
--- /dev/null
+++ b/libc3/window/sdl2/demo/toasters.h
@@ -0,0 +1,25 @@
+/* c3
+ * Copyright 2022,2023 kmx.io <contact@kmx.io>
+ *
+ * Permission is hereby granted to use this software granted the above
+ * copyright notice and this permission paragraph are included in all
+ * copies and substantial portions of this software.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
+ * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
+ * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
+ * THIS SOFTWARE.
+ */
+#ifndef TOASTERS_H
+#define TOASTERS_H
+
+#include "../types.h"
+
+extern s_sdl2_sprite g_toast_sprite;
+extern s_sdl2_sprite g_toaster_sprite;
+
+bool toasters_load (s_sequence *seq, s_window_sdl2 *window);
+bool toasters_render (s_sequence *seq, s_window_sdl2 *window,
+ void *context);
+
+#endif /* TOASTERS_H */
diff --git a/libc3/window/sdl2/demo/window_sdl2_demo.c b/libc3/window/sdl2/demo/window_sdl2_demo.c
index 8a10345..85dd299 100644
--- a/libc3/window/sdl2/demo/window_sdl2_demo.c
+++ b/libc3/window/sdl2/demo/window_sdl2_demo.c
@@ -16,10 +16,12 @@
#include "../../window.h"
#include "../window_sdl2.h"
#include "../sdl2_font.h"
+#include "../sdl2_sprite.h"
#include "bg_rect.h"
#include "lightspeed.h"
+#include "toasters.h"
-#define WINDOW_SDL2_DEMO_SEQUENCE_COUNT 2
+#define WINDOW_SDL2_DEMO_SEQUENCE_COUNT 3
//static s_sdl2_font g_font_computer_modern;
static s_sdl2_font g_font_courier_new;
@@ -133,29 +135,25 @@ bool window_sdl2_demo_load (s_window_sdl2 *window)
window_sdl2_sequence_init(window->sequence + 1, 20.0,
"02. Lightspeed",
lightspeed_load, lightspeed_render);
- /*
- if (! sdl2_sprite_init(&g_toaster_sprite,
- sdl2_png_1("img/flaps.png"),
+ if (! sdl2_sprite_init(&g_toaster_sprite, "img/flaps.png",
4, 1, 4))
return false;
- if (! sdl2_sprite_init(&g_toast_sprite,
- sdl2_png_1("img/toast.png"),
- 1, 1, 1))
+ if (! sdl2_sprite_init(&g_toast_sprite, "img/toast.png",
+ 1, 1, 1))
return false;
window_sdl2_sequence_init(window->sequence + 2, 60.0,
- "03. Toasters",
- toasters_load, toasters_render);
- if (! sdl2_sprite_init(&g_fly_sprite,
- sdl2_png_1("img/fly-noto.png"),
- 1, 1, 1))
+ "03. Toasters",
+ toasters_load, toasters_render);
+ /*
+ if (! sdl2_sprite_init(&g_fly_sprite, "img/fly-noto.png",
+ 1, 1, 1))
return false;
- if (! sdl2_sprite_init(&g_dead_fly_sprite,
- sdl2_png_1("img/fly-dead.png"),
- 1, 1, 1))
+ if (! sdl2_sprite_init(&g_dead_fly_sprite, "img/fly-dead.png",
+ 1, 1, 1))
return false;
window_sdl2_sequence_init(window->sequence + 3, 60.0,
- "04. Flies",
- flies_load, flies_render);
+ "04. Flies",
+ flies_load, flies_render);
*/
window_set_sequence_pos((s_window *) window, 0);
return true;
@@ -212,6 +210,7 @@ bool window_sdl2_demo_render (s_window_sdl2 *window, void *context)
render_text(&g_font_courier_new, 20.0f, 30.0f, seq->title);
/* progress bar */
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ glDisable(GL_TEXTURE_2D);
glRectd(19, 11,
19 + (window->w - 40.0) * seq->t / seq->duration + 2,
11 + 4);
diff --git a/libc3/window/sdl2/sdl2_sprite.c b/libc3/window/sdl2/sdl2_sprite.c
index 5b80aae..b0f9b51 100644
--- a/libc3/window/sdl2/sdl2_sprite.c
+++ b/libc3/window/sdl2/sdl2_sprite.c
@@ -43,14 +43,22 @@ static GLenum png_info_to_gl_format (int png_color_type,
break;
case PNG_COLOR_TYPE_RGB:
switch (png_bit_depth) {
- case 8: return GL_RGB8;
- case 16: return GL_RGB16;
+ case 8:
+ printf("GL_RGB8\n");
+ return GL_RGB8;
+ case 16:
+ printf("GL_RGB16\n");
+ return GL_RGB16;
}
break;
case PNG_COLOR_TYPE_RGBA:
switch (png_bit_depth) {
- case 8: return GL_RGBA8;
- case 16: return GL_RGBA16;
+ case 8:
+ printf("GL_RGBA8\n");
+ return GL_RGBA8;
+ case 16:
+ printf("GL_RGBA16\n");
+ return GL_RGBA16;
}
break;
}
@@ -61,8 +69,10 @@ static GLenum png_info_to_gl_type (int png_bit_depth)
{
switch (png_bit_depth) {
case 8:
+ printf("GL_UNSIGNED_BYTE\n");
return GL_UNSIGNED_BYTE;
case 16:
+ printf("GL_UNSIGNED_SHORT\n");
return GL_UNSIGNED_SHORT;
}
return 0;
@@ -126,7 +136,7 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
}
png_read = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL,
NULL);
- if (!png_read) {
+ if (! png_read) {
warn("sdl2_sprite_init: %s: png_create_read_struct",
sprite->real_path.ptr.ps8);
fclose(fp);
@@ -134,6 +144,16 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
str_clean(&sprite->real_path);
return NULL;
}
+ png_info = png_create_info_struct(png_read);
+ if (! png_info) {
+ warn("sdl2_sprite_init: %s: png_create_info_struct",
+ sprite->real_path.ptr.ps8);
+ png_destroy_read_struct(&png_read, NULL, NULL);
+ fclose(fp);
+ str_clean(&sprite->path);
+ str_clean(&sprite->real_path);
+ return NULL;
+ }
if (setjmp(png_jmpbuf(png_read))) {
png_destroy_read_struct(&png_read, &png_info, NULL);
fclose(fp);
@@ -143,7 +163,6 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
}
png_init_io(png_read, fp);
png_set_sig_bytes(png_read, sizeof(png_header));
- //png_set_compression_buffer_size(png_read, buffer_size);
png_read_png(png_read, png_info,
PNG_TRANSFORM_PACKING, NULL);
png_get_IHDR(png_read, png_info, &png_w, &png_h,
@@ -225,7 +244,10 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
sprite_data = data;
v = 0;
while (v < sprite->h) {
- memcpy(sprite_data, png_row[v], sprite_stride);
+ memcpy(sprite_data,
+ png_row[y * sprite->h + v] + x * sprite_stride,
+ sprite_stride);
+ sprite_data += sprite_stride;
v++;
}
glBindTexture(GL_TEXTURE_2D, sprite->texture[i]);
@@ -241,3 +263,24 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
fclose(fp);
return sprite;
}
+
+void sdl2_sprite_render (const s_sdl2_sprite *sprite,
+ uw frame)
+{
+ assert(sprite);
+ assert(frame < sprite->frame_count);
+ frame %= sprite->frame_count;
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, sprite->texture[frame]);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0);
+ glVertex2i(0, 0);
+ glTexCoord2f(0, 1);
+ glVertex2d(0, sprite->h);
+ glTexCoord2f(1, 1);
+ glVertex2d(sprite->w, sprite->h);
+ glTexCoord2f(1, 0);
+ glVertex2i(sprite->w, 0);
+ glEnd();
+}
diff --git a/libc3/window/sdl2/sdl2_sprite.h b/libc3/window/sdl2/sdl2_sprite.h
index d405334..10567e9 100644
--- a/libc3/window/sdl2/sdl2_sprite.h
+++ b/libc3/window/sdl2/sdl2_sprite.h
@@ -23,7 +23,6 @@ s_sdl2_sprite * sdl2_sprite_init (s_sdl2_sprite *sprite,
uw frame_count);
/* operations */
-void sdl2_sprite_render (const s_sdl2_sprite *sprite, uw frame,
- uw x, uw y);
+void sdl2_sprite_render (const s_sdl2_sprite *sprite, uw frame);
#endif /* CAIRO_SPRITE_H */