changeset 480:c1f64d451230

core: mlk_action has a start callback
author David Demelier <markand@malikania.fr>
date Mon, 27 Feb 2023 17:26:00 +0100
parents 8e41ed5474cf
children 4b99b760e99c
files examples/example-action/example-action.c libmlk-core/mlk/core/action-script.c libmlk-core/mlk/core/action-script.h libmlk-core/mlk/core/action-stack.c libmlk-core/mlk/core/action-stack.h libmlk-core/mlk/core/action.c libmlk-core/mlk/core/action.h man/mlk-action.3 man/mlk_action_start.3 tests/test-action-script.c tests/test-action.c
diffstat 11 files changed, 211 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-action/example-action.c	Mon Feb 27 16:33:33 2023 +0100
+++ b/examples/example-action/example-action.c	Mon Feb 27 17:26:00 2023 +0100
@@ -122,8 +122,8 @@
 static void     script_init_quest1(void);
 static void     script_init_quest2(void);
 
-static void     terminate_quest1(struct mlk_action *);
-static void     terminate_quest2(struct mlk_action *);
+static void     response_quest1_start(struct mlk_action *);
+static void     response_quest2_start(struct mlk_action *);
 
 static struct item quest1[] = {
 	{
@@ -171,20 +171,16 @@
 			.handle = item_handle,
 			.update = item_update,
 			.draw = item_draw,
-			.end = terminate_quest1
 		}
 	},
-
-	/*
-	 * This final action is a placeholder that will be updated once the
-	 * last message question is completed through the end callback.
-	 */
+	/* Text will be replaced on start depending on the question. */
 	{
 		.msg = {
 			.flags = MESSAGE_FLAGS_FADEOUT
 		},
 		.act = {
 			.data = &quest1[3].msg,
+			.start = response_quest1_start,
 			.handle = item_handle,
 			.update = item_update,
 			.draw = item_draw
@@ -222,7 +218,6 @@
 			.handle = item_handle,
 			.update = item_update,
 			.draw = item_draw,
-			.end = terminate_quest2
 		}
 	},
 
@@ -233,6 +228,7 @@
 		},
 		.act = {
 			.data = &quest2[2].msg,
+			.start = response_quest2_start,
 			.handle = item_handle,
 			.update = item_update,
 			.draw = item_draw
@@ -336,6 +332,8 @@
 		if ((err = mlk_action_script_append(&script, &m[i].act)) < 0)
 			mlk_panicf("%s", mlk_err_string(err));
 	}
+
+	mlk_action_script_start(&script);
 }
 
 static void
@@ -345,47 +343,47 @@
 }
 
 static void
-terminate_quest1(struct mlk_action *act)
+script_init_quest2(void)
+{
+	script_init_quest(quest2, MLK_UTIL_SIZE(quest2));
+}
+
+static void
+response_quest1_start(struct mlk_action *act)
 {
 	static const char *line;
 
+	struct message *question = &quest1[2].msg;
 	struct message *cur = act->data;
-	struct message *nxt = &quest1[3].msg;
 
-	nxt->linesz = 1;
-	nxt->lines = &line;
+	cur->linesz = 1;
+	cur->lines = &line;
 
-	if (cur->index == 0)
+	if (question->index == 0)
 		 line = "Don't be so confident";
 	else
 		 line = "Nevermind, I'll do it myself";
 
-	message_query(nxt, NULL, &nxt->h);
+	message_query(cur, NULL, &cur->h);
 }
 
 static void
-terminate_quest2(struct mlk_action *act)
+response_quest2_start(struct mlk_action *act)
 {
 	static const char *line;
 
+	struct message *question = &quest2[1].msg;
 	struct message *cur = act->data;
-	struct message *nxt = &quest2[2].msg;
 
-	nxt->linesz = 1;
-	nxt->lines = &line;
+	cur->linesz = 1;
+	cur->lines = &line;
 
-	if (cur->index == 0)
+	if (question->index == 0)
 		line = "Go away!";
 	else
 		line = "Install OpenBSD then";
 
-	message_query(nxt, NULL, &nxt->h);
-}
-
-static void
-script_init_quest2(void)
-{
-	script_init_quest(quest2, MLK_UTIL_SIZE(quest2));
+	message_query(cur, NULL, &cur->h);
 }
 
 static void
--- a/libmlk-core/mlk/core/action-script.c	Mon Feb 27 16:33:33 2023 +0100
+++ b/libmlk-core/mlk/core/action-script.c	Mon Feb 27 17:26:00 2023 +0100
@@ -43,6 +43,17 @@
 	s->size = s->cur = 0;
 }
 
+void
+mlk_action_script_start(struct mlk_action_script *s)
+{
+	assert(s);
+
+	struct mlk_action *a;
+
+	if ((a = current(s)))
+		mlk_action_start(a);
+}
+
 int
 mlk_action_script_append(struct mlk_action_script *s, struct mlk_action *a)
 {
@@ -83,6 +94,10 @@
 	if (mlk_action_update(a, ticks)) {
 		mlk_action_end(a);
 		s->cur++;
+
+		/* Start this action now. */
+		if ((a = current(s)))
+			mlk_action_start(a);
 	}
 
 	return s->cur >= s->size;
--- a/libmlk-core/mlk/core/action-script.h	Mon Feb 27 16:33:33 2023 +0100
+++ b/libmlk-core/mlk/core/action-script.h	Mon Feb 27 17:26:00 2023 +0100
@@ -39,6 +39,9 @@
 void
 mlk_action_script_init(struct mlk_action_script *, struct mlk_action **, size_t);
 
+void
+mlk_action_script_start(struct mlk_action_script *);
+
 int
 mlk_action_script_append(struct mlk_action_script *, struct mlk_action *);
 
--- a/libmlk-core/mlk/core/action-stack.c	Mon Feb 27 16:33:33 2023 +0100
+++ b/libmlk-core/mlk/core/action-stack.c	Mon Feb 27 17:26:00 2023 +0100
@@ -55,6 +55,18 @@
 }
 
 void
+mlk_action_stack_start(struct mlk_action_stack *st)
+{
+	assert(st);
+
+	struct mlk_action *act;
+
+	FOREACH(st, act)
+		if (act)
+			mlk_action_start(act);
+}
+
+void
 mlk_action_stack_handle(struct mlk_action_stack *st, const union mlk_event *ev)
 {
 	assert(st);
--- a/libmlk-core/mlk/core/action-stack.h	Mon Feb 27 16:33:33 2023 +0100
+++ b/libmlk-core/mlk/core/action-stack.h	Mon Feb 27 17:26:00 2023 +0100
@@ -41,6 +41,9 @@
 mlk_action_stack_add(struct mlk_action_stack *, struct mlk_action *);
 
 void
+mlk_action_stack_start(struct mlk_action_stack *);
+
+void
 mlk_action_stack_handle(struct mlk_action_stack *, const union mlk_event *);
 
 int
--- a/libmlk-core/mlk/core/action.c	Mon Feb 27 16:33:33 2023 +0100
+++ b/libmlk-core/mlk/core/action.c	Mon Feb 27 17:26:00 2023 +0100
@@ -21,6 +21,15 @@
 #include "action.h"
 
 void
+mlk_action_start(struct mlk_action *act)
+{
+	assert(act);
+
+	if (act->start)
+		act->start(act);
+}
+
+void
 mlk_action_handle(struct mlk_action *act, const union mlk_event *ev)
 {
 	assert(act);
--- a/libmlk-core/mlk/core/action.h	Mon Feb 27 16:33:33 2023 +0100
+++ b/libmlk-core/mlk/core/action.h	Mon Feb 27 17:26:00 2023 +0100
@@ -25,6 +25,7 @@
 
 struct mlk_action {
 	void *data;
+	void (*start)(struct mlk_action *);
 	void (*handle)(struct mlk_action *, const union mlk_event *);
 	int (*update)(struct mlk_action *, unsigned int);
 	void (*draw)(struct mlk_action *);
@@ -35,6 +36,9 @@
 MLK_CORE_BEGIN_DECLS
 
 void
+mlk_action_start(struct mlk_action *);
+
+void
 mlk_action_handle(struct mlk_action *, const union mlk_event *);
 
 int
--- a/man/mlk-action.3	Mon Feb 27 16:33:33 2023 +0100
+++ b/man/mlk-action.3	Mon Feb 27 17:26:00 2023 +0100
@@ -31,6 +31,7 @@
 .Bd -literal
 struct mlk_action {
 	void *data;
+	void (*start)(struct mlk_action *self);
 	void (*handle)(struct mlk_action *self, const union mlk_event *ev);
 	int (*update)(struct mlk_action *self, unsigned int ticks);
 	void (*draw)(struct mlk_action *self);
@@ -44,6 +45,11 @@
 .Bl -tag
 .It Va data
 Optional user data.
+.It Va start
+This function is called when the action is going to start. User can set a
+function to prepare the action especially in a sequence (see
+.Xr mlk-action-script 3
+for example).
 .It Va handle
 Handle the event
 .Fa ev .
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/mlk_action_start.3	Mon Feb 27 17:26:00 2023 +0100
@@ -0,0 +1,23 @@
+.Dd $Mdocdate$
+.Dt MLK_ACTION_START 3
+.Os
+.Sh NAME
+.Nm mlk_action_start
+.Nd start an action
+.Sh LIBRARY
+libmlk-core (-lmlk-core)
+.Sh SYNOPSIS
+.In mlk/core/action.h
+.Ft void
+.Fn mlk_action_start "struct mlk_action *self"
+.Sh DESCRIPTION
+Invoke the start callback on the action
+.Fa self
+if it is not null.
+.Sh SEE ALSO
+.Xr mlk-action 3
+.Sh AUTHORS
+The
+.Nm
+library was written by
+.An David Demelier Aq Mt markand@malikania.fr .
--- a/tests/test-action-script.c	Mon Feb 27 16:33:33 2023 +0100
+++ b/tests/test-action-script.c	Mon Feb 27 17:26:00 2023 +0100
@@ -24,6 +24,7 @@
 #include <dt.h>
 
 struct invokes {
+	int start;
 	int handle;
 	int update;
 	int draw;
@@ -33,6 +34,7 @@
 
 #define INIT(dat, up) {         \
 	.data = (dat),          \
+	.start = my_start,      \
 	.handle = my_handle,    \
 	.update = (up),         \
 	.draw = my_draw,        \
@@ -41,6 +43,12 @@
 }
 
 static void
+my_start(struct mlk_action *act)
+{
+	((struct invokes *)act->data)->start++;
+}
+
+static void
 my_handle(struct mlk_action *act, const union mlk_event *ev)
 {
 	(void)ev;
@@ -238,18 +246,23 @@
 	DT_ASSERT(mlk_action_script_append(&sc, &table[1].act) == 0);
 	DT_ASSERT(mlk_action_script_append(&sc, &table[2].act) == 0);
 
+	mlk_action_script_start(&sc);
+
 	/* 0 -> 1 */
 	DT_ASSERT(!mlk_action_script_update(&sc, 0));
+	DT_EQ_INT(table[0].inv.start, 1);
 	DT_EQ_INT(table[0].inv.handle, 0);
 	DT_EQ_INT(table[0].inv.update, 1);
 	DT_EQ_INT(table[0].inv.draw, 0);
 	DT_EQ_INT(table[0].inv.end, 1);
 	DT_EQ_INT(table[0].inv.finish, 0);
+	DT_EQ_INT(table[1].inv.start, 1);
 	DT_EQ_INT(table[1].inv.handle, 0);
 	DT_EQ_INT(table[1].inv.update, 0);
 	DT_EQ_INT(table[1].inv.draw, 0);
 	DT_EQ_INT(table[1].inv.end, 0);
 	DT_EQ_INT(table[1].inv.finish, 0);
+	DT_EQ_INT(table[2].inv.start, 0);
 	DT_EQ_INT(table[2].inv.handle, 0);
 	DT_EQ_INT(table[2].inv.update, 0);
 	DT_EQ_INT(table[2].inv.draw, 0);
@@ -258,16 +271,19 @@
 
 	/* 1 -> 2 */
 	DT_ASSERT(!mlk_action_script_update(&sc, 0));
+	DT_EQ_INT(table[0].inv.start, 1);
 	DT_EQ_INT(table[0].inv.handle, 0);
 	DT_EQ_INT(table[0].inv.update, 1);
 	DT_EQ_INT(table[0].inv.draw, 0);
 	DT_EQ_INT(table[0].inv.end, 1);
 	DT_EQ_INT(table[0].inv.finish, 0);
+	DT_EQ_INT(table[1].inv.start, 1);
 	DT_EQ_INT(table[1].inv.handle, 0);
 	DT_EQ_INT(table[1].inv.update, 1);
 	DT_EQ_INT(table[1].inv.draw, 0);
 	DT_EQ_INT(table[1].inv.end, 1);
 	DT_EQ_INT(table[1].inv.finish, 0);
+	DT_EQ_INT(table[2].inv.start, 1);
 	DT_EQ_INT(table[2].inv.handle, 0);
 	DT_EQ_INT(table[2].inv.update, 0);
 	DT_EQ_INT(table[2].inv.draw, 0);
@@ -278,16 +294,19 @@
 	DT_ASSERT(!mlk_action_script_update(&sc, 0));
 	DT_ASSERT(!mlk_action_script_update(&sc, 0));
 	DT_ASSERT(!mlk_action_script_update(&sc, 0));
+	DT_EQ_INT(table[0].inv.start, 1);
 	DT_EQ_INT(table[0].inv.handle, 0);
 	DT_EQ_INT(table[0].inv.update, 1);
 	DT_EQ_INT(table[0].inv.draw, 0);
 	DT_EQ_INT(table[0].inv.end, 1);
 	DT_EQ_INT(table[0].inv.finish, 0);
+	DT_EQ_INT(table[1].inv.start, 1);
 	DT_EQ_INT(table[1].inv.handle, 0);
 	DT_EQ_INT(table[1].inv.update, 1);
 	DT_EQ_INT(table[1].inv.draw, 0);
 	DT_EQ_INT(table[1].inv.end, 1);
 	DT_EQ_INT(table[1].inv.finish, 0);
+	DT_EQ_INT(table[2].inv.start, 1);
 	DT_EQ_INT(table[2].inv.handle, 0);
 	DT_EQ_INT(table[2].inv.update, 3);
 	DT_EQ_INT(table[2].inv.draw, 0);
@@ -297,16 +316,19 @@
 	/* Now, change its update function to complete the script. */
 	table[2].act.update = my_update_true;
 	DT_ASSERT(mlk_action_script_update(&sc, 0));
+	DT_EQ_INT(table[0].inv.start, 1);
 	DT_EQ_INT(table[0].inv.handle, 0);
 	DT_EQ_INT(table[0].inv.update, 1);
 	DT_EQ_INT(table[0].inv.draw, 0);
 	DT_EQ_INT(table[0].inv.end, 1);
 	DT_EQ_INT(table[0].inv.finish, 0);
+	DT_EQ_INT(table[1].inv.start, 1);
 	DT_EQ_INT(table[1].inv.handle, 0);
 	DT_EQ_INT(table[1].inv.update, 1);
 	DT_EQ_INT(table[1].inv.draw, 0);
 	DT_EQ_INT(table[1].inv.end, 1);
 	DT_EQ_INT(table[1].inv.finish, 0);
+	DT_EQ_INT(table[2].inv.start, 1);
 	DT_EQ_INT(table[2].inv.handle, 0);
 	DT_EQ_INT(table[2].inv.update, 4);
 	DT_EQ_INT(table[2].inv.draw, 0);
--- a/tests/test-action.c	Mon Feb 27 16:33:33 2023 +0100
+++ b/tests/test-action.c	Mon Feb 27 17:26:00 2023 +0100
@@ -24,6 +24,7 @@
 #include <dt.h>
 
 struct invokes {
+	int start;
 	int handle;
 	int update;
 	int draw;
@@ -35,6 +36,7 @@
 
 #define INIT(dat, up) {         \
         .data = (dat),          \
+        .start = my_start,      \
         .handle = my_handle,    \
         .update = (up),         \
         .draw = my_draw,        \
@@ -43,6 +45,12 @@
 }
 
 static void
+my_start(struct mlk_action *act)
+{
+	((struct invokes *)act->data)->start = 1;
+}
+
+static void
 my_handle(struct mlk_action *act, const union mlk_event *ev)
 {
 	(void)ev;
@@ -89,6 +97,22 @@
 }
 
 static void
+test_basics_start(void)
+{
+	struct invokes inv = {0};
+	struct mlk_action act = INIT(&inv, my_update_true);
+
+	mlk_action_start(&act);
+
+	DT_ASSERT(inv.start);
+	DT_ASSERT(!inv.handle);
+	DT_ASSERT(!inv.update);
+	DT_ASSERT(!inv.draw);
+	DT_ASSERT(!inv.end);
+	DT_ASSERT(!inv.finish);
+}
+
+static void
 test_basics_handle(void)
 {
 	struct invokes inv = {0};
@@ -96,6 +120,7 @@
 
 	mlk_action_handle(&act, &dummy);
 
+	DT_ASSERT(!inv.start);
 	DT_ASSERT(inv.handle);
 	DT_ASSERT(!inv.update);
 	DT_ASSERT(!inv.draw);
@@ -116,6 +141,7 @@
 
 	/* True version. */
 	DT_ASSERT(mlk_action_update(&table[0].act, 0));
+	DT_ASSERT(!table[0].inv.start);
 	DT_ASSERT(!table[0].inv.handle);
 	DT_ASSERT(table[0].inv.update);
 	DT_ASSERT(!table[0].inv.draw);
@@ -124,6 +150,7 @@
 
 	/* False version. */
 	DT_ASSERT(!mlk_action_update(&table[1].act, 0));
+	DT_ASSERT(!table[1].inv.start);
 	DT_ASSERT(!table[1].inv.handle);
 	DT_ASSERT(table[1].inv.update);
 	DT_ASSERT(!table[1].inv.draw);
@@ -139,6 +166,7 @@
 
 	mlk_action_draw(&act);
 
+	DT_ASSERT(!inv.start);
 	DT_ASSERT(!inv.handle);
 	DT_ASSERT(!inv.update);
 	DT_ASSERT(inv.draw);
@@ -154,6 +182,7 @@
 
 	mlk_action_end(&act);
 
+	DT_ASSERT(!inv.start);
 	DT_ASSERT(!inv.handle);
 	DT_ASSERT(!inv.update);
 	DT_ASSERT(!inv.draw);
@@ -169,6 +198,7 @@
 
 	mlk_action_finish(&act);
 
+	DT_ASSERT(!inv.start);
 	DT_ASSERT(!inv.handle);
 	DT_ASSERT(!inv.update);
 	DT_ASSERT(!inv.draw);
@@ -196,15 +226,14 @@
 }
 
 static void
-test_stack_handle(void)
+test_stack_start(void)
 {
 	struct {
-		int called;
+		struct invokes inv;
 		struct mlk_action act;
 	} table[] = {
-		{ 0, { .data = &table[0].called, .handle = my_handle } },
-		{ 0, { .data = &table[1].called, .handle = my_handle } },
-		{ 0, { .data = &table[2].called, .handle = my_handle } },
+		{ .act = INIT(&table[0], my_update_true)        },
+		{ .act = INIT(&table[1], my_update_true)        },
 	};
 
 	struct mlk_action *actions[10];
@@ -213,12 +242,55 @@
 	mlk_action_stack_init(&st, actions, 10);
 	mlk_action_stack_add(&st, &table[0].act);
 	mlk_action_stack_add(&st, &table[1].act);
-	mlk_action_stack_add(&st, &table[2].act);
+	mlk_action_stack_start(&st);
+
+	DT_ASSERT(table[0].inv.start);
+	DT_ASSERT(!table[0].inv.handle);
+	DT_ASSERT(!table[0].inv.update);
+	DT_ASSERT(!table[0].inv.draw);
+	DT_ASSERT(!table[0].inv.end);
+	DT_ASSERT(!table[0].inv.finish);
+
+	DT_ASSERT(table[1].inv.start);
+	DT_ASSERT(!table[1].inv.handle);
+	DT_ASSERT(!table[1].inv.update);
+	DT_ASSERT(!table[1].inv.draw);
+	DT_ASSERT(!table[1].inv.end);
+	DT_ASSERT(!table[1].inv.finish);
+}
+
+static void
+test_stack_handle(void)
+{
+	struct {
+		struct invokes inv;
+		struct mlk_action act;
+	} table[] = {
+		{ .act = INIT(&table[0], my_update_true)        },
+		{ .act = INIT(&table[1], my_update_true)        },
+	};
+
+	struct mlk_action *actions[10];
+	struct mlk_action_stack st = {0};
+
+	mlk_action_stack_init(&st, actions, 10);
+	mlk_action_stack_add(&st, &table[0].act);
+	mlk_action_stack_add(&st, &table[1].act);
 	mlk_action_stack_handle(&st, &dummy);
 
-	DT_ASSERT(table[0].called);
-	DT_ASSERT(table[1].called);
-	DT_ASSERT(table[2].called);
+	DT_ASSERT(!table[0].inv.start);
+	DT_ASSERT(table[0].inv.handle);
+	DT_ASSERT(!table[0].inv.update);
+	DT_ASSERT(!table[0].inv.draw);
+	DT_ASSERT(!table[0].inv.end);
+	DT_ASSERT(!table[0].inv.finish);
+
+	DT_ASSERT(!table[1].inv.start);
+	DT_ASSERT(table[1].inv.handle);
+	DT_ASSERT(!table[1].inv.update);
+	DT_ASSERT(!table[1].inv.draw);
+	DT_ASSERT(!table[1].inv.end);
+	DT_ASSERT(!table[1].inv.finish);
 }
 
 static void
@@ -398,7 +470,7 @@
 		struct mlk_action act;
 	} table[] = {
 		{ .act = INIT(&table[0], my_update_true)        },
-		{ .act = INIT(&table[0], my_update_false)       },
+		{ .act = INIT(&table[1], my_update_false)       },
 	};
 
 	struct mlk_action *actions[10];
@@ -415,22 +487,24 @@
 	DT_ASSERT(table[0].inv.end);
 	DT_ASSERT(table[0].inv.finish);
 
-	DT_ASSERT(!table[0].inv.handle);
-	DT_ASSERT(!table[0].inv.update);
-	DT_ASSERT(!table[0].inv.draw);
-	DT_ASSERT(table[0].inv.end);
-	DT_ASSERT(table[0].inv.finish);
+	DT_ASSERT(!table[1].inv.handle);
+	DT_ASSERT(!table[1].inv.update);
+	DT_ASSERT(!table[1].inv.draw);
+	DT_ASSERT(table[1].inv.end);
+	DT_ASSERT(table[1].inv.finish);
 }
 
 int
 main(void)
 {
+	DT_RUN(test_basics_start);
 	DT_RUN(test_basics_handle);
 	DT_RUN(test_basics_update);
 	DT_RUN(test_basics_draw);
 	DT_RUN(test_basics_end);
 	DT_RUN(test_basics_finish);
 	DT_RUN(test_stack_add);
+	DT_RUN(test_stack_start);
 	DT_RUN(test_stack_handle);
 	DT_RUN(test_stack_update);
 	DT_RUN(test_stack_draw);