diff --git a/include/parts.h b/include/parts.h index 36b4900..8d6426c 100644 --- a/include/parts.h +++ b/include/parts.h @@ -30,9 +30,12 @@ void PE_SetDelegateIndex(int parts_no, int delegate_index); int PE_GetDelegateIndex(int parts_no); bool PE_SetPartsCG(int parts_no, struct string *cg_name, int sprite_deform, int state); bool PE_SetPartsCG_by_index(int parts_no, int 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); 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, + int frame_time, int state); bool PE_SetLoopCGSurfaceArea(int parts_no, int x, int y, int w, int h, int state); bool PE_SetHGaugeCG(int parts_no, struct string *cg_name, int state); bool PE_SetHGaugeCG_by_index(int parts_no, int cg_no, int state); @@ -62,6 +65,8 @@ void PE_SetZ(int parts_no, int z); void PE_SetShow(int parts_no, bool show); void PE_SetAlpha(int parts_no, int alpha); void PE_SetPartsDrawFilter(int PartsNumber, int DrawFilter);; +void PE_SetAddColor(int parts_no, int r, int g, int b); +void PE_SetMultiplyColor(int parts_no, int r, int g, int b); int PE_GetPartsX(int parts_no); int PE_GetPartsY(int parts_no); int PE_GetPartsZ(int parts_no); @@ -85,6 +90,7 @@ void PE_SetPartsPixelDecide(int PartsNumber, bool PixelDecide); bool PE_SetThumbnailReductionSize(int ReductionSize); bool PE_SetThumbnailMode(bool Mode); bool PE_Save(struct page **buffer); +bool PE_SaveWithoutHideParts(struct page **buffer); bool PE_Load(struct page **buffer); // GUIEngine int PE_GetFreeNumber(void); @@ -123,7 +129,11 @@ bool PE_IsCursorIn(int parts_no, int mouse_x, int mouse_y, int state); // 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, + int begin_t, int end_t, struct string *curve_name); void PE_AddMotionAlpha(int parts_no, int begin_a, int end_a, int begin_t, int end_t); +void PE_AddMotionAlpha_curve(int parts_no, int begin_a, int end_a, int begin_t, int end_t, + struct string *curve_name); void PE_AddMotionCG_by_index(int parts_no, int begin_cg_no, int nr_cg, int begin_t, int end_t); void PE_AddMotionHGaugeRate(int parts_no, int begin_numerator, int begin_denominator, int end_numerator, int end_denominator, int begin_t, int end_t); @@ -140,6 +150,7 @@ void PE_AddMotionSound(int sound_no, int begin_t); void PE_BeginMotion(void); void PE_EndMotion(void); void PE_SetMotionTime(int t); +void PE_UpdateMotionTime(int time, bool skip); bool PE_IsMotion(void); int PE_GetMotionEndTime(void); diff --git a/src/hll/GUIEngine.c b/src/hll/GUIEngine.c index 044ce81..9d61b10 100644 --- a/src/hll/GUIEngine.c +++ b/src/hll/GUIEngine.c @@ -423,7 +423,6 @@ HLL_QUIET_UNIMPLEMENTED(0, int, GUIEngine, GetMessageType); //static void GUIEngine_Parts_SetSpeedupRateByMessageSkip(int PartsNumber, int Rate); //static void GUIEngine_Parts_SetResetTimerByChangeInputStatus(int PartsNumber, bool Reset, int State); //static void GUIEngine_Parts_SetAddColor(int PartsNumber, int nR, int nG, int nB); -HLL_QUIET_UNIMPLEMENTED(, void, GUIEngine, Parts_SetAddColor, int parts_number, int r, int g, int b); //static void GUIEngine_Parts_SetMultiplyColor(int PartsNumber, int nR, int nG, int nB); //static void GUIEngine_Parts_SetDrag(int PartsNumber, bool Drag); //static void GUIEngine_Parts_SetPartsOriginPosMode(int PartsNumber, int OriginPosMode); @@ -807,9 +806,9 @@ HLL_LIBRARY(GUIEngine, HLL_TODO_EXPORT(SetMultiTextBoxCGName, GUIEngine_SetMultiTextBoxCGName), HLL_TODO_EXPORT(GetMultiTextBoxCGName, GUIEngine_GetMultiTextBoxCGName), HLL_EXPORT(Parts_SetPartsCG, PE_SetPartsCG), - HLL_TODO_EXPORT(Parts_GetPartsCGName, GUIEngine_Parts_GetPartsCGName), + HLL_EXPORT(Parts_GetPartsCGName, PE_GetPartsCGName), HLL_EXPORT(Parts_SetPartsCGSurfaceArea, PE_SetPartsCGSurfaceArea), - HLL_TODO_EXPORT(Parts_SetLoopCG, GUIEngine_Parts_SetLoopCG), + HLL_EXPORT(Parts_SetLoopCG, PE_SetLoopCG), HLL_EXPORT(Parts_SetLoopCGSurfaceArea, PE_SetLoopCGSurfaceArea), HLL_EXPORT(Parts_SetText, PE_SetText), HLL_EXPORT(Parts_AddPartsText, PE_AddPartsText), @@ -891,23 +890,23 @@ HLL_LIBRARY(GUIEngine, HLL_TODO_EXPORT(Parts_SetClickable, GUIEngine_Parts_SetClickable), HLL_TODO_EXPORT(Parts_SetSpeedupRateByMessageSkip, GUIEngine_Parts_SetSpeedupRateByMessageSkip), HLL_TODO_EXPORT(Parts_SetResetTimerByChangeInputStatus, GUIEngine_Parts_SetResetTimerByChangeInputStatus), - HLL_EXPORT(Parts_SetAddColor, GUIEngine_Parts_SetAddColor), - HLL_TODO_EXPORT(Parts_SetMultiplyColor, GUIEngine_Parts_SetMultiplyColor), + HLL_EXPORT(Parts_SetAddColor, PE_SetAddColor), + HLL_EXPORT(Parts_SetMultiplyColor, PE_SetMultiplyColor), HLL_TODO_EXPORT(Parts_SetDrag, GUIEngine_Parts_SetDrag), HLL_EXPORT(Parts_SetPartsOriginPosMode, PE_SetPartsOriginPosMode), HLL_EXPORT(Parts_SetParentPartsNumber, PE_SetParentPartsNumber), HLL_TODO_EXPORT(Parts_SetInputState, GUIEngine_Parts_SetInputState), HLL_TODO_EXPORT(Parts_SetOnCursorShowLinkPartsNumber, GUIEngine_Parts_SetOnCursorShowLinkPartsNumber), - HLL_TODO_EXPORT(Parts_SetPartsMessageWindowShowLink, GUIEngine_Parts_SetPartsMessageWindowShowLink), + HLL_EXPORT(Parts_SetPartsMessageWindowShowLink, PE_SetPartsMessageWindowShowLink), HLL_TODO_EXPORT(Parts_SetSoundNumber, GUIEngine_Parts_SetSoundNumber), HLL_TODO_EXPORT(Parts_SetClickMissSoundNumber, GUIEngine_Parts_SetClickMissSoundNumber), - HLL_TODO_EXPORT(Parts_SetPartsMagX, GUIEngine_Parts_SetPartsMagX), - HLL_TODO_EXPORT(Parts_SetPartsMagY, GUIEngine_Parts_SetPartsMagY), + HLL_EXPORT(Parts_SetPartsMagX, PE_SetPartsMagX), + HLL_EXPORT(Parts_SetPartsMagY, PE_SetPartsMagY), HLL_TODO_EXPORT(Parts_SetPartsRotateX, GUIEngine_Parts_SetPartsRotateX), HLL_TODO_EXPORT(Parts_SetPartsRotateY, GUIEngine_Parts_SetPartsRotateY), HLL_TODO_EXPORT(Parts_SetPartsRotateZ, GUIEngine_Parts_SetPartsRotateZ), HLL_TODO_EXPORT(Parts_SetPartsAlphaClipperPartsNumber, GUIEngine_Parts_SetPartsAlphaClipperPartsNumber), - HLL_TODO_EXPORT(Parts_SetPartsPixelDecide, GUIEngine_Parts_SetPartsPixelDecide), + HLL_EXPORT(Parts_SetPartsPixelDecide, PE_SetPartsPixelDecide), HLL_EXPORT(Parts_GetPartsX, PE_GetPartsX), HLL_EXPORT(Parts_GetPartsY, PE_GetPartsY), HLL_EXPORT(Parts_GetPartsZ, PE_GetPartsZ), @@ -939,8 +938,8 @@ HLL_LIBRARY(GUIEngine, HLL_TODO_EXPORT(Parts_GetPartsUpperLeftPosY, GUIEngine_Parts_GetPartsUpperLeftPosY), HLL_EXPORT(Parts_GetPartsWidth, PE_GetPartsWidth), HLL_EXPORT(Parts_GetPartsHeight, PE_GetPartsHeight), - HLL_TODO_EXPORT(Parts_AddMotionPos, GUIEngine_Parts_AddMotionPos), - HLL_TODO_EXPORT(Parts_AddMotionAlpha, GUIEngine_Parts_AddMotionAlpha), + HLL_EXPORT(Parts_AddMotionPos, PE_AddMotionPos_curve), + HLL_EXPORT(Parts_AddMotionAlpha, PE_AddMotionAlpha_curve), HLL_TODO_EXPORT(Parts_AddMotionCG, GUIEngine_Parts_AddMotionCG), HLL_TODO_EXPORT(Parts_AddMotionCGTermination, GUIEngine_Parts_AddMotionCGTermination), HLL_TODO_EXPORT(Parts_AddMotionHGaugeRate, GUIEngine_Parts_AddMotionHGaugeRate), @@ -958,11 +957,11 @@ HLL_LIBRARY(GUIEngine, HLL_TODO_EXPORT(Parts_SetThumbnailReductionSize, GUIEngine_Parts_SetThumbnailReductionSize), HLL_TODO_EXPORT(Parts_SetThumbnailMode, GUIEngine_Parts_SetThumbnailMode), HLL_TODO_EXPORT(GetClickNumber, GUIEngine_GetClickNumber), - HLL_TODO_EXPORT(Parts_BeginMotion, GUIEngine_Parts_BeginMotion), - HLL_TODO_EXPORT(Parts_EndMotion, GUIEngine_Parts_EndMotion), - HLL_TODO_EXPORT(Parts_IsMotion, GUIEngine_Parts_IsMotion), + HLL_EXPORT(Parts_BeginMotion, PE_BeginMotion), + HLL_EXPORT(Parts_EndMotion, PE_EndMotion), + HLL_EXPORT(Parts_IsMotion, PE_IsMotion), HLL_TODO_EXPORT(Parts_SeekEndMotion, GUIEngine_Parts_SeekEndMotion), - HLL_TODO_EXPORT(Parts_UpdateMotionTime, GUIEngine_Parts_UpdateMotionTime), - HLL_TODO_EXPORT(Save, GUIEngine_Save), - HLL_TODO_EXPORT(SaveWithoutHideParts, GUIEngine_SaveWithoutHideParts), + HLL_EXPORT(Parts_UpdateMotionTime, PE_UpdateMotionTime), + HLL_EXPORT(Save, PE_Save), + HLL_EXPORT(SaveWithoutHideParts, PE_SaveWithoutHideParts), HLL_TODO_EXPORT(Load, GUIEngine_Load)); diff --git a/src/hll/IbisInputEngine.c b/src/hll/IbisInputEngine.c index ef0e205..2d21387 100644 --- a/src/hll/IbisInputEngine.c +++ b/src/hll/IbisInputEngine.c @@ -17,9 +17,11 @@ #include "hll.h" #include "sact.h" -//bool Mouse_HideCursorByGame(bool Hide); +//bool Mouse_MovePosImmediately(int x, int y); +//bool Mouse_HideCursorByGame(bool hide); //bool Mouse_IsHideCursorByGame(void); //void Mouse_HideByStepMessage(void); +HLL_QUIET_UNIMPLEMENTED(, void, IbisInputEngine, Mouse_HideByStepMessage); //void MouseWheel_ClearCount(void); HLL_QUIET_UNIMPLEMENTED(, void, IbisInputEngine, MouseWheel_ClearCount); @@ -49,6 +51,10 @@ HLL_WARN_UNIMPLEMENTED(0.0, float, IbisInputEngine, Joystick_GetAxis, int dev, i HLL_LIBRARY(IbisInputEngine, HLL_EXPORT(Mouse_GetPos, sact_Mouse_GetPos), + HLL_TODO_EXPORT(Mouse_MovePosImmediately, IbisInputEngine_Mouse_MovePosImmediately), + HLL_TODO_EXPORT(Mouse_HideCursorByGame, IbisInputEngine_Mouse_HideCursorByGame), + HLL_TODO_EXPORT(Mouse_IsHideCursorByGame, IbisInputEngine_Mouse_IsHideCursorByGame), + HLL_EXPORT(Mouse_HideByStepMessage, IbisInputEngine_Mouse_HideByStepMessage), HLL_EXPORT(MouseWheel_ClearCount, IbisInputEngine_MouseWheel_ClearCount), HLL_EXPORT(MouseWheel_GetCount, IbisInputEngine_MouseWheel_GetCount), HLL_EXPORT(Key_IsDown, sact_Key_IsDown), diff --git a/src/parts/construction.c b/src/parts/construction.c index eae7e5b..9ce5bc6 100644 --- a/src/parts/construction.c +++ b/src/parts/construction.c @@ -200,7 +200,7 @@ static void build_create(struct parts *parts, struct parts_construction_process struct parts_cp_create *op) { gfx_delete_texture(&cproc->common.texture); - gfx_init_texture_rgba(&cproc->common.texture, op->w, op->h, (SDL_Color){0,0,0,0}); + gfx_init_texture_rgba(&cproc->common.texture, op->w, op->h, (SDL_Color){0,0,0,255}); parts_set_dims(parts, &cproc->common, op->w, op->h); } @@ -230,12 +230,15 @@ static void build_fill_alpha_color(struct parts_construction_process *cproc, static void build_draw_text(struct parts_construction_process *cproc, struct parts_cp_text *op) { - // FIXME: this should set alpha to 0 in text area gfx_render_text(&cproc->common.texture, op->x, op->y, op->text->text, &op->style); } static void build_copy_text(struct parts_construction_process *cproc, struct parts_cp_text *op) { + int w = ceilf(gfx_size_text (&op->style, op->text->text)); + int h = ceilf(op->style.size + op->style.edge_up + op->style.edge_down); + gfx_fill_with_alpha(&cproc->common.texture, op->x, op->y, w, h, + op->style.edge_color.r, op->style.edge_color.g, op->style.edge_color.b, 0); gfx_render_text(&cproc->common.texture, op->x, op->y, op->text->text, &op->style); } @@ -278,7 +281,8 @@ bool PE_SetPartsConstructionSurfaceArea(int parts_no, int x, int y, int w, int h if (!parts_state_valid(--state)) return false; - struct parts_construction_process *cproc = get_cproc(parts_no, state); - parts_set_surface_area(&cproc->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_construction_process *cproc = parts_get_construction_process(parts, state); + parts_set_surface_area(parts, &cproc->common, x, y, w, h); return true; } diff --git a/src/parts/debug.c b/src/parts/debug.c index c17eba3..6efddad 100644 --- a/src/parts/debug.c +++ b/src/parts/debug.c @@ -139,6 +139,10 @@ static void parts_construction_process_print(struct parts_construction_process * static void parts_print_state(struct parts_state *state, int indent) { + if (state->type == PARTS_UNINITIALIZED) { + printf("UNINITIALIZED"); + return; + } printf("{\n"); indent++; @@ -304,7 +308,7 @@ static void _parts_print(struct parts *parts, int indent) } else { indent_printf(indent, "children = {\n"); struct parts *child; - TAILQ_FOREACH(child, &parts->children, parts_list_entry) { + PARTS_FOREACH_CHILD(child, parts) { _parts_print(child, indent+1); printf(",\n"); } @@ -324,8 +328,9 @@ void parts_print(struct parts *parts) void parts_engine_print(void) { struct parts *parts; - TAILQ_FOREACH(parts, &parts_list, parts_list_entry) { - parts_print(parts); + PARTS_LIST_FOREACH(parts) { + if (parts->parent < 0) + parts_print(parts); } } @@ -357,25 +362,25 @@ static void parts_list_print(struct parts *parts, int indent) struct parts_state *state = &parts->states[parts->state]; switch (state->type) { case PARTS_UNINITIALIZED: - printf("(uninitialized)\n"); + printf("(uninitialized)"); break; case PARTS_CG: - printf("(cg %d)\n", state->cg.no); + printf("(cg %d)", state->cg.no); break; case PARTS_TEXT: - printf("(text)\n"); // TODO? store actual text and print it here + printf("(text)"); // TODO? store actual text and print it here break; case PARTS_ANIMATION: - printf("(animation %d+%d)\n", state->anim.cg_no, state->anim.nr_frames); + printf("(animation %d+%d)", state->anim.cg_no, state->anim.nr_frames); break; case PARTS_NUMERAL: - printf("(numeral %d)\n", state->num.cg_no); + printf("(numeral %d)", state->num.cg_no); break; case PARTS_HGAUGE: - printf("(hgauge)\n"); // TODO? store rate and cg and print them here + printf("(hgauge)"); // TODO? store rate and cg and print them here break; case PARTS_VGAUGE: - printf("(vgauge)\n"); + printf("(vgauge)"); break; case PARTS_CONSTRUCTION_PROCESS: { printf("(construction process:"); @@ -402,13 +407,15 @@ static void parts_list_print(struct parts *parts, int indent) break; } } - printf(")\n"); + printf(")"); break; } } + printf(" @ z=%d\n", parts->z); + struct parts *child; - TAILQ_FOREACH(child, &parts->children, parts_list_entry) { + PARTS_FOREACH_CHILD(child, parts) { parts_list_print(child, indent + 1); } } @@ -416,8 +423,9 @@ static void parts_list_print(struct parts *parts, int indent) static void parts_cmd_parts_list(unsigned nr_args, char **args) { struct parts *parts; - TAILQ_FOREACH(parts, &parts_list, parts_list_entry) { - parts_list_print(parts, 0); + PARTS_LIST_FOREACH(parts) { + if (parts->parent < 0) + parts_list_print(parts, 0); } } diff --git a/src/parts/input.c b/src/parts/input.c index 2585c36..c296325 100644 --- a/src/parts/input.c +++ b/src/parts/input.c @@ -80,7 +80,7 @@ void PE_UpdateInputState(possibly_unused int passed_time) mouse_get_pos(&cur_pos.x, &cur_pos.y); struct parts *parts; - TAILQ_FOREACH(parts, &parts_list, parts_list_entry) { + PARTS_LIST_FOREACH(parts) { parts_update_mouse(parts, cur_pos, cur_clicking); } @@ -174,6 +174,19 @@ bool PE_IsCursorIn(int parts_no, int mouse_x, int mouse_y, int state) if (!parts_state_valid(--state)) return false; - // TODO - return false; + struct parts *parts = parts_try_get(parts_no); + if (!parts) + return false; + + // 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; + } + + Point mouse_pos = { mouse_x, mouse_y }; + return SDL_PointInRect(&mouse_pos, &hitbox); } diff --git a/src/parts/motion.c b/src/parts/motion.c index 3fba7e3..4a06001 100644 --- a/src/parts/motion.c +++ b/src/parts/motion.c @@ -15,6 +15,7 @@ */ #include "system4.h" +#include "system4/string.h" #include "audio.h" #include "xsystem4.h" @@ -162,10 +163,10 @@ static void parts_update_with_motion(struct parts *parts, struct parts_motion *m } } -static void parts_list_update_motion(struct parts_list *list) +static void parts_update_all_motion(void) { struct parts *parts; - TAILQ_FOREACH(parts, list, parts_list_entry) { + PARTS_LIST_FOREACH(parts) { struct parts_motion *motion; TAILQ_FOREACH(motion, &parts->motion, entry) { if (motion->begin_time > motion_t) @@ -175,13 +176,7 @@ static void parts_list_update_motion(struct parts_list *list) // at the end-state of the second motion. parts_update_with_motion(parts, motion); } - parts_list_update_motion(&parts->children); } -} - -static void parts_update_all_motion(void) -{ - parts_list_update_motion(&parts_list); struct sound_motion *sound; TAILQ_FOREACH(sound, &sound_motion_list, entry) { @@ -198,10 +193,10 @@ static void parts_update_all_motion(void) * NOTE: If a motion begins at e.g. t=100 with a value of v=0, then that value * becomes the initial value of v at t=0. */ -static void parts_list_init_all_motion(struct parts_list *list) +static void parts_init_all_motion(void) { struct parts *parts; - TAILQ_FOREACH(parts, list, parts_list_entry) { + PARTS_LIST_FOREACH(parts) { struct parts_motion *motion; bool initialized[PARTS_NR_MOTION_TYPES] = {0}; TAILQ_FOREACH(motion, &parts->motion, entry) { @@ -213,18 +208,12 @@ static void parts_list_init_all_motion(struct parts_list *list) } } -static void parts_list_fini_all_motion(struct parts_list *list) -{ - struct parts *parts; - TAILQ_FOREACH(parts, list, parts_list_entry) { - parts_clear_motion(parts); - parts_list_fini_all_motion(&parts->children); - } -} - static void parts_fini_all_motion(void) { - parts_list_fini_all_motion(&parts_list); + struct parts *parts; + PARTS_LIST_FOREACH(parts) { + parts_clear_motion(parts); + } while (!TAILQ_EMPTY(&sound_motion_list)) { struct sound_motion *motion = TAILQ_FIRST(&sound_motion_list); @@ -244,6 +233,13 @@ void PE_AddMotionPos(int parts_no, int begin_x, int begin_y, int end_x, int end_ parts_add_motion(parts, motion); } +void PE_AddMotionPos_curve(int parts_no, int begin_x, int begin_y, int end_x, int end_y, + int begin_t, int end_t, struct string *curve_name) +{ + // TODO: use curve + PE_AddMotionPos(parts_no, begin_x, begin_y, end_x, end_y, begin_t, end_t); +} + void PE_AddMotionAlpha(int parts_no, int begin_a, int end_a, int begin_t, int end_t) { struct parts *parts = parts_get(parts_no); @@ -253,6 +249,13 @@ void PE_AddMotionAlpha(int parts_no, int begin_a, int end_a, int begin_t, int en parts_add_motion(parts, motion); } +void PE_AddMotionAlpha_curve(int parts_no, int begin_a, int end_a, int begin_t, int end_t, + struct string *curve_name) +{ + // TODO: use curve + PE_AddMotionAlpha(parts_no, begin_a, end_a, begin_t, end_t); +} + void PE_AddMotionCG_by_index(int parts_no, int begin_cg_no, int nr_cg, int begin_t, int end_t) { struct parts *parts = parts_get(parts_no); @@ -372,7 +375,7 @@ void PE_BeginMotion(void) // FIXME: starting a motion seems to clear non-default states motion_t = 0; is_motion = true; - parts_list_init_all_motion(&parts_list); + parts_init_all_motion(); } void PE_EndMotion(void) @@ -397,6 +400,12 @@ void PE_SetMotionTime(int t) PE_EndMotion(); } +void PE_UpdateMotionTime(int time, possibly_unused bool skip) +{ + // TODO: use skip + PE_SetMotionTime(motion_t + time); +} + bool PE_IsMotion(void) { return is_motion; diff --git a/src/parts/parts.c b/src/parts/parts.c index d468598..9580b53 100644 --- a/src/parts/parts.c +++ b/src/parts/parts.c @@ -37,6 +37,7 @@ static void parts_init(struct parts *parts) parts->origin_mode = 1; parts->z = 1; parts->show = true; + parts->alpha = 255; parts->parent = -1; parts->linked_to = -1; parts->linked_from = -1; @@ -56,19 +57,33 @@ static struct parts *parts_alloc(void) return parts; } -static void parts_list_insert(struct parts_list *list, struct parts *parts) +static void parts_list_insert(struct parts *parts) { struct parts *p; - TAILQ_FOREACH(p, list, parts_list_entry) { + PARTS_LIST_FOREACH(p) { if (p->z >= parts->z) { TAILQ_INSERT_BEFORE(p, parts, parts_list_entry); return; } } - TAILQ_INSERT_TAIL(list, parts, parts_list_entry); + TAILQ_INSERT_TAIL(&parts_list, parts, parts_list_entry); parts_engine_dirty(); } +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; + } else { + child->parent = -1; + } +} + struct parts *parts_try_get(int parts_no) { struct ht_slot *slot = ht_put_int(parts_table, parts_no, NULL); @@ -86,7 +101,7 @@ struct parts *parts_get(int parts_no) struct parts *parts = parts_alloc(); parts->no = parts_no; slot->value = parts; - parts_list_insert(&parts_list, parts); + parts_list_insert(parts); return parts; } @@ -95,16 +110,9 @@ bool parts_exists(int parts_no) return !!ht_get_int(parts_table, parts_no, NULL); } -static struct parts_list *parts_get_list(struct parts *parts) +static void parts_list_remove(struct parts *parts) { - if (parts->parent < 0) - return &parts_list; - return &parts_get(parts->parent)->children; -} - -static void parts_list_remove(struct parts_list *list, struct parts *parts) -{ - TAILQ_REMOVE(list, parts, parts_list_entry); + TAILQ_REMOVE(&parts_list, parts, parts_list_entry); } static void parts_state_free(struct parts_state *state) @@ -114,6 +122,8 @@ static void parts_state_free(struct parts_state *state) break; case PARTS_CG: gfx_delete_texture(&state->common.texture); + if (state->cg.name) + free_string(state->cg.name); break; case PARTS_TEXT: gfx_delete_texture(&state->common.texture); @@ -123,6 +133,7 @@ static void parts_state_free(struct parts_state *state) for (unsigned i = 0; i < state->anim.nr_frames; i++) { gfx_delete_texture(&state->anim.frames[i]); } + free(state->anim.frames); break; case PARTS_NUMERAL: gfx_delete_texture(&state->common.texture); @@ -256,12 +267,22 @@ static Point calculate_offset(int mode, int w, int h) static void parts_common_recalculate_hitbox(struct parts *parts, struct parts_common *common) { 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, - .w = common->w, - .h = common->h, - }; + + if (common->surface_area.w || common->surface_area.h) { + Rectangle r = { 0, 0, common->w, common->h }; + 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; + } else { + common->hitbox = (Rectangle) { + .x = parts->pos.x + common->origin_offset.x, + .y = parts->pos.y + common->origin_offset.y, + .w = common->w, + .h = common->h, + }; + } } static void parts_recalculate_hitbox(struct parts *parts) @@ -327,7 +348,7 @@ void parts_set_alpha(struct parts *parts, int alpha) parts_dirty(parts); } -static bool parts_set_cg(struct parts *parts, struct cg *cg, int cg_no, int state) +static bool parts_set_cg(struct parts *parts, struct cg *cg, int cg_no, struct string *name, int state) { if (!cg) return false; @@ -336,6 +357,9 @@ static bool parts_set_cg(struct parts *parts, struct cg *cg, int cg_no, int stat gfx_init_texture_with_cg(&parts_cg->common.texture, cg); parts_set_dims(parts, &parts_cg->common, cg->metrics.w, cg->metrics.h); parts_cg->no = cg_no; + if (parts_cg->name) + free_string(parts_cg->name); + parts_cg->name = name; parts_dirty(parts); cg_free(cg); return true; @@ -348,7 +372,7 @@ bool parts_set_cg_by_index(struct parts *parts, int cg_no, int state) parts_dirty(parts); return true; } - return parts_set_cg(parts, asset_cg_load(cg_no), cg_no, state); + return parts_set_cg(parts, asset_cg_load(cg_no), cg_no, NULL, state); } bool parts_set_cg_by_name(struct parts *parts, struct string *cg_name, int state) @@ -360,7 +384,7 @@ bool parts_set_cg_by_name(struct parts *parts, struct string *cg_name, int state } int no; struct cg *cg = asset_cg_load_by_name(cg_name->text, &no); - return parts_set_cg(parts, cg, no, state); + return parts_set_cg(parts, cg, no, string_dup(cg_name), state); } void parts_set_hgauge_rate(struct parts *parts, float rate, int state) @@ -467,9 +491,12 @@ void parts_set_state(struct parts *parts, enum parts_state_type state) } } -void parts_set_surface_area(struct parts_common *common, int x, int y, int w, int h) +void parts_set_surface_area(struct parts *parts, struct parts_common *common, int x, int y, int w, int h) { + if (x < 0 || y < 0) + return; common->surface_area = (Rectangle) { x, y, w, h }; + parts_common_recalculate_hitbox(parts, common); } static void parts_update_loop(struct parts *parts, int passed_time) @@ -498,7 +525,7 @@ static void parts_update_loop(struct parts *parts, int passed_time) static void parts_update_animation(int passed_time) { struct parts *parts; - TAILQ_FOREACH(parts, &parts_list, parts_list_entry) { + PARTS_LIST_FOREACH(parts) { parts_update_loop(parts, passed_time); } } @@ -515,14 +542,14 @@ void parts_release(int parts_no) parts_state_free(&parts->states[i]); } + // break parent/child relationships while (!TAILQ_EMPTY(&parts->children)) { struct parts *child = TAILQ_FIRST(&parts->children); - child->parent = -1; - parts_list_remove(&parts->children, child); - parts_list_insert(&parts_list, child); + parts_set_parent(child, NULL); } + parts_set_parent(parts, NULL); - parts_list_remove(parts_get_list(parts), parts); + parts_list_remove(parts); free(parts); slot->value = NULL; parts_engine_dirty(); @@ -575,59 +602,65 @@ int PE_GetDelegateIndex(int parts_no) bool PE_SetPartsCG(int parts_no, struct string *cg_name, possibly_unused int sprite_deform, int state) { - if (!parts_state_valid(--state)) { - WARNING("Invalid parts state: %d", state); + if (!parts_state_valid(--state)) return false; - } return parts_set_cg_by_name(parts_get(parts_no), cg_name, state); } bool PE_SetPartsCG_by_index(int parts_no, int cg_no, possibly_unused int sprite_deform, int state) { - if (!parts_state_valid(--state)) { - WARNING("Invalid parts state: %d", state); + if (!parts_state_valid(--state)) return false; - } return parts_set_cg_by_index(parts_get(parts_no), cg_no, state); } +void PE_GetPartsCGName(int parts_no, struct string **cg_name, int state) +{ + if (!parts_state_valid(--state)) + return; + struct parts_cg *cg = parts_get_cg(parts_get(parts_no), state); + if (cg->name) { + if (*cg_name) + free_string(*cg_name); + *cg_name = string_dup(cg->name); + } +} + bool PE_SetPartsCGSurfaceArea(int parts_no, int x, int y, int w, int h, int state) { - if (!parts_state_valid(--state)) { - WARNING("Invalid parts state: %d", state); + if (!parts_state_valid(--state)) return false; - } - struct parts_cg *cg = parts_get_cg(parts_get(parts_no), state); - parts_set_surface_area(&cg->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_cg *cg = parts_get_cg(parts, state); + parts_set_surface_area(parts, &cg->common, x, y, w, h); return true; } int PE_GetPartsCGNumber(int parts_no, int state) { if (!parts_state_valid(--state)) { - WARNING("Invalid parts state: %d", state); return false; } return parts_get_cg(parts_get(parts_no), state)->no; } -bool PE_SetLoopCG_by_index(int parts_no, int cg_no, int nr_frames, int frame_time, int state) +static bool set_loop_cg(int parts_no, int start_no, int nr_frames, int frame_time, int state, + struct cg *(*load_cg)(int no, void *data), void *data) { - if (!parts_state_valid(--state)) { - WARNING("Invalid parts state: %d", state); + if (!parts_state_valid(--state)) return false; - } if (nr_frames <= 0 || nr_frames > 10000) { WARNING("Invalid frame count: %d", nr_frames); + return false; } int w = 0, h = 0; struct parts *parts = parts_get(parts_no); Texture *frames = xcalloc(nr_frames, sizeof(Texture)); for (int i = 0; i < nr_frames; i++) { - struct cg *cg = asset_cg_load(cg_no + i); + struct cg *cg = load_cg(start_no + i, data); if (!cg) { for (int j = 0; j < i; j++) { gfx_delete_texture(&frames[j]); @@ -643,13 +676,41 @@ bool PE_SetLoopCG_by_index(int parts_no, int cg_no, int nr_frames, int frame_tim struct parts_animation *anim = parts_get_animation(parts, state); parts_set_dims(parts, &anim->common, w, h); - anim->frames = frames; // free previous value? + free(anim->frames); + anim->frames = frames; anim->nr_frames = nr_frames; anim->frame_time = frame_time; anim->elapsed = 0; anim->current_frame = 0; anim->common.texture = frames[0]; return true; + +} + +static struct cg *load_loop_cg_by_index(int no, void *_) +{ + return asset_cg_load(no); +} + +bool PE_SetLoopCG_by_index(int parts_no, int cg_no, int nr_frames, int frame_time, int state) +{ + return set_loop_cg(parts_no, cg_no, nr_frames, frame_time, state, + load_loop_cg_by_index, NULL); +} + +static struct cg *load_loop_cg_by_name(int no, void *data) +{ + int unused_no; + struct string *cg_name = string_format((struct string*)data, (union vm_value){.i=no}); + struct cg *cg = asset_cg_load_by_name(cg_name->text, &unused_no); + free_string(cg_name); + return cg; +} + +bool PE_SetLoopCG(int parts_no, struct string *cg_name, int start_no, int nr_frames, int frame_time, int state) +{ + return set_loop_cg(parts_no, start_no, nr_frames, frame_time, state, + load_loop_cg_by_name, cg_name); } bool PE_SetLoopCGSurfaceArea(int parts_no, int x, int y, int w, int h, int state) @@ -659,8 +720,9 @@ bool PE_SetLoopCGSurfaceArea(int parts_no, int x, int y, int w, int h, int state return false; } - struct parts_animation *anim = parts_get_animation(parts_get(parts_no), state); - parts_set_surface_area(&anim->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_animation *anim = parts_get_animation(parts, state); + parts_set_surface_area(parts, &anim->common, x, y, w, h); return true; } @@ -719,8 +781,9 @@ bool PE_SetHGaugeSurfaceArea(int parts_no, int x, int y, int w, int h, int state if (!parts_state_valid(--state)) return false; - struct parts_gauge *g = parts_get_hgauge(parts_get(parts_no), state); - parts_set_surface_area(&g->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_gauge *g = parts_get_hgauge(parts, state); + parts_set_surface_area(parts, &g->common, x, y, w, h); return true; } @@ -759,8 +822,9 @@ bool PE_SetVGaugeSurfaceArea(int parts_no, int x, int y, int w, int h, int state if (!parts_state_valid(--state)) return false; - struct parts_gauge *g = parts_get_vgauge(parts_get(parts_no), state); - parts_set_surface_area(&g->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_gauge *g = parts_get_vgauge(parts, state); + parts_set_surface_area(parts, &g->common, x, y, w, h); return true; } @@ -849,8 +913,9 @@ bool PE_SetNumeralSurfaceArea(int parts_no, int x, int y, int w, int h, int stat if (!parts_state_valid(--state)) return false; - struct parts_numeral *n = parts_get_numeral(parts_get(parts_no), state); - parts_set_surface_area(&n->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_numeral *n = parts_get_numeral(parts, state); + parts_set_surface_area(parts, &n->common, x, y, w, h); return true; } @@ -893,9 +958,8 @@ void PE_SetZ(int parts_no, int z) struct parts *parts = parts_get(parts_no); parts->z = z; - struct parts_list *list = parts_get_list(parts); - parts_list_remove(list, parts); - parts_list_insert(list, parts); + parts_list_remove(parts); + parts_list_insert(parts); } void PE_SetShow(int parts_no, bool show) @@ -913,8 +977,16 @@ void PE_SetAlpha(int parts_no, int alpha) } void PE_SetPartsDrawFilter(int PartsNumber, int DrawFilter); -void PE_SetAddColor(int PartsNumber, int nR, int nG, int nB); -void PE_SetMultiplyColor(int PartsNumber, int nR, int nG, int nB); + +void PE_SetAddColor(int parts_no, int r, int g, int b) +{ + //NOTICE("PE_SetAddColor(%d, %d, %d, %d)", parts_no, r, g, b); +} + +void PE_SetMultiplyColor(int parts_no, int r, int g, int b) +{ + //NOTICE("PE_SetMultiplyColor(%d, %d, %d, %d)", parts_no, r, g, b); +} int PE_GetPartsX(int parts_no) { @@ -972,9 +1044,7 @@ void PE_SetParentPartsNumber(int parts_no, int parent_parts_no) if (parts->parent == parent_parts_no) return; - parts_list_remove(parts_get_list(parts), parts); - parts_list_insert(&parts_get(parent_parts_no)->children, parts); - parts->parent = parent_parts_no; + parts_set_parent(parts, parts_get(parent_parts_no)); } bool PE_SetPartsGroupNumber(possibly_unused int PartsNumber, possibly_unused int GroupNumber) @@ -1009,7 +1079,12 @@ void PE_SetPartsRotateZ(int parts_no, float rot_z) } void PE_SetPartsAlphaClipperPartsNumber(int PartsNumber, int AlphaClipperPartsNumber); -void PE_SetPartsPixelDecide(int PartsNumber, bool PixelDecide); + +void PE_SetPartsPixelDecide(int parts_no, bool pixel_decide) +{ + //NOTICE("PE_SetPartsPixelDecide(%d, %s)", parts_no, pixel_decide ? "true" : "false"); +} + bool PE_SetThumbnailReductionSize(int ReductionSize); bool PE_SetThumbnailMode(bool Mode); @@ -1024,6 +1099,17 @@ bool PE_Save(struct page **buffer) return true; } +bool PE_SaveWithoutHideParts(struct page **buffer) +{ + // TODO + if (*buffer) { + delete_page_vars(*buffer); + free_page(*buffer); + } + *buffer = NULL; + return true; +} + bool PE_Load(possibly_unused struct page **buffer) { // TODO diff --git a/src/parts/parts_internal.h b/src/parts/parts_internal.h index 2582052..1833bf1 100644 --- a/src/parts/parts_internal.h +++ b/src/parts/parts_internal.h @@ -98,6 +98,7 @@ struct parts_common { struct parts_cg { struct parts_common common; int no; + struct string *name; }; struct parts_text { @@ -199,6 +200,7 @@ struct parts { enum parts_state_type state; struct parts_state states[PARTS_NR_STATES]; TAILQ_ENTRY(parts) parts_list_entry; + TAILQ_ENTRY(parts) child_list_entry; struct parts_list children; int no; int delegate_index; @@ -219,6 +221,9 @@ struct parts { TAILQ_HEAD(, parts_motion) motion; }; +#define PARTS_LIST_FOREACH(iter) TAILQ_FOREACH(iter, &parts_list, parts_list_entry) +#define PARTS_FOREACH_CHILD(iter, parent) TAILQ_FOREACH(iter, &parent->children, child_list_entry) + // parts.c extern struct parts_list parts_list; struct parts *parts_try_get(int parts_no); @@ -244,7 +249,7 @@ bool parts_set_number(struct parts *parts, int n, int state); void parts_set_state(struct parts *parts, enum parts_state_type state); void parts_release(int parts_no); void parts_release_all(void); -void parts_set_surface_area(struct parts_common *common, int x, int y, int w, int h); +void parts_set_surface_area(struct parts *parts, struct parts_common *common, int x, int y, int w, int h); // render.c void parts_render_init(void); diff --git a/src/parts/render.c b/src/parts/render.c index b3edbca..a44321a 100644 --- a/src/parts/render.c +++ b/src/parts/render.c @@ -81,17 +81,16 @@ static void parts_render_cg(struct parts *parts, struct parts_common *common, } gfx_prepare_job(&job); - glUniform1f(parts_shader.alpha_mod, common->texture.alpha_mod / 255.0); + glUniform1f(parts_shader.alpha_mod, params->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); gfx_run_job(&job); } -static void _parts_render(struct parts *parts, struct parts_render_params *parent_params) +void parts_render(struct parts *parts) { if (!parts->show) return; - if (parts->linked_to >= 0) { struct parts *link_parts = parts_get(parts->linked_to); struct parts_state *link_state = &link_parts->states[link_parts->state]; @@ -99,11 +98,21 @@ static void _parts_render(struct parts *parts, struct parts_render_params *paren return; } - struct parts_render_params params = *parent_params; - // modify params per parts values - params.alpha *= parts->alpha / 255.0; - params.offset.x += parts->pos.x; - params.offset.y += parts->pos.y; + struct parts_render_params params = { + .offset = parts->pos, + .alpha = parts->alpha, + }; + + // 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; + } // render struct parts_state *state = &parts->states[parts->state]; @@ -124,32 +133,13 @@ static void _parts_render(struct parts *parts, struct parts_render_params *paren break; } } - - // render children - struct parts *child; - TAILQ_FOREACH(child, &parts->children, parts_list_entry) { - _parts_render(child, ¶ms); - } -} - -void parts_render(struct parts *parts) -{ - struct parts_render_params params = { - .offset = { 0, 0 }, - .alpha = 255, - }; - _parts_render(parts, ¶ms); } void parts_engine_render(possibly_unused struct sprite *_) { - struct parts_render_params params = { - .offset = { 0, 0 }, - .alpha = 255, - }; struct parts *parts; - TAILQ_FOREACH(parts, &parts_list, parts_list_entry) { - _parts_render(parts, ¶ms); + PARTS_LIST_FOREACH(parts) { + parts_render(parts); } } diff --git a/src/parts/text.c b/src/parts/text.c index db775dc..0ef6404 100644 --- a/src/parts/text.c +++ b/src/parts/text.c @@ -114,8 +114,9 @@ bool PE_SetPartsTextSurfaceArea(int parts_no, int x, int y, int w, int h, int st if (!parts_state_valid(--state)) return false; - struct parts_text *text = parts_get_text(parts_get(parts_no), state); - parts_set_surface_area(&text->common, x, y, w, h); + struct parts *parts = parts_get(parts_no); + struct parts_text *text = parts_get_text(parts, state); + parts_set_surface_area(parts, &text->common, x, y, w, h); return true; }