mirror of
https://github.com/nunuhara/xsystem4.git
synced 2026-09-22 23:18:01 +03:00
parts: refactor parent-child handling
Parent-child relationships are established by the UpdateComponent function. Parts_SetParentPartsNumber does not establish the relationship (and it does not create the parent object if it does not exist yet). Render params are now computed recursively on children when they are set on the parent (instead of recomputing them every time a child parts is rendered).
This commit is contained in:
@@ -25,6 +25,7 @@ struct string;
|
||||
// parts.c
|
||||
bool PE_Init(void);
|
||||
void PE_Update(int passed_time, bool message_window_show);
|
||||
void PE_UpdateComponent(int passed_time);
|
||||
void PE_UpdateParts(int passed_time, bool is_skip, bool message_window_show);
|
||||
void PE_SetDelegateIndex(int parts_no, int delegate_index);
|
||||
int PE_GetDelegateIndex(int parts_no);
|
||||
|
||||
+1
-2
@@ -39,7 +39,6 @@ static void GUIEngine_ModuleFini(void)
|
||||
//static void GUIEngine_PushController(void);
|
||||
//static void GUIEngine_PopController(ref array<int> EraseNumberList);
|
||||
//static void GUIEngine_UpdateComponent(possibly_unused int passed_time)
|
||||
HLL_QUIET_UNIMPLEMENTED(, void, GUIEngine, UpdateComponent, int passed_time);
|
||||
//static void GUIEngine_BeginInput(void);
|
||||
//static void GUIEngine_EndInput(void);
|
||||
//static void GUIEngine_UpdateInputState(int PassedTime);
|
||||
@@ -510,7 +509,7 @@ HLL_LIBRARY(GUIEngine,
|
||||
HLL_EXPORT(IsExist, PE_IsExist),
|
||||
HLL_TODO_EXPORT(PushController, GUIEngine_PushController),
|
||||
HLL_TODO_EXPORT(PopController, GUIEngine_PopController),
|
||||
HLL_EXPORT(UpdateComponent, GUIEngine_UpdateComponent),
|
||||
HLL_EXPORT(UpdateComponent, PE_UpdateComponent),
|
||||
HLL_EXPORT(BeginInput, PE_BeginInput),
|
||||
HLL_EXPORT(EndInput, PE_EndInput),
|
||||
HLL_EXPORT(UpdateInputState, PE_UpdateInputState),
|
||||
|
||||
+56
-22
@@ -164,9 +164,6 @@ static void parts_print_state(struct parts_state *state, int indent)
|
||||
|
||||
struct parts_common *com = &state->common;
|
||||
|
||||
indent_printf(indent, "texture = ");
|
||||
gfx_print_texture(&state->common.texture, indent);
|
||||
printf(",\n");
|
||||
indent_printf(indent, "dims = {w=%d,h=%d},\n", state->common.w, state->common.h);
|
||||
indent_printf(indent, "origin_offset = "); gfx_print_point(&com->origin_offset); printf(",\n");
|
||||
indent_printf(indent, "hitbox = "); gfx_print_rectangle(&com->hitbox); printf(",\n");
|
||||
@@ -263,6 +260,40 @@ static void parts_print_motion(struct parts_motion *motion, int indent)
|
||||
indent_printf(indent, "}");
|
||||
}
|
||||
|
||||
static void parts_print_params(struct parts_params *global, struct parts_params *local, int indent)
|
||||
{
|
||||
printf("{\n");
|
||||
indent++;
|
||||
|
||||
indent_printf(indent, "z = %d (%d),\n", global->z, local->z);
|
||||
indent_printf(indent, "pos = ");
|
||||
gfx_print_point(&global->pos);
|
||||
printf(" (");
|
||||
gfx_print_point(&local->pos);
|
||||
printf("),\n");
|
||||
indent_printf(indent, "show = %s (%s),\n", global->show ? "true" : "false",
|
||||
local->show ? "true" : "false");
|
||||
indent_printf(indent, "alpha = %u (%u),\n", (unsigned)global->alpha, (unsigned)local->alpha);
|
||||
indent_printf(indent, "scale = {x=%f,y=%f} ({x=%f,y=%f}),\n", global->scale.x, global->scale.y,
|
||||
local->scale.x, local->scale.y);
|
||||
indent_printf(indent, "rotation = {x=%f,y=%f,z=%f} ({x=%f,y=%f,z=%f}),\n",
|
||||
global->rotation.x, global->rotation.y, global->rotation.z,
|
||||
local->rotation.x, local->rotation.y, local->rotation.z);
|
||||
indent_printf(indent, "add_color = ");
|
||||
gfx_print_color(&global->add_color);
|
||||
printf(" (");
|
||||
gfx_print_color(&local->add_color);
|
||||
printf("),\n");
|
||||
indent_printf(indent, "multiply_color = ");
|
||||
gfx_print_color(&global->multiply_color);
|
||||
printf(" (");
|
||||
gfx_print_color(&local->multiply_color);
|
||||
printf("),\n");
|
||||
|
||||
indent--;
|
||||
indent_printf(indent, "}");
|
||||
}
|
||||
|
||||
static void _parts_print(struct parts *parts, int indent)
|
||||
{
|
||||
static const char *state_names[PARTS_NR_STATES] = {
|
||||
@@ -280,30 +311,33 @@ static void _parts_print(struct parts *parts, int indent)
|
||||
// print states
|
||||
indent_printf(indent, "state = %s,\n", state);
|
||||
for (int i = 0; i < PARTS_NR_STATES; i++) {
|
||||
if (parts->states[i].type == PARTS_UNINITIALIZED && i != parts->state)
|
||||
continue;
|
||||
indent_printf(indent, "state[%s] = ", state_names[i]);
|
||||
parts_print_state(&parts->states[i], indent);
|
||||
printf(",\n");
|
||||
}
|
||||
|
||||
// print params
|
||||
indent_printf(indent, "local = ");
|
||||
parts_print_params(&parts->global, &parts->local, indent);
|
||||
printf(",\n");
|
||||
|
||||
// print misc. data
|
||||
indent_printf(indent, "delegate_index = %d,\n", parts->delegate_index);
|
||||
if (parts->delegate_index >= 0)
|
||||
indent_printf(indent, "delegate_index = %d,\n", parts->delegate_index);
|
||||
indent_printf(indent, "sprite_deform = %d,\n", parts->sprite_deform);
|
||||
indent_printf(indent, "clickable = %s,\n", parts->clickable ? "true" : "false");
|
||||
indent_printf(indent, "on_cursor_sound = %d,\n", parts->on_cursor_sound);
|
||||
indent_printf(indent, "on_click_sound = %d,\n", parts->on_click_sound);
|
||||
if (parts->on_cursor_sound >= 0)
|
||||
indent_printf(indent, "on_cursor_sound = %d,\n", parts->on_cursor_sound);
|
||||
if (parts->on_click_sound >= 0)
|
||||
indent_printf(indent, "on_click_sound = %d,\n", parts->on_click_sound);
|
||||
indent_printf(indent, "origin_mode = %d,\n", parts->origin_mode);
|
||||
indent_printf(indent, "parent = %d,\n", parts->parent);
|
||||
indent_printf(indent, "linked_to = %d,\n", parts->linked_to);
|
||||
indent_printf(indent, "linked_from = %d,\n", parts->linked_from);
|
||||
indent_printf(indent, "alpha = %u,\n", (unsigned)parts->alpha);
|
||||
indent_printf(indent, "pos = "); gfx_print_point(&parts->pos); printf(",\n");
|
||||
indent_printf(indent, "z = %d,\n", parts->z);
|
||||
indent_printf(indent, "show = %s,\n", parts->show ? "true" : "false");
|
||||
indent_printf(indent, "scale = {x=%f,y=%f},\n", parts->scale.x, parts->scale.y);
|
||||
indent_printf(indent, "rotation = {x=%f,y=%f,z=%f},\n",
|
||||
parts->rotation.x, parts->rotation.y, parts->rotation.z);
|
||||
indent_printf(indent, "add_color = "); gfx_print_color(&parts->add_color); printf(",\n");
|
||||
indent_printf(indent, "multiply_color = "); gfx_print_color(&parts->multiply_color); printf(",\n");
|
||||
indent_printf(indent, "parent = %d,\n", parts->parent ? parts->parent->no : -1);
|
||||
if (parts->linked_to >= 0)
|
||||
indent_printf(indent, "linked_to = %d,\n", parts->linked_to);
|
||||
if (parts->linked_from >= 0)
|
||||
indent_printf(indent, "linked_from = %d,\n", parts->linked_from);
|
||||
indent_printf(indent, "draw_filter = %d,\n", parts->draw_filter);
|
||||
|
||||
// print motion data
|
||||
@@ -348,7 +382,7 @@ void parts_engine_print(void)
|
||||
{
|
||||
struct parts *parts;
|
||||
PARTS_LIST_FOREACH(parts) {
|
||||
if (parts->parent < 0)
|
||||
if (!parts->parent)
|
||||
parts_print(parts);
|
||||
}
|
||||
}
|
||||
@@ -376,7 +410,7 @@ static void parts_cmd_parts(unsigned nr_args, char **args)
|
||||
|
||||
static void parts_list_print(struct parts *parts, int indent)
|
||||
{
|
||||
indent_printf(indent, parts->show ? "+ " : "- ");
|
||||
indent_printf(indent, parts->local.show ? "+ " : "- ");
|
||||
printf("parts %d ", parts->no);
|
||||
struct parts_state *state = &parts->states[parts->state];
|
||||
switch (state->type) {
|
||||
@@ -443,7 +477,7 @@ static void parts_list_print(struct parts *parts, int indent)
|
||||
}
|
||||
}
|
||||
|
||||
printf(" @ z=%d (%d)\n", parts->global_z, parts->z);
|
||||
printf(" @ z=%d (%d)\n", parts->global.z, parts->local.z);
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
@@ -455,7 +489,7 @@ static void parts_cmd_parts_list(unsigned nr_args, char **args)
|
||||
{
|
||||
struct parts *parts;
|
||||
PARTS_LIST_FOREACH(parts) {
|
||||
if (parts->parent < 0)
|
||||
if (!parts->parent)
|
||||
parts_list_print(parts, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -180,11 +180,9 @@ bool PE_IsCursorIn(int parts_no, int mouse_x, int mouse_y, int state)
|
||||
|
||||
// TODO: this could be cached
|
||||
Rectangle hitbox = parts->states[state].common.hitbox;
|
||||
struct parts *parent = parts;
|
||||
while (parent->parent >= 0) {
|
||||
parent = parts_get(parent->parent);
|
||||
hitbox.x += parent->pos.x;
|
||||
hitbox.y += parent->pos.y;
|
||||
for (struct parts *parent = parts->parent; parent; parent = parent->parent) {
|
||||
hitbox.x += parent->local.pos.x;
|
||||
hitbox.y += parent->local.pos.y;
|
||||
}
|
||||
|
||||
Point mouse_pos = { mouse_x, mouse_y };
|
||||
|
||||
+313
-126
@@ -27,27 +27,31 @@
|
||||
#include "parts_internal.h"
|
||||
|
||||
struct parts_list parts_list = TAILQ_HEAD_INITIALIZER(parts_list);
|
||||
static struct parts_list dirty_list = TAILQ_HEAD_INITIALIZER(dirty_list);
|
||||
static struct hash_table *parts_table = NULL;
|
||||
|
||||
#define PARTS_PARAMS_INITIALIZER (struct parts_params) { \
|
||||
.z = 1, \
|
||||
.pos = { 0, 0 }, \
|
||||
.show = true, \
|
||||
.alpha = 255, \
|
||||
.scale = { 1.0f, 1.0f }, \
|
||||
.rotation = { 0.0f, 0.0f, 0.0f }, \
|
||||
.add_color = { 0, 0, 0, 0 }, \
|
||||
.multiply_color = { 255, 255, 255, 255 } \
|
||||
}
|
||||
|
||||
static void parts_init(struct parts *parts)
|
||||
{
|
||||
parts->local = PARTS_PARAMS_INITIALIZER;
|
||||
parts->global = PARTS_PARAMS_INITIALIZER;
|
||||
parts->delegate_index = -1;
|
||||
parts->on_cursor_sound = -1;
|
||||
parts->on_click_sound = -1;
|
||||
parts->origin_mode = 1;
|
||||
parts->z = 1;
|
||||
parts->global_z = 1;
|
||||
parts->show = true;
|
||||
parts->alpha = 255;
|
||||
parts->parent = -1;
|
||||
parts->pending_parent = -1;
|
||||
parts->linked_to = -1;
|
||||
parts->linked_from = -1;
|
||||
parts->scale.x = 1.0;
|
||||
parts->scale.y = 1.0;
|
||||
parts->rotation.x = 0.0;
|
||||
parts->rotation.y = 0.0;
|
||||
parts->rotation.z = 0.0;
|
||||
parts->multiply_color = (SDL_Color) { 255, 255, 255, 255 };
|
||||
TAILQ_INIT(&parts->children);
|
||||
TAILQ_INIT(&parts->motion);
|
||||
}
|
||||
@@ -59,11 +63,19 @@ static struct parts *parts_alloc(void)
|
||||
return parts;
|
||||
}
|
||||
|
||||
static void parts_component_dirty(struct parts *parts)
|
||||
{
|
||||
if (parts->dirty)
|
||||
return;
|
||||
parts->dirty = true;
|
||||
TAILQ_INSERT_TAIL(&dirty_list, parts, dirty_list_entry);
|
||||
}
|
||||
|
||||
static void parts_list_insert(struct parts *parts)
|
||||
{
|
||||
struct parts *p;
|
||||
PARTS_LIST_FOREACH(p) {
|
||||
if (p->global_z > parts->global_z) {
|
||||
if (p->global.z > parts->global.z) {
|
||||
TAILQ_INSERT_BEFORE(p, parts, parts_list_entry);
|
||||
parts_engine_dirty();
|
||||
return;
|
||||
@@ -85,33 +97,6 @@ static void parts_list_resort(struct parts *parts)
|
||||
parts_list_insert(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_z(struct parts *parts, int parent_z)
|
||||
{
|
||||
parts->global_z = parent_z + parts->z;
|
||||
parts_list_resort(parts);
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_z(child, parts->global_z);
|
||||
}
|
||||
}
|
||||
|
||||
static void parts_set_parent(struct parts *child, struct parts *parent)
|
||||
{
|
||||
if (child->parent >= 0) {
|
||||
struct parts *old_parent = parts_get(child->parent);
|
||||
TAILQ_REMOVE(&old_parent->children, child, child_list_entry);
|
||||
}
|
||||
if (parent) {
|
||||
TAILQ_INSERT_TAIL(&parent->children, child, child_list_entry);
|
||||
child->parent = parent->no;
|
||||
parts_update_global_z(child, parent->global_z);
|
||||
} else {
|
||||
child->parent = -1;
|
||||
parts_update_global_z(child, 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct parts *parts_try_get(int parts_no)
|
||||
{
|
||||
struct ht_slot *slot = ht_put_int(parts_table, parts_no, NULL);
|
||||
@@ -309,13 +294,13 @@ static void parts_common_recalculate_hitbox(struct parts *parts, struct parts_co
|
||||
SDL_IntersectRect(&r, &common->surface_area, &common->hitbox);
|
||||
common->origin_offset.x -= common->surface_area.x;
|
||||
common->origin_offset.y -= common->surface_area.y;
|
||||
common->hitbox.x += parts->pos.x + common->origin_offset.x;
|
||||
common->hitbox.y += parts->pos.y + common->origin_offset.y;
|
||||
common->hitbox.x += parts->local.pos.x + common->origin_offset.x;
|
||||
common->hitbox.y += parts->local.pos.y + common->origin_offset.y;
|
||||
} else {
|
||||
common->origin_offset = calculate_offset(parts->origin_mode, common->w, common->h);
|
||||
common->hitbox = (Rectangle) {
|
||||
.x = parts->pos.x + common->origin_offset.x,
|
||||
.y = parts->pos.y + common->origin_offset.y,
|
||||
.x = parts->local.pos.x + common->origin_offset.x,
|
||||
.y = parts->local.pos.y + common->origin_offset.y,
|
||||
.w = common->w,
|
||||
.h = common->h,
|
||||
};
|
||||
@@ -329,11 +314,189 @@ static void parts_recalculate_hitbox(struct parts *parts)
|
||||
}
|
||||
}
|
||||
|
||||
static void parts_update_global_pos(struct parts *parts, Point parent_pos)
|
||||
{
|
||||
parts->global.pos = (Point) {
|
||||
parent_pos.x + parts->local.pos.x,
|
||||
parent_pos.y + parts->local.pos.y
|
||||
};
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_pos(child, parts->global.pos);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_pos(struct parts *parts, Point pos)
|
||||
{
|
||||
parts->pos.x = pos.x;
|
||||
parts->pos.y = pos.y;
|
||||
parts->local.pos.x = pos.x;
|
||||
parts->local.pos.y = pos.y;
|
||||
parts_recalculate_hitbox(parts);
|
||||
parts_update_global_pos(parts, parts->parent ? parts->parent->global.pos : (Point){0,0});
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_z(struct parts *parts, int parent_z)
|
||||
{
|
||||
parts->global.z = parent_z + parts->local.z;
|
||||
parts_list_resort(parts);
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_z(child, parts->global.z);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_z(struct parts *parts, int z)
|
||||
{
|
||||
if (parts->local.z == z)
|
||||
return;
|
||||
|
||||
parts->local.z = z;
|
||||
parts_update_global_z(parts, parts->parent ? parts->parent->global.z : 0);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_show(struct parts *parts, bool parent_show)
|
||||
{
|
||||
parts->global.show = parent_show && parts->local.show;
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_show(child, parts->global.show);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_show(struct parts *parts, bool show)
|
||||
{
|
||||
if (parts->local.show == show)
|
||||
return;
|
||||
|
||||
parts->local.show = show;
|
||||
parts_update_global_show(parts, parts->parent ? parts->parent->global.show : true);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_alpha(struct parts *parts, int parent_alpha)
|
||||
{
|
||||
parts->global.alpha = parent_alpha * (parts->local.alpha / 255.0f);
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_alpha(child, parts->global.alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_alpha(struct parts *parts, int alpha)
|
||||
{
|
||||
parts->local.alpha = max(0, min(255, alpha));
|
||||
parts_update_global_alpha(parts, parts->parent ? parts->parent->global.alpha : 255);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_add_color(struct parts *parts, SDL_Color parent_color)
|
||||
{
|
||||
parts->global.add_color = (SDL_Color) {
|
||||
parent_color.r * (parts->local.add_color.r / 255.0f),
|
||||
parent_color.g * (parts->local.add_color.g / 255.0f),
|
||||
parent_color.b * (parts->local.add_color.b / 255.0f),
|
||||
0
|
||||
};
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_add_color(child, parts->global.add_color);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_add_color(struct parts *parts, SDL_Color color)
|
||||
{
|
||||
parts->local.add_color = color;
|
||||
parts_update_global_add_color(parts, parts->parent ? parts->parent->global.add_color
|
||||
: (SDL_Color){0,0,0,0});
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_multiply_color(struct parts *parts, SDL_Color parent_color)
|
||||
{
|
||||
parts->global.multiply_color = (SDL_Color) {
|
||||
parent_color.r * (parts->local.multiply_color.r / 255.0f),
|
||||
parent_color.g * (parts->local.multiply_color.g / 255.0f),
|
||||
parent_color.b * (parts->local.multiply_color.b / 255.0f),
|
||||
255
|
||||
};
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_multiply_color(child, parts->global.multiply_color);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_multiply_color(struct parts *parts, SDL_Color color)
|
||||
{
|
||||
parts->local.multiply_color = color;
|
||||
parts_update_global_multiply_color(parts, parts->parent ? parts->parent->global.multiply_color
|
||||
: (SDL_Color){255,255,255,255});
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
void parts_set_origin_mode(struct parts *parts, int origin_mode)
|
||||
{
|
||||
parts->origin_mode = origin_mode;
|
||||
parts_recalculate_hitbox(parts);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_scale_x(struct parts *parts, float parent_scale_x)
|
||||
{
|
||||
parts->global.scale.x = parent_scale_x * parts->local.scale.x;
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_scale_x(child, parts->global.scale.x);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_scale_x(struct parts *parts, float mag)
|
||||
{
|
||||
parts->local.scale.x = mag;
|
||||
parts_recalculate_hitbox(parts);
|
||||
parts_update_global_scale_x(parts, parts->parent ? parts->parent->global.scale.x : 1.0f);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_scale_y(struct parts *parts, float parent_scale_y)
|
||||
{
|
||||
parts->global.scale.y = parent_scale_y * parts->local.scale.y;
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_scale_y(child, parts->global.scale.y);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_scale_y(struct parts *parts, float mag)
|
||||
{
|
||||
parts->local.scale.y = mag;
|
||||
parts_recalculate_hitbox(parts);
|
||||
parts_update_global_scale_y(parts, parts->parent ? parts->parent->global.scale.y : 1.0f);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static void parts_update_global_rotate_z(struct parts *parts, float parent_rot_z)
|
||||
{
|
||||
parts->global.rotation.z = parent_rot_z + parts->local.rotation.z;
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_rotate_z(child, parts->global.rotation.z);
|
||||
}
|
||||
}
|
||||
|
||||
void parts_set_rotation_z(struct parts *parts, float rot)
|
||||
{
|
||||
parts->local.rotation.z = rot;
|
||||
parts_update_global_rotate_z(parts, parts->parent ? parts->parent->global.rotation.z : 0.0f);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
@@ -344,47 +507,6 @@ void parts_set_dims(struct parts *parts, struct parts_common *common, int w, int
|
||||
parts_common_recalculate_hitbox(parts, common);
|
||||
}
|
||||
|
||||
void parts_set_origin_mode(struct parts *parts, int origin_mode)
|
||||
{
|
||||
parts->origin_mode = origin_mode;
|
||||
parts_recalculate_hitbox(parts);
|
||||
}
|
||||
|
||||
void parts_set_scale_x(struct parts *parts, float mag)
|
||||
{
|
||||
parts->scale.x = mag;
|
||||
parts_recalculate_hitbox(parts);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
void parts_set_scale_y(struct parts *parts, float mag)
|
||||
{
|
||||
parts->scale.y = mag;
|
||||
parts_recalculate_hitbox(parts);
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
void parts_set_rotation_z(struct parts *parts, float rot)
|
||||
{
|
||||
parts->rotation.z = rot;
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
void parts_set_alpha(struct parts *parts, int alpha)
|
||||
{
|
||||
parts->alpha = max(0, min(255, alpha));
|
||||
for (int i = 0; i < PARTS_NR_STATES; i++) {
|
||||
struct parts_state *s = &parts->states[i];
|
||||
s->common.texture.alpha_mod = parts->alpha;
|
||||
if (s->type == PARTS_ANIMATION) {
|
||||
for (unsigned i = 0; i < s->anim.nr_frames; i++) {
|
||||
s->anim.frames[i].alpha_mod = parts->alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
parts_dirty(parts);
|
||||
}
|
||||
|
||||
static bool parts_set_cg(struct parts *parts, struct cg *cg, int cg_no, struct string *name, int state)
|
||||
{
|
||||
if (!cg)
|
||||
@@ -598,9 +720,13 @@ void parts_release(int parts_no)
|
||||
// break parent/child relationships
|
||||
while (!TAILQ_EMPTY(&parts->children)) {
|
||||
struct parts *child = TAILQ_FIRST(&parts->children);
|
||||
parts_set_parent(child, NULL);
|
||||
TAILQ_REMOVE(&parts->children, child, child_list_entry);
|
||||
child->parent = NULL;
|
||||
}
|
||||
if (parts->parent) {
|
||||
TAILQ_REMOVE(&parts->parent->children, parts, child_list_entry);
|
||||
parts->parent = NULL;
|
||||
}
|
||||
parts_set_parent(parts, NULL);
|
||||
|
||||
parts_list_remove(parts);
|
||||
free(parts);
|
||||
@@ -627,8 +753,88 @@ bool PE_Init(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parts_has_dirty_parent(struct parts *parts)
|
||||
{
|
||||
for (struct parts *parent = parts->parent; parent; parent = parent->parent) {
|
||||
if (parent->dirty)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void parts_combine_params(struct parts_params *parent, struct parts_params *child,
|
||||
struct parts_params *out)
|
||||
{
|
||||
out->z = parent->z + child->z;
|
||||
out->pos = (Point) { parent->pos.x + child->pos.x, parent->pos.y + child->pos.y };
|
||||
out->show = parent->show && child->show;
|
||||
out->alpha = parent->alpha * (child->alpha / 255.0f);
|
||||
out->scale.x = parent->scale.x * child->scale.x;
|
||||
out->scale.y = parent->scale.y * child->scale.y;
|
||||
out->rotation.x = parent->rotation.x + child->rotation.x;
|
||||
out->rotation.y = parent->rotation.y + child->rotation.y;
|
||||
out->rotation.z = parent->rotation.z + child->rotation.z;
|
||||
out->add_color.r = parent->add_color.r * (child->add_color.r / 255.0f);
|
||||
out->add_color.g = parent->add_color.g * (child->add_color.g / 255.0f);
|
||||
out->add_color.b = parent->add_color.b * (child->add_color.b / 255.0f);
|
||||
out->multiply_color.r = parent->multiply_color.r * (child->multiply_color.r / 255.0f);
|
||||
out->multiply_color.g = parent->multiply_color.g * (child->multiply_color.g / 255.0f);
|
||||
out->multiply_color.b = parent->multiply_color.b * (child->multiply_color.b / 255.0f);
|
||||
}
|
||||
|
||||
static void parts_update_component(struct parts *parts)
|
||||
{
|
||||
if (parts->parent) {
|
||||
int old_z = parts->global.z;
|
||||
parts_combine_params(&parts->parent->global, &parts->local, &parts->global);
|
||||
if (parts->global.z != old_z)
|
||||
parts_list_resort(parts);
|
||||
}
|
||||
|
||||
if (parts->dirty) {
|
||||
TAILQ_REMOVE(&dirty_list, parts, dirty_list_entry);
|
||||
parts->dirty = false;
|
||||
}
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_component(child);
|
||||
}
|
||||
}
|
||||
|
||||
void PE_UpdateComponent(possibly_unused int passed_time)
|
||||
{
|
||||
while (!TAILQ_EMPTY(&dirty_list)) {
|
||||
// pop parts object from dirty list
|
||||
struct parts *parts = TAILQ_FIRST(&dirty_list);
|
||||
TAILQ_REMOVE(&dirty_list, parts, dirty_list_entry);
|
||||
parts->dirty = false;
|
||||
|
||||
// update parent
|
||||
struct parts *parent;
|
||||
if (parts->pending_parent >= 0 && (parent = parts_try_get(parts->pending_parent))) {
|
||||
if (parts->parent) {
|
||||
TAILQ_REMOVE(&parts->parent->children, parts, child_list_entry);
|
||||
}
|
||||
parts->parent = parent;
|
||||
TAILQ_INSERT_TAIL(&parent->children, parts, child_list_entry);
|
||||
}
|
||||
// TODO: should the child be orphaned if it already has a parent and an invalid
|
||||
// parent no is given?
|
||||
parts->pending_parent = -1;
|
||||
|
||||
// don't do anything here if parent is dirty
|
||||
if (parts_has_dirty_parent(parts))
|
||||
continue;
|
||||
|
||||
// update child params
|
||||
parts_update_component(parts);
|
||||
}
|
||||
}
|
||||
|
||||
void PE_Update(int passed_time, possibly_unused bool message_window_show)
|
||||
{
|
||||
PE_UpdateComponent(passed_time);
|
||||
audio_update();
|
||||
parts_update_animation(passed_time);
|
||||
PE_UpdateInputState(passed_time);
|
||||
@@ -1050,36 +1256,14 @@ void PE_SetPos(int parts_no, int x, int y)
|
||||
parts_set_pos(parts_get(parts_no), (Point){ x, y });
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: If a ChipmunkSpriteEngine sprite is at Z=0, it's drawn behind;
|
||||
* otherwise it's drawn in front, regardless of the parts Z-value.
|
||||
* This is implemented by giving GoatGUIEngine sprites a Z-value of
|
||||
* 0 and a secondary Z-value of 1 + the value given here.
|
||||
*/
|
||||
void PE_SetZ(int parts_no, int z)
|
||||
{
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
if (parts->z == z)
|
||||
return;
|
||||
|
||||
int diff = z - parts->z;
|
||||
parts->z = z;
|
||||
parts->global_z += diff;
|
||||
parts_list_resort(parts);
|
||||
|
||||
struct parts *child;
|
||||
PARTS_FOREACH_CHILD(child, parts) {
|
||||
parts_update_global_z(child, parts->global_z);
|
||||
}
|
||||
parts_set_z(parts_get(parts_no), z);
|
||||
}
|
||||
|
||||
void PE_SetShow(int parts_no, bool show)
|
||||
{
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
if (parts->show != show) {
|
||||
parts->show = show;
|
||||
parts_dirty(parts);
|
||||
}
|
||||
parts_set_show(parts_get(parts_no), show);
|
||||
}
|
||||
|
||||
void PE_SetAlpha(int parts_no, int alpha)
|
||||
@@ -1096,32 +1280,34 @@ void PE_SetPartsDrawFilter(int parts_no, int draw_filter)
|
||||
|
||||
void PE_SetAddColor(int parts_no, int r, int g, int b)
|
||||
{
|
||||
parts_get(parts_no)->add_color = (SDL_Color) {
|
||||
SDL_Color add_color = {
|
||||
min(255, max(0, r)),
|
||||
min(255, max(0, g)),
|
||||
min(255, max(0, b)),
|
||||
255
|
||||
};
|
||||
parts_set_add_color(parts_get(parts_no), add_color);
|
||||
}
|
||||
|
||||
void PE_SetMultiplyColor(int parts_no, int r, int g, int b)
|
||||
{
|
||||
parts_get(parts_no)->multiply_color = (SDL_Color) {
|
||||
SDL_Color multiply_color = {
|
||||
min(255, max(0, r)),
|
||||
min(255, max(0, g)),
|
||||
min(255, max(0, b)),
|
||||
255
|
||||
};
|
||||
parts_set_multiply_color(parts_get(parts_no), multiply_color);
|
||||
}
|
||||
|
||||
int PE_GetPartsX(int parts_no)
|
||||
{
|
||||
return parts_get(parts_no)->pos.x;
|
||||
return parts_get(parts_no)->local.pos.x;
|
||||
}
|
||||
|
||||
int PE_GetPartsY(int parts_no)
|
||||
{
|
||||
return parts_get(parts_no)->pos.y;
|
||||
return parts_get(parts_no)->local.pos.y;
|
||||
}
|
||||
|
||||
int PE_GetPartsWidth(int parts_no, int state)
|
||||
@@ -1154,17 +1340,17 @@ int PE_GetPartsUpperLeftPosY(int parts_no, int state)
|
||||
|
||||
int PE_GetPartsZ(int parts_no)
|
||||
{
|
||||
return parts_get(parts_no)->z;
|
||||
return parts_get(parts_no)->local.z;
|
||||
}
|
||||
|
||||
bool PE_GetPartsShow(int parts_no)
|
||||
{
|
||||
return parts_get(parts_no)->show;
|
||||
return parts_get(parts_no)->local.show;
|
||||
}
|
||||
|
||||
int PE_GetPartsAlpha(int parts_no)
|
||||
{
|
||||
return parts_get(parts_no)->alpha;
|
||||
return parts_get(parts_no)->local.alpha;
|
||||
}
|
||||
|
||||
void PE_GetAddColor(int PartsNumber, int *nR, int *nG, int *nB);
|
||||
@@ -1185,10 +1371,8 @@ int PE_GetPartsOriginPosMode(int parts_no)
|
||||
void PE_SetParentPartsNumber(int parts_no, int parent_parts_no)
|
||||
{
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
if (parts->parent == parent_parts_no)
|
||||
return;
|
||||
|
||||
parts_set_parent(parts, parts_get(parent_parts_no));
|
||||
parts->pending_parent = parent_parts_no;
|
||||
parts_component_dirty(parts);
|
||||
}
|
||||
|
||||
bool PE_SetPartsGroupNumber(possibly_unused int PartsNumber, possibly_unused int GroupNumber)
|
||||
@@ -1206,12 +1390,14 @@ bool PE_GetPartsMessageWindowShowLink(int PartsNumber);
|
||||
|
||||
void PE_SetPartsMagX(int parts_no, float scale_x)
|
||||
{
|
||||
parts_set_scale_x(parts_get(parts_no), scale_x);
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
parts_set_scale_x(parts, scale_x);
|
||||
}
|
||||
|
||||
void PE_SetPartsMagY(int parts_no, float scale_y)
|
||||
{
|
||||
parts_set_scale_y(parts_get(parts_no), scale_y);
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
parts_set_scale_y(parts, scale_y);
|
||||
}
|
||||
|
||||
void PE_SetPartsRotateX(int parts_no, float rot_x)
|
||||
@@ -1226,7 +1412,8 @@ void PE_SetPartsRotateY(int parts_no, float rot_y)
|
||||
|
||||
void PE_SetPartsRotateZ(int parts_no, float rot_z)
|
||||
{
|
||||
parts_set_rotation_z(parts_get(parts_no), rot_z);
|
||||
struct parts *parts = parts_get(parts_no);
|
||||
parts_set_rotation_z(parts, rot_z);
|
||||
}
|
||||
|
||||
void PE_SetPartsAlphaClipperPartsNumber(int PartsNumber, int AlphaClipperPartsNumber);
|
||||
|
||||
+17
-10
@@ -210,13 +210,29 @@ struct parts_state {
|
||||
|
||||
TAILQ_HEAD(parts_list, parts);
|
||||
|
||||
struct parts_params {
|
||||
int z;
|
||||
Point pos;
|
||||
bool show;
|
||||
uint8_t alpha;
|
||||
struct { float x, y; } scale;
|
||||
struct { float x, y, z; } rotation;
|
||||
SDL_Color add_color;
|
||||
SDL_Color multiply_color;
|
||||
};
|
||||
|
||||
struct parts {
|
||||
//struct sprite sp;
|
||||
enum parts_state_type state;
|
||||
struct parts_state states[PARTS_NR_STATES];
|
||||
TAILQ_ENTRY(parts) parts_list_entry;
|
||||
TAILQ_ENTRY(parts) child_list_entry;
|
||||
TAILQ_ENTRY(parts) dirty_list_entry;
|
||||
struct parts_list children;
|
||||
struct parts_params local;
|
||||
struct parts_params global;
|
||||
struct parts *parent;
|
||||
int dirty;
|
||||
int no;
|
||||
int delegate_index;
|
||||
int sprite_deform;
|
||||
@@ -224,18 +240,9 @@ struct parts {
|
||||
int on_cursor_sound;
|
||||
int on_click_sound;
|
||||
int origin_mode;
|
||||
int parent;
|
||||
int pending_parent;
|
||||
int linked_to;
|
||||
int linked_from;
|
||||
uint8_t alpha;
|
||||
int z;
|
||||
int global_z;
|
||||
bool show;
|
||||
Point pos;
|
||||
struct { float x, y; } scale;
|
||||
struct { float x, y, z; } rotation;
|
||||
SDL_Color add_color;
|
||||
SDL_Color multiply_color;
|
||||
int draw_filter;
|
||||
TAILQ_HEAD(, parts_motion) motion;
|
||||
};
|
||||
|
||||
+15
-52
@@ -29,14 +29,6 @@
|
||||
// Goat sprites are integrated into the scene via a single (virtual) sprite
|
||||
static struct sprite goat_sprite;
|
||||
|
||||
struct parts_render_params {
|
||||
Point offset;
|
||||
uint8_t alpha;
|
||||
struct { float x, y; } scale;
|
||||
SDL_Color add_color;
|
||||
SDL_Color multiply_color;
|
||||
};
|
||||
|
||||
static struct {
|
||||
struct shader shader;
|
||||
GLint alpha_mod;
|
||||
@@ -46,20 +38,18 @@ static struct {
|
||||
GLint multiply_color;
|
||||
} parts_shader;
|
||||
|
||||
static void parts_render_text(struct parts *parts, struct parts_common *common,
|
||||
struct parts_render_params *params)
|
||||
static void parts_render_text(struct parts *parts, struct parts_common *common)
|
||||
{
|
||||
Rectangle rect = {
|
||||
.x = params->offset.x + common->origin_offset.x,
|
||||
.y = params->offset.y + common->origin_offset.y,
|
||||
.x = parts->global.pos.x + common->origin_offset.x,
|
||||
.y = parts->global.pos.y + common->origin_offset.y,
|
||||
.w = common->w,
|
||||
.h = common->h
|
||||
};
|
||||
gfx_render_texture(&parts->states[parts->state].common.texture, &rect);
|
||||
}
|
||||
|
||||
static void parts_render_cg(struct parts *parts, struct parts_common *common,
|
||||
struct parts_render_params *params)
|
||||
static void parts_render_cg(struct parts *parts, struct parts_common *common)
|
||||
{
|
||||
switch (parts->draw_filter) {
|
||||
case 1:
|
||||
@@ -70,12 +60,12 @@ static void parts_render_cg(struct parts *parts, struct parts_common *common,
|
||||
}
|
||||
|
||||
mat4 mw_transform = GLM_MAT4_IDENTITY_INIT;
|
||||
glm_translate(mw_transform, (vec3) { params->offset.x, params->offset.y, 0 });
|
||||
glm_translate(mw_transform, (vec3) { parts->global.pos.x, parts->global.pos.y, 0 });
|
||||
// FIXME: need perspective for 3D rotate
|
||||
//glm_rotate_x(mw_transform, parts->rotation.x, mw_transform);
|
||||
//glm_rotate_y(mw_transform, parts->rotation.y, mw_transform);
|
||||
glm_rotate_z(mw_transform, parts->rotation.z, mw_transform);
|
||||
glm_scale(mw_transform, (vec3){ params->scale.x, params->scale.y, 1.0 });
|
||||
glm_rotate_z(mw_transform, parts->local.rotation.z, mw_transform);
|
||||
glm_scale(mw_transform, (vec3){ parts->global.scale.x, parts->global.scale.y, 1.0 });
|
||||
glm_translate(mw_transform, (vec3){ common->origin_offset.x, common->origin_offset.y, 0 });
|
||||
glm_scale(mw_transform, (vec3){ common->w, common->h, 1.0 });
|
||||
mat4 wv_transform = WV_TRANSFORM(config.view_width, config.view_height);
|
||||
@@ -94,13 +84,13 @@ static void parts_render_cg(struct parts *parts, struct parts_common *common,
|
||||
}
|
||||
|
||||
gfx_prepare_job(&job);
|
||||
glUniform1f(parts_shader.alpha_mod, params->alpha / 255.0);
|
||||
glUniform1f(parts_shader.alpha_mod, parts->global.alpha / 255.0);
|
||||
glUniform2f(parts_shader.bot_left, r.x, r.y);
|
||||
glUniform2f(parts_shader.top_right, r.x + r.w, r.y + r.h);
|
||||
glUniform3f(parts_shader.add_color, params->add_color.r / 255.0f,
|
||||
params->add_color.g / 255.0f, params->add_color.b / 255.0f);
|
||||
glUniform3f(parts_shader.multiply_color, params->multiply_color.r / 255.0f,
|
||||
params->multiply_color.g / 255.0f, params->multiply_color.b / 255.0f);
|
||||
glUniform3f(parts_shader.add_color, parts->global.add_color.r / 255.0f,
|
||||
parts->global.add_color.g / 255.0f, parts->global.add_color.b / 255.0f);
|
||||
glUniform3f(parts_shader.multiply_color, parts->global.multiply_color.r / 255.0f,
|
||||
parts->global.multiply_color.g / 255.0f, parts->global.multiply_color.b / 255.0f);
|
||||
gfx_run_job(&job);
|
||||
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
@@ -108,7 +98,7 @@ static void parts_render_cg(struct parts *parts, struct parts_common *common,
|
||||
|
||||
void parts_render(struct parts *parts)
|
||||
{
|
||||
if (!parts->show)
|
||||
if (!parts->global.show)
|
||||
return;
|
||||
if (parts->linked_to >= 0) {
|
||||
struct parts *link_parts = parts_get(parts->linked_to);
|
||||
@@ -117,33 +107,6 @@ void parts_render(struct parts *parts)
|
||||
return;
|
||||
}
|
||||
|
||||
struct parts_render_params params = {
|
||||
.offset = parts->pos,
|
||||
.alpha = parts->alpha,
|
||||
.scale = { parts->scale.x, parts->scale.y },
|
||||
.add_color = parts->add_color,
|
||||
.multiply_color = parts->multiply_color,
|
||||
};
|
||||
|
||||
// adjust pos/alpha per parent parts
|
||||
struct parts *parent = parts;
|
||||
while (parent->parent >= 0) {
|
||||
parent = parts_get(parent->parent);
|
||||
if (!parent->show)
|
||||
return;
|
||||
params.alpha *= parent->alpha / 255.0f;
|
||||
params.offset.x += parent->pos.x;
|
||||
params.offset.y += parent->pos.y;
|
||||
params.scale.x *= parent->scale.x;
|
||||
params.scale.y *= parent->scale.y;
|
||||
params.add_color.r *= parent->add_color.r / 255.0f;
|
||||
params.add_color.g *= parent->add_color.g / 255.0f;
|
||||
params.add_color.b *= parent->add_color.b / 255.0f;
|
||||
params.multiply_color.r *= parent->multiply_color.r / 255.0f;
|
||||
params.multiply_color.g *= parent->multiply_color.g / 255.0f;
|
||||
params.multiply_color.b *= parent->multiply_color.b / 255.0f;
|
||||
}
|
||||
|
||||
// render
|
||||
struct parts_state *state = &parts->states[parts->state];
|
||||
if (state->common.texture.handle) {
|
||||
@@ -156,10 +119,10 @@ void parts_render(struct parts *parts)
|
||||
case PARTS_HGAUGE:
|
||||
case PARTS_VGAUGE:
|
||||
case PARTS_CONSTRUCTION_PROCESS:
|
||||
parts_render_cg(parts, &state->common, ¶ms);
|
||||
parts_render_cg(parts, &state->common);
|
||||
break;
|
||||
case PARTS_TEXT:
|
||||
parts_render_text(parts, &state->common, ¶ms);
|
||||
parts_render_text(parts, &state->common);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user