changeset 74:4991bf5f2343

core: implement inhibit system, closes #2468 @1h
author David Demelier <markand@malikania.fr>
date Fri, 31 Jan 2020 13:47:49 +0100
parents b49d8475a611
children ac97053d8e2e
files Makefile src/adventure/main.c src/core/game.c src/core/game.h src/core/inhibit.c src/core/inhibit.h src/core/painter.h
diffstat 7 files changed, 162 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Jan 31 08:09:05 2020 +0100
+++ b/Makefile	Fri Jan 31 13:47:49 2020 +0100
@@ -32,6 +32,7 @@
                 src/core/font.c \
                 src/core/game.c \
                 src/core/image.c \
+                src/core/inhibit.c \
                 src/core/map.c \
                 src/core/map_state.c \
                 src/core/message.c \
--- a/src/adventure/main.c	Fri Jan 31 08:09:05 2020 +0100
+++ b/src/adventure/main.c	Fri Jan 31 13:47:49 2020 +0100
@@ -26,6 +26,7 @@
 #include "font.h"
 #include "game.h"
 #include "image.h"
+#include "inhibit.h"
 #include "map.h"
 #include "map_state.h"
 #include "message.h"
@@ -99,11 +100,19 @@
 	wait_action(&w, &ac);
 	script_append(&sc, &ac);
 
+	/* Inhibit input. */
+	inhibit_action(INHIBIT_STATE_INPUT, &ac);
+	script_append(&sc, &ac);
+
 	message_start(&msg);
 	message_action(&msg, &ac);
 	ac.end = myresult;
+	script_append(&sc, &ac);
 
+	/* Put it back. */
+	inhibit_action(INHIBIT_NONE, &ac);
 	script_append(&sc, &ac);
+
 	script_start(&sc);
 	script_action(&sc, &ac);
 
--- a/src/core/game.c	Fri Jan 31 08:09:05 2020 +0100
+++ b/src/core/game.c	Fri Jan 31 13:47:49 2020 +0100
@@ -24,10 +24,7 @@
 #include "state.h"
 #include "painter.h"
 
-struct game game = {
-	.state = NULL,
-	.state_next = NULL
-};
+struct game game;
 
 static struct action *
 find_empty_action(void)
@@ -73,6 +70,7 @@
 			continue;
 
 		if (a->update(a, ticks)) {
+			puts("HERE ACTION HAS FINISHED");
 			if (a->end)
 				a->end(a);
 			if (a->finish)
@@ -109,7 +107,7 @@
 {
 	assert(event);
 
-	if (game.state)
+	if (game.state && !(game.inhibit & INHIBIT_STATE_INPUT))
 		game.state->handle(event);
 
 	handle_actions(event);
@@ -118,30 +116,32 @@
 void
 game_update(unsigned int ticks)
 {
-	/* Change state if any. */
-	if (game.state_next) {
-		/* Inform the current state we're gonna leave it. */
-		if (game.state)
-			game.state->leave();
+	if (!(game.inhibit & INHIBIT_STATE_UPDATE)) {
+		/* Change state if any. */
+		if (game.state_next) {
+			/* Inform the current state we're gonna leave it. */
+			if (game.state)
+				game.state->leave();
 
-		game.state = game.state_next;
-		game.state->enter();
-		game.state_next = NULL;
+			game.state = game.state_next;
+			game.state->enter();
+			game.state_next = NULL;
 
-		/* Remove any actions that must be deleted. */
-		clear_actions();
+			/* Remove any actions that must be deleted. */
+			clear_actions();
+		}
+
+		if (game.state)
+			game.state->update(ticks);
 	}
 
-	if (game.state)
-		game.state->update(ticks);
-
 	update_actions(ticks);
 }
 
 void
 game_draw(void)
 {
-	if (game.state)
+	if (game.state && !(game.inhibit & INHIBIT_STATE_DRAW))
 		game.state->draw();
 
 	draw_actions();
--- a/src/core/game.h	Fri Jan 31 08:09:05 2020 +0100
+++ b/src/core/game.h	Fri Jan 31 13:47:49 2020 +0100
@@ -27,11 +27,12 @@
 #include <stdbool.h>
 
 #include "action.h"
+#include "inhibit.h"
 
 /**
  * \brief Max number of actions allowed at the same time.
  */
-#define GAME_ACTIONS_MAX 32
+#define GAME_ACTIONS_MAX 128
 
 struct state;
 
@@ -41,6 +42,9 @@
  * \brief Main game object.
  */
 struct game {
+	/* Inhibition */
+	enum inhibit inhibit;           /*!< (RW) What to disable. */
+
 	/* Game states. */
 	struct state *state;            /*!< (RO) Current state  */
 	struct state *state_next;       /*!< (RO) Next state */
@@ -57,9 +61,8 @@
 /**
  * Request to change state.
  *
- * This function will only update state after the next \a game_update call.
- *
- * If quick is true, change state immediately.
+ * This function will only update state after the next \ref  game_update call
+ * unless quick is set to true.
  *
  * \pre state != NULL
  * \param state the new state
@@ -98,6 +101,7 @@
  *
  * \pre action != NULL
  * \param action the action to copy
+ * \note The core API **never** add actions by itself.
  */
 void
 game_add_action(const struct action *action);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/inhibit.c	Fri Jan 31 13:47:49 2020 +0100
@@ -0,0 +1,53 @@
+/*
+ * inhibit.c -- disable specific game behavior
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "action.h"
+#include "inhibit.h"
+#include "game.h"
+#include "util.h"
+
+static bool
+update(struct action *a, unsigned int ticks)
+{
+	(void)ticks;
+
+	game.inhibit = *((enum inhibit *)a->data);
+
+	return true;
+}
+
+static void
+finish(struct action *a)
+{
+	free(a->data);
+}
+
+void
+inhibit_action(enum inhibit mode, struct action *a)
+{
+	assert(a);
+
+	memset(a, 0, sizeof (struct action));
+	a->data = ememdup(&mode, sizeof (enum inhibit));
+	a->update = update;
+	a->finish = finish;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/inhibit.h	Fri Jan 31 13:47:49 2020 +0100
@@ -0,0 +1,68 @@
+/*
+ * inhibit.h -- disable specific game behavior
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MOLKO_INHIBIT_H
+#define MOLKO_INHIBIT_H
+
+/**
+ * \file inhibit.h
+ * \brief Disable specific game behavior.
+ */
+
+struct action;
+
+/**
+ * \brief Game inhibition.
+ *
+ * This enum is used to alter the game behavior.
+ */
+enum inhibit {
+	/**
+	 * Nothing.
+	 */
+	INHIBIT_NONE,
+
+	/**
+	 * Disable input handling in current state.
+	 */
+	INHIBIT_STATE_INPUT        = (1 << 0),
+
+	/**
+	 * Disable current state updates.
+	 */
+	INHIBIT_STATE_UPDATE       = (1 << 1),
+
+	/**
+	 * Disable current state rendering.
+	 */
+	INHIBIT_STATE_DRAW         = (1 << 2)
+};
+
+/**
+ * Create an action to inhibit the system.
+ *
+ * The mode will replace the actual inhibit modes rather than adding new flags.
+ *
+ * \pre a != NULL
+ * \param mode the new mode
+ * \param a the action to fill
+ */
+void
+inhibit_action(enum inhibit mode, struct action *a);
+
+#endif /* !MOLKO_INHIBIT_H */
--- a/src/core/painter.h	Fri Jan 31 08:09:05 2020 +0100
+++ b/src/core/painter.h	Fri Jan 31 13:47:49 2020 +0100
@@ -48,8 +48,8 @@
  * If texture is NULL, use default context aka the window.
  *
  * \param tex the texture
- * \see PAINTER_BEGIN
- * \see PAINTER_END
+ * \see \ref PAINTER_BEGIN
+ * \see \ref PAINTER_END
  */
 void
 painter_set_target(struct texture *tex);
@@ -120,7 +120,7 @@
  *
  * \pre tex != NULL
  * \param tex the texture to use
- * \see PAINTER_END
+ * \see \ref PAINTER_END
  */
 #define PAINTER_BEGIN(tex    )                                          \
 do {                                                                    \
@@ -132,7 +132,7 @@
 /**
  * Use this macro at the end of rendering into a given texture.
  *
- * \see PAINTER_BEGIN
+ * \see \ref PAINTER_BEGIN
  */
 #define PAINTER_END()                                                   \
         painter_set_target(__current_texture__);                        \