diff src/core/message.c @ 64:da9b7462ab92

core: implement question, closes #2464 @2h
author David Demelier <markand@malikania.fr>
date Thu, 23 Jan 2020 20:44:01 +0100
parents d07acc6ee4d9
children 80a913d25aa9
line wrap: on
line diff
--- a/src/core/message.c	Thu Jan 23 13:48:49 2020 +0100
+++ b/src/core/message.c	Thu Jan 23 20:44:01 2020 +0100
@@ -18,6 +18,7 @@
 
 #include <assert.h>
 
+#include "event.h"
 #include "font.h"
 #include "message.h"
 #include "painter.h"
@@ -25,19 +26,19 @@
 #include "texture.h"
 #include "window.h"
 
-#define MESSAGE_SPEED   1000    /* Time delay for animations */
+#define MESSAGE_SPEED   150     /* Time delay for animations */
 #define MESSAGE_TIMEOUT 5000    /* Time for auto-closing */
 
 static unsigned int
-average_height(const struct message *msg)
+average(const struct message *msg)
 {
 	unsigned int n = 0;
 	unsigned int total = 0;
 
 	for (int i = 0; i < 6; ++i) {
-		if (msg->ttext[i]) {
+		if (msg->textures[i]) {
 			n += 1;
-			total += texture_height(msg->ttext[i]);
+			total += texture_height(msg->textures[i]);
 		}
 	}
 
@@ -45,15 +46,44 @@
 }
 
 static void
+clear(struct message *msg)
+{
+	for (unsigned int i = 0; i < 12; ++i) {
+		if (msg->textures[i]) {
+			texture_close(msg->textures[i]);
+			msg->textures[i] = NULL;
+		}
+	}
+}
+
+static void
 redraw(struct message *msg)
 {
+	clear(msg);
+
 	/* Generate textures if not already done. */
-	for (int i = 0; i < 6; ++i) {
-		if (!msg->text[i] || msg->ttext[i] || msg->stext[i])
+	for (unsigned int i = 0; i < 6; ++i) {
+		if (!msg->text[i])
 			continue;
 
-		msg->stext[i] = font_render(msg->font, msg->text[i], 0x000000ff);
-		msg->ttext[i] = font_render(msg->font, msg->text[i], msg->color);
+		/* Normal lines of text. */
+		unsigned long color = msg->colors[0];
+
+		if (msg->flags & MESSAGE_QUESTION && msg->index == i)
+			color = msg->colors[1];
+
+		if (!msg->textures[i])
+			msg->textures[i] = font_render(
+			    msg->font,
+			    msg->text[i],
+			    color
+			);
+		if (!msg->textures[i + 6])
+			msg->textures[i + 6] = font_render(
+			    msg->font,
+			    msg->text[i],
+			    0x000000ff
+			);
 	}
 }
 
@@ -63,8 +93,40 @@
 	assert(msg);
 
 	msg->elapsed = 0;
-	msg->alpha = 0;
 	msg->state = MESSAGE_OPENING;
+	msg->height[0] = texture_height(msg->frame);
+	msg->height[1] = 0;
+
+	redraw(msg);
+}
+
+void
+message_handle(struct message *msg, const union event *ev)
+{
+	assert(msg);
+	assert(ev);
+
+	if (ev->type != EVENT_KEYDOWN || msg->state == MESSAGE_NONE)
+		return;
+
+	switch (ev->key.key) {
+	case KEY_UP:
+		if (msg->index > 0)
+			msg->index--;
+		break;
+	case KEY_DOWN:
+		if (msg->index < 5 && msg->text[msg->index + 1])
+			msg->index++;
+		break;
+	case KEY_ENTER:
+		msg->state = MESSAGE_HIDING;
+		msg->elapsed = 0;
+		break;
+	default:
+		break;
+	}
+
+	redraw(msg);
 }
 
 bool
@@ -76,10 +138,10 @@
 
 	switch (msg->state) {
 	case MESSAGE_OPENING:
-		msg->alpha += 255 * ticks / MESSAGE_SPEED;
+		msg->height[1] += texture_height(msg->frame) * ticks / MESSAGE_SPEED;
 
-		if (msg->alpha > 255)
-			msg->alpha = 255;
+		if (msg->height[1] > msg->height[0])
+			msg->height[1] = msg->height[0];
 		if (msg->elapsed >= MESSAGE_SPEED) {
 			msg->state = MESSAGE_SHOWING;
 			msg->elapsed = 0;
@@ -95,6 +157,8 @@
 
 		break;
 	case MESSAGE_HIDING:
+		msg->height[1] -= texture_height(msg->frame) * ticks / MESSAGE_SPEED;
+
 		if (msg->elapsed >= MESSAGE_SPEED) {
 			msg->state = MESSAGE_NONE;
 			msg->elapsed = 0;
@@ -118,23 +182,31 @@
 	const unsigned int h = texture_height(msg->frame);
 	const unsigned int x = (window_width() / 2) - (w / 2);
 	const unsigned int y = 80;
-	const unsigned int avgh = average_height(msg);
+	const unsigned int avgh = average(msg);
 	const unsigned int gapy = (h - (avgh * 6)) / 7;
 
-	/* TODO: handle state */
-	redraw(msg);
-	texture_draw(msg->frame, x, y);
+	switch (msg->state) {
+	case MESSAGE_OPENING:
+	case MESSAGE_HIDING:
+		texture_draw_ex(msg->frame, 0, 0, w, msg->height[1], x, y, w, msg->height[1], 0);
+		break;
+	case MESSAGE_SHOWING:
+		texture_draw(msg->frame, x, y);
 
-	for (int i = 0; i < 6; ++i) {
-		/* TODO: avatar handling */
-		const int real_x = x + 20;
-		const int real_y = y + ((i + 1) * gapy) + (i * avgh);
+		for (int i = 0; i < 6; ++i) {
+			/* TODO: avatar handling */
+			const int real_x = x + 20;
+			const int real_y = y + ((i + 1) * gapy) + (i * avgh);
 
-		if (!msg->ttext[i])
-			continue;
+			if (!msg->textures[i])
+				continue;
 
-		texture_draw(msg->stext[i], real_x + 2, real_y + 2);
-		texture_draw(msg->ttext[i], real_x, real_y);
+			texture_draw(msg->textures[i + 6], real_x + 2, real_y + 2);
+			texture_draw(msg->textures[i], real_x, real_y);
+		}
+		break;
+	default:
+		break;
 	}
 }
 
@@ -152,14 +224,5 @@
 {
 	assert(msg);
 
-	for (int i = 0; i < 6; ++i) {
-		if (msg->ttext[i]) {
-			texture_close(msg->ttext[i]);
-			msg->ttext[i] = NULL;
-		}
-		if (msg->stext[i]) {
-			texture_close(msg->stext[i]);
-			msg->stext[i] = NULL;
-		}
-	}
+	clear(msg);
 }