PartsEngine: Implement message dispatch system

This adds a message queue that captures GUI events and exposes them
through HLL accessor functions.
This commit is contained in:
kichikuou
2026-04-15 08:56:52 +09:00
parent dc105aeb16
commit a0d78a024c
6 changed files with 190 additions and 13 deletions
+13
View File
@@ -176,6 +176,19 @@ void PE_EndInput(void);
int PE_GetClickPartsNumber(void);
bool PE_IsCursorIn(int parts_no, int mouse_x, int mouse_y, int state);
// message.c
void PE_ReleaseMessage(void);
void PE_PopMessage(void);
int PE_GetMessageType(void);
int PE_GetMessagePartsNumber(void);
int PE_GetMessageDelegateIndex(void);
int PE_GetMessageVariableCount(void);
int PE_GetMessageVariableType(int index);
int PE_GetMessageVariableInt(int index);
float PE_GetMessageVariableFloat(int index);
bool PE_GetMessageVariableBool(int index);
void PE_GetMessageVariableString(int index, struct string **out);
// motion.c
void PE_AddMotionPos(int parts_no, int begin_x, int begin_y, int end_x, int end_y, int begin_t, int end_t);
void PE_AddMotionPos_curve(int parts_no, int begin_x, int begin_y, int end_x, int end_y,
+11 -13
View File
@@ -143,8 +143,6 @@ static int PartsEngine_PartsFunc(int func_id, struct page **array_int,
}
HLL_WARN_UNIMPLEMENTED(, void, PartsEngine, StopSoundWithoutSystemSound);
HLL_WARN_UNIMPLEMENTED(, void, PartsEngine, ReleaseMessage, void);
HLL_WARN_UNIMPLEMENTED(0, int, PartsEngine, GetMessageType, void);
HLL_WARN_UNIMPLEMENTED(, void, PartsEngine, Parts_SetPassCursor, int Number, bool Pass);
static void PartsEngine_PreLink(void);
@@ -332,18 +330,18 @@ HLL_LIBRARY(PartsEngine,
HLL_TODO_EXPORT(ReleaseActivity, PartsEngine_ReleaseActivity),
HLL_TODO_EXPORT(CrateActivityBinary, PartsEngine_CrateActivityBinary),
HLL_TODO_EXPORT(ReadActivityBinary, PartsEngine_ReadActivityBinary),
HLL_EXPORT(ReleaseMessage, PartsEngine_ReleaseMessage),
HLL_TODO_EXPORT(PopMessage, PartsEngine_PopMessage),
HLL_TODO_EXPORT(GetMessagePartsNumber, PartsEngine_GetMessagePartsNumber),
HLL_TODO_EXPORT(GetMessageDelegateIndex, PartsEngine_GetMessageDelegateIndex),
HLL_EXPORT(ReleaseMessage, PE_ReleaseMessage),
HLL_EXPORT(PopMessage, PE_PopMessage),
HLL_EXPORT(GetMessagePartsNumber, PE_GetMessagePartsNumber),
HLL_EXPORT(GetMessageDelegateIndex, PE_GetMessageDelegateIndex),
HLL_EXPORT(GetDelegateIndex, PE_GetDelegateIndex),
HLL_EXPORT(GetMessageType, PartsEngine_GetMessageType),
HLL_TODO_EXPORT(GetMessageVariableCount, PartsEngine_GetMessageVariableCount),
HLL_TODO_EXPORT(GetMessageVariableType, PartsEngine_GetMessageVariableType),
HLL_TODO_EXPORT(GetMessageVariableInt, PartsEngine_GetMessageVariableInt),
HLL_TODO_EXPORT(GetMessageVariableFloat, PartsEngine_GetMessageVariableFloat),
HLL_TODO_EXPORT(GetMessageVariableBool, PartsEngine_GetMessageVariableBool),
HLL_TODO_EXPORT(GetMessageVariableString, PartsEngine_GetMessageVariableString),
HLL_EXPORT(GetMessageType, PE_GetMessageType),
HLL_EXPORT(GetMessageVariableCount, PE_GetMessageVariableCount),
HLL_EXPORT(GetMessageVariableType, PE_GetMessageVariableType),
HLL_EXPORT(GetMessageVariableInt, PE_GetMessageVariableInt),
HLL_EXPORT(GetMessageVariableFloat, PE_GetMessageVariableFloat),
HLL_EXPORT(GetMessageVariableBool, PE_GetMessageVariableBool),
HLL_EXPORT(GetMessageVariableString, PE_GetMessageVariableString),
HLL_EXPORT(SetDelegateIndex, PE_SetDelegateIndex),
HLL_TODO_EXPORT(SetFocus, PartsEngine_SetFocus),
HLL_TODO_EXPORT(IsFocus, PartsEngine_IsFocus),
+1
View File
@@ -61,6 +61,7 @@ xsystem4 = [version_h,
'parts/flash.c',
'parts/flat.c',
'parts/input.c',
'parts/message.c',
'parts/motion.c',
'parts/parts.c',
'parts/render.c',
+146
View File
@@ -0,0 +1,146 @@
/* Copyright (C) 2026 kichikuou <KichikuouChrome@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "system4.h"
#include "system4/string.h"
#include "vm.h"
#include "parts.h"
#include "parts_internal.h"
#define PARTS_MSG_MAX_VARS 4
struct parts_message {
STAILQ_ENTRY(parts_message) entry;
int parts_no;
int delegate_index;
int type;
int variables[PARTS_MSG_MAX_VARS];
int nr_variables;
};
static STAILQ_HEAD(, parts_message) msg_queue =
STAILQ_HEAD_INITIALIZER(msg_queue);
void parts_msg_push(int parts_no, int delegate_index, int type, const char *fmt, ...)
{
// Message system is introduced in Rance 9
if (!parts_multi_controller)
return;
struct parts_message *msg = xmalloc(sizeof(*msg));
msg->parts_no = parts_no;
msg->delegate_index = delegate_index;
msg->type = type;
msg->nr_variables = 0;
va_list ap;
va_start(ap, fmt);
for (const char *p = fmt; *p; p++) {
if (msg->nr_variables >= PARTS_MSG_MAX_VARS) {
VM_ERROR("parts_msg_push: too many variables");
}
switch (*p) {
case 'i':
msg->variables[msg->nr_variables++] = va_arg(ap, int);
break;
default:
VM_ERROR("parts_msg_push: unsupported format '%c'", *p);
}
}
va_end(ap);
STAILQ_INSERT_TAIL(&msg_queue, msg, entry);
}
void PE_ReleaseMessage(void)
{
while (!STAILQ_EMPTY(&msg_queue)) {
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
STAILQ_REMOVE_HEAD(&msg_queue, entry);
free(msg);
}
}
void PE_PopMessage(void)
{
if (STAILQ_EMPTY(&msg_queue))
return;
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
STAILQ_REMOVE_HEAD(&msg_queue, entry);
free(msg);
}
int PE_GetMessageType(void)
{
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
return msg ? msg->type : 0;
}
int PE_GetMessagePartsNumber(void)
{
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
return msg ? msg->parts_no : 0;
}
int PE_GetMessageDelegateIndex(void)
{
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
return msg ? msg->delegate_index : -1;
}
int PE_GetMessageVariableCount(void)
{
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
return msg ? msg->nr_variables : 0;
}
int PE_GetMessageVariableType(possibly_unused int index)
{
// In the current implementation, all variables are integers.
return 1;
}
int PE_GetMessageVariableInt(int index)
{
struct parts_message *msg = STAILQ_FIRST(&msg_queue);
if (!msg)
return 0;
if (index < 0 || index >= msg->nr_variables)
return 0;
return msg->variables[index];
}
float PE_GetMessageVariableFloat(possibly_unused int index)
{
return 0.0f;
}
bool PE_GetMessageVariableBool(possibly_unused int index)
{
return false;
}
void PE_GetMessageVariableString(possibly_unused int index, struct string **out)
{
if (*out)
free_string(*out);
*out = string_ref(&EMPTY_STRING);
}
+1
View File
@@ -1020,6 +1020,7 @@ bool PE_Init(void)
void PE_Reset(void)
{
PE_ReleaseAllParts();
PE_ReleaseMessage();
ctrl_stack_fini();
sact_ModuleFini();
}
+18
View File
@@ -465,6 +465,24 @@ void parts_add_motion(struct parts *parts, struct parts_motion *motion);
extern Point parts_prev_pos;
extern bool parts_began_click;
// message.c
enum parts_message_type {
PARTS_MSG_MOUSE_ENTER = 1,
PARTS_MSG_MOUSE_MOVE = 2,
PARTS_MSG_MOUSE_LEAVE = 3,
PARTS_MSG_MOUSE_WHEEL = 4,
PARTS_MSG_MOUSE_CLICK = 5,
PARTS_MSG_MOUSE_ON = 6,
PARTS_MSG_DRAG_BEGIN = 7,
PARTS_MSG_DRAGGING = 8,
PARTS_MSG_DRAG_END = 9,
PARTS_MSG_KEY_TRIGGER = 14,
PARTS_MSG_KEY_DOWN = 15,
PARTS_MSG_KEY_UP = 17,
};
void parts_msg_push(int parts_no, int delegate_index, int type, const char *fmt, ...);
// construction.c
void parts_cp_op_free(struct parts_cp_op *op);
void parts_add_cp_op(struct parts_construction_process *cproc, struct parts_cp_op *op);