Merge pull request #327 from kichikuou/partsfunc

PartsEngine: Implement some PartsFuncs
This commit is contained in:
Nunuhara Cabbage
2026-04-20 19:10:24 -07:00
committed by GitHub
6 changed files with 223 additions and 0 deletions
+6
View File
@@ -37,6 +37,7 @@ bool PE_SetPartsCG_by_string_index(int parts_no, struct string *cg_no,
int sprite_deform, int state);
void PE_GetPartsCGName(int parts_no, struct string **cg_name, int state);
bool PE_SetPartsCGSurfaceArea(int parts_no, int x, int y, int w, int h, int state);
void PE_GetPartsCGSurfaceArea(int parts_no, int *x, int *y, int *w, int *h, int state);
int PE_GetPartsCGNumber(int parts_no, int state);
bool PE_SetLoopCG_by_index(int parts_no, int cg_no, int nr_frames, int frame_time, int state);
bool PE_SetLoopCG(int parts_no, struct string *cg_name, int start_no, int nr_frames,
@@ -126,8 +127,13 @@ bool PE_IsExist(int parts_no);
void PE_set_active_controller(int controller_no);
int PE_get_active_controller(void);
int PE_get_system_controller(void);
void PE_parts_set_want_save(int parts_no, bool want_save);
bool PE_init_parts_movie(int parts_no, int width, int height, int bg_r, int bg_g, int bg_b, int state);
int PE_get_movie_sprite(int parts_no, int state);
float PE_parts_get_absolute_x(int parts_no);
float PE_parts_get_absolute_y(int parts_no);
int PE_parts_get_absolute_z(int parts_no);
void PE_parts_set_lock_input_state(int parts_no, bool lock);
// construction.c
bool PE_AddCreateToPartsConstructionProcess(int parts_no, int w, int h, int state);
+165
View File
@@ -18,6 +18,7 @@
#include "system4/ain.h"
#include "vm/heap.h"
#include "vm/page.h"
#include "parts.h"
#include "hll.h"
@@ -97,6 +98,130 @@ static void PartsEngine_AddComponentMotionPos(int parts_no, float begin_x, float
begin_t, end_t, curve_name);
}
static void PartsEngine_add_construction_process(union vm_value *ints,
union vm_value *floats, union vm_value *strings)
{
int parts_no = ints[0].i;
int state = ints[1].i;
int command = ints[2].i;
int interp_type = ints[3].i;
int sx = ints[4].i;
int sy = ints[5].i;
int sw = ints[6].i;
int sh = ints[7].i;
int dx = ints[8].i;
int dy = ints[9].i;
int dw = ints[12].i;
int dh = ints[13].i;
int r = ints[14].i;
int g = ints[15].i;
int b = ints[16].i;
int a = ints[17].i;
// int r2 = ints[18].i;
// int g2 = ints[19].i;
// int b2 = ints[20].i;
int char_space = ints[21].i;
int line_space = ints[22].i;
int font_type = ints[23].i;
int font_size = ints[24].i;
int font_r = ints[25].i;
int font_g = ints[26].i;
int font_b = ints[27].i;
int edge_r = ints[28].i;
int edge_g = ints[29].i;
int edge_b = ints[30].i;
int full_size = ints[31].i;
float bold_weight = floats[0].f;
float edge_weight = floats[1].f;
struct string *text = heap_get_string(strings[0].i);
struct string *cg_name = heap_get_string(strings[1].i);
switch (command) {
case 0: // CASConstructionProcess::SetCreate
PE_AddCreateToPartsConstructionProcess(parts_no, dw, dh, state);
break;
case 1: // CASConstructionProcess::SetCreatePixelOnly
PE_AddCreatePixelOnlyToPartsConstructionProcess(parts_no, dw, dh, state);
break;
case 2: // CASConstructionProcess::SetCreateCG
PE_AddCreateCGToProcess(parts_no, cg_name, state);
break;
case 3: // CASConstructionProcess::SetFill
PE_AddFillToPartsConstructionProcess(parts_no,
dx, dy, dw, dh, r, g, b, state);
break;
case 4: // CASConstructionProcess::SetFillAlphaColor
PE_AddFillAlphaColorToPartsConstructionProcess(parts_no,
dx, dy, dw, dh, r, g, b, a, state);
break;
case 5: // CASConstructionProcess::SetFillAMap
PE_AddFillAMapToPartsConstructionProcess(parts_no,
dx, dy, dw, dh, a, state);
break;
case 6: // CASConstructionProcess::SetFillWithAlpha
PE_AddFillWithAlphaToPartsConstructionProcess(parts_no,
dx, dy, dw, dh, r, g, b, a, state);
break;
case 7: // CASConstructionProcess::SetDrawText
PE_AddDrawTextToPartsConstructionProcess(parts_no,
dx, dy, text, font_type, font_size,
font_r, font_g, font_b, bold_weight,
edge_r, edge_g, edge_b, edge_weight,
char_space, line_space, state);
break;
case 8: // CASConstructionProcess::SetCopyText
PE_AddCopyTextToPartsConstructionProcess(parts_no,
dx, dy, text, font_type, font_size,
font_r, font_g, font_b, bold_weight,
edge_r, edge_g, edge_b, edge_weight,
char_space, line_space, state);
break;
case 9: // CASConstructionProcess::SetFillGradationHorizon
WARNING("AddConstructProcess: FillGradationHorizon unimplemented");
break;
case 10: // CASConstructionProcess::SetDrawRect
PE_AddDrawRectToPartsConstructionProcess(parts_no,
dx, dy, dw, dh, r, g, b, state);
break;
case 11: // CASConstructionProcess::SetCutCGBlend (equal scale)
PE_AddDrawCutCGToPartsConstructionProcess(parts_no, cg_name,
dx, dy, dw, dh, sx, sy, dw, dh,
interp_type, state);
break;
case 12: // CASConstructionProcess::SetCutCGCopy (equal scale)
PE_AddCopyCutCGToPartsConstructionProcess(parts_no, cg_name,
dx, dy, dw, dh, sx, sy, dw, dh,
interp_type, state);
break;
case 13: // CASConstructionProcess::SetCutCGScaleBlend
PE_AddDrawCutCGToPartsConstructionProcess(parts_no, cg_name,
dx, dy, dw, dh, sx, sy, sw, sh,
interp_type, state);
break;
case 14: // CASConstructionProcess::SetCutCGScaleCopy
PE_AddCopyCutCGToPartsConstructionProcess(parts_no, cg_name,
dx, dy, dw, dh, sx, sy, sw, sh,
interp_type, state);
break;
case 15: // CASConstructionProcess::SetGrayFilter
PE_AddGrayFilterToPartsConstructionProcess(parts_no,
dx, dy, dw, dh, full_size, state);
break;
case 16: // CASConstructionProcess::SetAddFilter
WARNING("AddConstructProcess: AddFilter unimplemented");
break;
case 17: // CASConstructionProcess::SetMulFilter
WARNING("AddConstructProcess: MulFilter unimplemented");
break;
case 18: // CASConstructionProcess::SetDrawLine
WARNING("AddConstructProcess: DrawLine unimplemented");
break;
default:
WARNING("AddConstructProcess: unknown command %d", command);
break;
}
}
// Generic dispatch function for PartsEngine operations.
// func_id selects the operation; arguments and return values are passed
// through three typed arrays (int/bool, float, string).
@@ -110,9 +235,17 @@ static int PartsEngine_PartsFunc(int func_id, struct page **array_int,
{
int nr_ints = (array_int && *array_int) ? (*array_int)->nr_vars : 0;
union vm_value *ints = nr_ints ? (*array_int)->values : NULL;
int nr_floats = (array_float && *array_float) ? (*array_float)->nr_vars : 0;
union vm_value *floats = nr_floats ? (*array_float)->values : NULL;
int nr_strings = (array_string && *array_string) ? (*array_string)->nr_vars : 0;
union vm_value *strings = nr_strings ? (*array_string)->values : NULL;
#define REQUIRE_INTS(n) \
if (nr_ints != (n)) VM_ERROR("Invalid arguments for PartsFunc %d: expected %d ints, got %d", func_id, (n), nr_ints)
#define REQUIRE_FLOATS(n) \
if (nr_floats < (n)) VM_ERROR("Invalid arguments for PartsFunc %d: expected %d floats, got %d", func_id, (n), nr_floats)
#define REQUIRE_STRINGS(n) \
if (nr_strings < (n)) VM_ERROR("Invalid arguments for PartsFunc %d: expected %d strings, got %d", func_id, (n), nr_strings)
switch (func_id) {
case 0: // void SetActiveLayer(int layer)
@@ -127,6 +260,38 @@ static int PartsEngine_PartsFunc(int func_id, struct page **array_int,
REQUIRE_INTS(1);
ints[0].i = PE_get_system_controller();
return 1;
case 4: // void SetWantSave(int parts_no, bool want_save)
REQUIRE_INTS(2);
PE_parts_set_want_save(ints[0].i, !!ints[1].i);
return 1;
case 40: // float PARTS_GetAbsoluteX(int number)
REQUIRE_INTS(1);
REQUIRE_FLOATS(1);
floats[0].f = PE_parts_get_absolute_x(ints[0].i);
return 1;
case 41: // float PARTS_GetAbsoluteY(int number)
REQUIRE_INTS(1);
REQUIRE_FLOATS(1);
floats[0].f = PE_parts_get_absolute_y(ints[0].i);
return 1;
case 42: // int PARTS_GetAbsoluteZ(int number)
REQUIRE_INTS(2);
ints[1].i = PE_parts_get_absolute_z(ints[0].i);
return 1;
case 45: // void PARTS_SetLockInputState(int number, bool lock)
REQUIRE_INTS(2);
PE_parts_set_lock_input_state(ints[0].i, !!ints[1].i);
return 1;
case 103: // void GetPartsCGSurfaceArea(int parts_no, int *x, int *y, int *w, int *h, int state)
REQUIRE_INTS(6);
PE_GetPartsCGSurfaceArea(ints[0].i, &ints[1].i, &ints[2].i, &ints[3].i, &ints[4].i, ints[5].i);
return 1;
case 159: // AddConstructProcess(ArrayInt[32], ArrayFloat[2], ArrayString[2])
REQUIRE_INTS(32);
REQUIRE_FLOATS(2);
REQUIRE_STRINGS(2);
PartsEngine_add_construction_process(ints, floats, strings);
return 1;
case 162: // bool InitPartsMovie(int parts_no, int width, int height, int bg_r, int bg_g, int bg_b, int state)
REQUIRE_INTS(8);
ints[7].i = PE_init_parts_movie(ints[0].i, ints[1].i, ints[2].i, ints[3].i, ints[4].i, ints[5].i, ints[6].i);
+3
View File
@@ -388,6 +388,9 @@ cJSON *parts_to_json(struct parts *parts, bool recursive, bool verbose)
cJSON_AddNumberToObject(obj, "delegate_index", parts->delegate_index);
cJSON_AddNumberToObject(obj, "sprite_deform", parts->sprite_deform);
cJSON_AddBoolToObject(obj, "clickable", parts->clickable);
cJSON_AddBoolToObject(obj, "pass_cursor", parts->pass_cursor);
cJSON_AddBoolToObject(obj, "lock_input_state", parts->lock_input_state);
cJSON_AddBoolToObject(obj, "want_save", parts->want_save);
if (parts->on_cursor_sound >= 0)
cJSON_AddNumberToObject(obj, "on_cursor_sound", parts->on_cursor_sound);
if (parts->on_click_sound >= 0)
+43
View File
@@ -62,6 +62,7 @@ static void parts_init(struct parts *parts)
parts->local = PARTS_PARAMS_INITIALIZER;
parts->global = PARTS_PARAMS_INITIALIZER;
parts->delegate_index = -1;
parts->want_save = true;
parts->on_cursor_sound = -1;
parts->on_click_sound = -1;
parts->origin_mode = 1;
@@ -884,6 +885,8 @@ bool parts_numeral_set_number(struct parts *parts, struct parts_numeral *num, in
void parts_set_state(struct parts *parts, enum parts_state_type state)
{
if (parts->lock_input_state)
return;
while (state > PARTS_STATE_DEFAULT && parts->states[state].type == PARTS_UNINITIALIZED)
state--;
if (parts->state != state) {
@@ -1227,6 +1230,18 @@ bool PE_SetPartsCGSurfaceArea(int parts_no, int x, int y, int w, int h, int stat
return true;
}
void PE_GetPartsCGSurfaceArea(int parts_no, int *x, int *y, int *w, int *h, int state)
{
if (!parts_state_valid(--state))
return;
struct parts_cg *cg = parts_get_cg(parts_get(parts_no), state);
*x = cg->common.surface_area.x;
*y = cg->common.surface_area.y;
*w = cg->common.surface_area.w;
*h = cg->common.surface_area.h;
}
int PE_GetPartsCGNumber(int parts_no, int state)
{
if (!parts_state_valid(--state)) {
@@ -2089,6 +2104,34 @@ int PE_get_system_controller(void)
return PARTS_CONTROLLER_SYSTEM_OVERLAY;
}
void PE_parts_set_want_save(int parts_no, bool want_save)
{
parts_get(parts_no)->want_save = want_save;
}
float PE_parts_get_absolute_x(int parts_no)
{
struct parts *parts = parts_try_get(parts_no);
return parts ? (float)parts->global.pos.x : 0.0f;
}
float PE_parts_get_absolute_y(int parts_no)
{
struct parts *parts = parts_try_get(parts_no);
return parts ? (float)parts->global.pos.y : 0.0f;
}
int PE_parts_get_absolute_z(int parts_no)
{
struct parts *parts = parts_try_get(parts_no);
return parts ? parts->global.z : 0;
}
void PE_parts_set_lock_input_state(int parts_no, bool lock)
{
parts_get(parts_no)->lock_input_state = lock;
}
bool PE_init_parts_movie(int parts_no, int width, int height, int bg_r, int bg_g, int bg_b, int state)
{
if (!parts_state_valid(--state))
+2
View File
@@ -366,6 +366,8 @@ struct parts {
int sprite_deform;
bool clickable;
bool pass_cursor;
bool lock_input_state;
bool want_save;
int on_cursor_sound;
int on_click_sound;
int origin_mode;
+4
View File
@@ -537,6 +537,7 @@ static void save_parts(struct iarray_writer *w, struct parts *parts)
if (parts_multi_controller) {
iarray_write(w, parts->controller_no);
iarray_write(w, parts->pass_cursor);
iarray_write(w, parts->lock_input_state);
}
unsigned motion_count_pos = iarray_writer_pos(w);
@@ -582,6 +583,7 @@ static void load_parts(struct iarray_reader *r, int version)
if (parts_multi_controller) {
parts->controller_no = iarray_read(r);
parts->pass_cursor = iarray_read(r);
parts->lock_input_state = iarray_read(r);
}
int motion_count = iarray_read(r);
for (int i = 0; i < motion_count; i++) {
@@ -648,6 +650,8 @@ static bool parts_engine_save(struct page **buffer, bool save_hidden)
PARTS_LIST_FOREACH(parts) {
if (!save_hidden && !parts->global.show)
continue;
if (!parts->want_save)
continue;
save_parts(&w, parts);
count++;
}