aboutsummaryrefslogtreecommitdiff
path: root/config/render_demo.c
diff options
context:
space:
mode:
Diffstat (limited to 'config/render_demo.c')
-rw-r--r--config/render_demo.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/config/render_demo.c b/config/render_demo.c
new file mode 100644
index 0000000..761b552
--- /dev/null
+++ b/config/render_demo.c
@@ -0,0 +1,302 @@
+#include "ecex.h"
+
+#define RENDER_DEMO_BUF "*render-demo*"
+#define RENDER_DEMO_VAR_X "x_milli"
+#define RENDER_DEMO_VAR_Y "y_milli"
+#define RENDER_DEMO_VAR_TARGET_X "target_x_milli"
+#define RENDER_DEMO_VAR_TARGET_Y "target_y_milli"
+#define RENDER_DEMO_VAR_MOVING "moving"
+#define RENDER_DEMO_VAR_BOX_X "box_x"
+#define RENDER_DEMO_VAR_BOX_Y "box_y"
+#define RENDER_DEMO_VAR_BOX_SIZE "box_size"
+#define RENDER_DEMO_VAR_TRAVEL_X "travel_x"
+#define RENDER_DEMO_VAR_TRAVEL_Y "travel_y"
+#define RENDER_DEMO_VAR_AREA_X "area_x"
+#define RENDER_DEMO_VAR_AREA_Y "area_y"
+
+#define RENDER_DEMO_LABEL_TITLE 20
+#define RENDER_DEMO_LABEL_SUBTITLE 21
+#define RENDER_DEMO_LABEL_SAFE_DRAW 22
+#define RENDER_DEMO_LABEL_ANIM 23
+#define RENDER_DEMO_LABEL_POSITION 24
+#define RENDER_DEMO_LABEL_CLICK 25
+
+typedef struct render_demo_state {
+ ecex_t *ed;
+ int log_draw_count;
+} render_demo_state_t;
+
+static int render_demo_get(ecex_t *ed, render_demo_state_t *s, const char *name, int fallback) {
+ if (!ed || !s || !name) return fallback;
+ return ecex_var_i32(ed, s, name, fallback);
+}
+
+static void render_demo_set(ecex_t *ed, render_demo_state_t *s, const char *name, int value) {
+ if (!ed || !s || !name) return;
+ ecex_var_i32_set_scalar(ed, s, name, value);
+}
+
+static void render_demo_reset(ecex_t *ed, render_demo_state_t *s) {
+ ecex_log_ptr("render_demo_reset: state=", s);
+ if (!ed || !s) return;
+
+ /* Store mutable demo state in the host variable registry. This mirrors the
+ * Tetris plugin flow and avoids relying on CCDJIT struct-field writes for
+ * values that must survive renderer, animation, and mouse callbacks.
+ * Values are fixed-point integers: 0..1000 represents the available travel
+ * range inside the demo frame. */
+ render_demo_set(ed, s, RENDER_DEMO_VAR_X, 0);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_Y, 500);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_TARGET_X, 0);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_TARGET_Y, 500);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_MOVING, 0);
+ s->log_draw_count = 0;
+}
+
+static int render_demo_draw(ecex_t *ed, buffer_t *buffer, ecex_draw_context_t *ctx, void *userdata) {
+ render_demo_state_t *s = (render_demo_state_t *)userdata;
+ int w;
+ int h;
+ int cx;
+ int cy;
+ int cw;
+ int ch;
+ int line_h;
+ int box;
+ int travel;
+ int x_milli;
+ int y_milli;
+ int box_x;
+ int box_y;
+ int travel_y;
+ int area_x;
+ int area_y;
+
+ (void)buffer;
+ if (!ed || !ctx || !s) return 0;
+
+ s->log_draw_count++;
+ if (s->log_draw_count <= 4 || (s->log_draw_count % 60) == 0) {
+ ecex_log_int("render_demo_draw: count=", s->log_draw_count);
+ }
+
+ w = (int)ctx->w;
+ h = (int)ctx->h;
+ cx = (int)ctx->content_x;
+ cy = (int)ctx->content_y;
+ cw = (int)ctx->content_w;
+ ch = (int)ctx->content_h;
+ line_h = (int)ctx->line_height;
+ if (line_h < 18) line_h = 18;
+ if (cw < 1) cw = w - cx * 2;
+ if (ch < 1) ch = h - cy * 2;
+ if (cw < 1) cw = 1;
+ if (ch < 1) ch = 1;
+
+ ecex_draw_color_rgba8(ctx, 26, 28, 36, 255);
+ ecex_draw_rect_i(ctx, 0, 0, w, h);
+
+ ecex_draw_color_rgba8(ctx, 48, 96, 180, 255);
+ ecex_draw_rect_i(ctx, cx, cy, (cw * 55) / 100, line_h * 2);
+
+ ecex_draw_color_rgba8(ctx, 242, 230, 191, 255);
+ ecex_draw_rect_outline_i(ctx, cx, cy, cw, ch, 2);
+ ecex_draw_label_i(ctx, cx + 12, cy + 10, RENDER_DEMO_LABEL_TITLE);
+
+ ecex_draw_color_rgba8(ctx, 229, 89, 64, 255);
+ ecex_draw_line_i(ctx, cx, cy + ch, cx + cw, cy, 3);
+
+ ecex_draw_color_rgba8(ctx, 160, 230, 180, 255);
+ ecex_draw_label_i(ctx, cx + 12, cy + line_h * 3, RENDER_DEMO_LABEL_SUBTITLE);
+ ecex_draw_label_i(ctx, cx + 12, cy + line_h * 4, RENDER_DEMO_LABEL_SAFE_DRAW);
+ ecex_draw_label_i(ctx, cx + 12, cy + line_h * 5, RENDER_DEMO_LABEL_ANIM);
+ ecex_draw_label_i(ctx, cx + 12, cy + line_h * 6, RENDER_DEMO_LABEL_CLICK);
+
+ x_milli = render_demo_get(ed, s, RENDER_DEMO_VAR_X, 0);
+ y_milli = render_demo_get(ed, s, RENDER_DEMO_VAR_Y, 500);
+ ecex_draw_stat_i(ctx, cx + 12, cy + line_h * 8, RENDER_DEMO_LABEL_POSITION, x_milli);
+
+ box = line_h * 2;
+ if (box < 36) box = 36;
+ if (box > 72) box = 72;
+ travel = cw - box - 24;
+ if (travel < 0) travel = 0;
+ area_x = cx + 12;
+ area_y = cy + line_h * 10;
+ travel_y = ch - (area_y - cy) - box - 12;
+ if (travel_y < 0) travel_y = 0;
+ if (x_milli < 0) x_milli = 0;
+ if (x_milli > 1000) x_milli = 1000;
+ if (y_milli < 0) y_milli = 0;
+ if (y_milli > 1000) y_milli = 1000;
+ box_x = area_x + (travel * x_milli) / 1000;
+ box_y = area_y + (travel_y * y_milli) / 1000;
+
+ render_demo_set(ed, s, RENDER_DEMO_VAR_BOX_X, box_x);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_BOX_Y, box_y);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_BOX_SIZE, box);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_TRAVEL_X, travel);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_TRAVEL_Y, travel_y);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_AREA_X, area_x);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_AREA_Y, area_y);
+
+ ecex_draw_color_rgba8(ctx, 70, 76, 90, 255);
+ ecex_draw_rect_outline_i(ctx, area_x, area_y, travel + box, travel_y + box, 1);
+
+ ecex_draw_color_rgba8(ctx, 89, 242, 140, 255);
+ ecex_draw_rect_i(ctx, box_x, box_y, box, box);
+ ecex_draw_color_rgba8(ctx, 20, 24, 30, 255);
+ ecex_draw_rect_outline_i(ctx, box_x, box_y, box, box, 2);
+
+ return 0;
+}
+
+
+static int render_demo_clamp_milli(int value) {
+ if (value < 0) return 0;
+ if (value > 1000) return 1000;
+ return value;
+}
+
+static int render_demo_delta_step(int current, int target) {
+ int delta = target - current;
+ int step;
+ if (delta < 0) {
+ if (delta >= -4) return target;
+ step = delta / 5;
+ if (step == 0) step = -1;
+ return current + step;
+ }
+ if (delta <= 4) return target;
+ step = delta / 5;
+ if (step == 0) step = 1;
+ return current + step;
+}
+
+static int render_demo_tick(ecex_t *ed, buffer_t *buffer, int now_ms, void *userdata) {
+ render_demo_state_t *s = (render_demo_state_t *)userdata;
+ int x;
+ int y;
+ int target_x;
+ int target_y;
+ int next_x;
+ int next_y;
+
+ (void)buffer;
+ (void)now_ms;
+ if (!ed || !s) return 0;
+ if (!render_demo_get(ed, s, RENDER_DEMO_VAR_MOVING, 0)) return 0;
+
+ x = render_demo_get(ed, s, RENDER_DEMO_VAR_X, 0);
+ y = render_demo_get(ed, s, RENDER_DEMO_VAR_Y, 500);
+ target_x = render_demo_get(ed, s, RENDER_DEMO_VAR_TARGET_X, x);
+ target_y = render_demo_get(ed, s, RENDER_DEMO_VAR_TARGET_Y, y);
+
+ next_x = render_demo_delta_step(x, target_x);
+ next_y = render_demo_delta_step(y, target_y);
+ render_demo_set(ed, s, RENDER_DEMO_VAR_X, render_demo_clamp_milli(next_x));
+ render_demo_set(ed, s, RENDER_DEMO_VAR_Y, render_demo_clamp_milli(next_y));
+
+ if (next_x == target_x && next_y == target_y) {
+ render_demo_set(ed, s, RENDER_DEMO_VAR_MOVING, 0);
+ ecex_log("render_demo_tick: target reached");
+ }
+ return 1;
+}
+
+static int render_demo_mouse(ecex_t *ed, buffer_t *buffer, int event, int x, int y, int button, void *userdata) {
+ render_demo_state_t *s = (render_demo_state_t *)userdata;
+ int box;
+ int area_x;
+ int area_y;
+ int travel_x;
+ int travel_y;
+ int nx;
+ int ny;
+
+ (void)buffer;
+ if (!ed || !s || button != ECEX_MOUSE_BUTTON_LEFT) return 0;
+ if (event != ECEX_MOUSE_PRESS) return 0;
+
+ box = render_demo_get(ed, s, RENDER_DEMO_VAR_BOX_SIZE, 0);
+ area_x = render_demo_get(ed, s, RENDER_DEMO_VAR_AREA_X, 0);
+ area_y = render_demo_get(ed, s, RENDER_DEMO_VAR_AREA_Y, 0);
+ travel_x = render_demo_get(ed, s, RENDER_DEMO_VAR_TRAVEL_X, 0);
+ travel_y = render_demo_get(ed, s, RENDER_DEMO_VAR_TRAVEL_Y, 0);
+ if (box <= 0) return 0;
+
+ if (x < area_x || x >= area_x + travel_x + box ||
+ y < area_y || y >= area_y + travel_y + box) {
+ return 0;
+ }
+
+ nx = x - area_x - box / 2;
+ ny = y - area_y - box / 2;
+ if (travel_x <= 0) render_demo_set(ed, s, RENDER_DEMO_VAR_TARGET_X, 0);
+ else render_demo_set(ed, s, RENDER_DEMO_VAR_TARGET_X, render_demo_clamp_milli((nx * 1000) / travel_x));
+ if (travel_y <= 0) render_demo_set(ed, s, RENDER_DEMO_VAR_TARGET_Y, 0);
+ else render_demo_set(ed, s, RENDER_DEMO_VAR_TARGET_Y, render_demo_clamp_milli((ny * 1000) / travel_y));
+
+ render_demo_set(ed, s, RENDER_DEMO_VAR_MOVING, 1);
+ ecex_log("render_demo_mouse: target set");
+ return 1;
+}
+
+static void render_demo_free_state(void *userdata) {
+ render_demo_state_t *s = (render_demo_state_t *)userdata;
+ if (!s) return;
+ ecex_var_free_owner(s->ed, s);
+ ecex_config_free(s);
+}
+
+static int cmd_render_demo(ecex_t *ed) {
+ buffer_t *buffer;
+ render_demo_state_t *s;
+
+ ecex_log("cmd_render_demo: enter");
+ if (!ed) return -1;
+
+ buffer = ecex_find_buffer(ed, RENDER_DEMO_BUF);
+ if (!buffer) buffer = ecex_create_interactive_buffer(ed, RENDER_DEMO_BUF);
+ if (!buffer) return -1;
+
+ s = (render_demo_state_t *)ecex_buffer_renderer_userdata(buffer);
+ if (!s) {
+ s = (render_demo_state_t *)ecex_config_calloc(1, sizeof(*s));
+ if (!s) return -1;
+ s->ed = ed;
+ render_demo_reset(ed, s);
+
+ if (ecex_buffer_set_renderer(buffer, render_demo_draw, s, render_demo_free_state, ECEX_RENDER_REPLACE_CONTENT) != 0) {
+ render_demo_free_state(s);
+ return -1;
+ }
+ if (ecex_buffer_set_mouse_handler(buffer, render_demo_mouse, s, 0) != 0) {
+ ecex_buffer_clear_renderer(buffer);
+ return -1;
+ }
+ if (ecex_buffer_set_animation_ms(buffer, render_demo_tick, s, 0, 60) != 0) {
+ ecex_buffer_clear_mouse_handler(buffer);
+ ecex_buffer_clear_renderer(buffer);
+ return -1;
+ }
+ }
+
+ if (ecex_buffer_replace_text(buffer, "Render demo. The renderer replaces normal buffer content.\n") != 0) {
+ return -1;
+ }
+ ecex_buffer_set_modified(buffer, 0);
+
+ return ecex_switch_buffer(ed, RENDER_DEMO_BUF);
+}
+
+int ecex_render_demo_plugin(ecex_t *ed) {
+ ECEX_CONFIG_COMMAND("render-demo", cmd_render_demo);
+ return 0;
+}
+
+#ifndef ECEX_NO_STANDALONE_CONFIG
+ECEX_CONFIG_BEGIN
+ ECEX_CONFIG_INCLUDE(ecex_render_demo_plugin);
+ECEX_CONFIG_END
+#endif