X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=4b87d8118696c33434364a001e878c1c99101835;hb=438885e31e0cf03304f95b125c949b9c8641e6b5;hp=ac194d56a5b97d3d5435e8dbdc68ab5c5b400c36;hpb=19d38b8a650bd10ffbbaed031f5b3819dbcd32ce;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index ac194d56..4b87d811 100644 --- a/src/tools.c +++ b/src/tools.c @@ -11,6 +11,8 @@ * tools.c * ***********************************************************/ +#include + #include "libgame/libgame.h" #include "tools.h" @@ -37,6 +39,118 @@ #define NUM_TOOL_BUTTONS 7 +/* constants for number of doors and door parts */ +#define NUM_DOORS 2 +#define MAX_PARTS_PER_DOOR 8 +#define MAX_DOOR_PARTS (NUM_DOORS * MAX_PARTS_PER_DOOR) + + +struct DoorPartOrderInfo +{ + int nr; + int sort_priority; +}; + +static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS]; + +struct DoorPartControlInfo +{ + int door_nr; + int graphic; + struct DoorPartPosInfo *pos; +}; + +static struct DoorPartControlInfo door_part_controls[] = +{ + { + DOOR_1, + IMG_DOOR_1_GFX_PART_1, + &door_1.part_1 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_2, + &door_1.part_2 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_3, + &door_1.part_3 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_4, + &door_1.part_4 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_5, + &door_1.part_5 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_6, + &door_1.part_6 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_7, + &door_1.part_7 + }, + { + DOOR_1, + IMG_DOOR_1_GFX_PART_8, + &door_1.part_8 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_1, + &door_2.part_1 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_2, + &door_2.part_2 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_3, + &door_2.part_3 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_4, + &door_2.part_4 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_5, + &door_2.part_5 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_6, + &door_2.part_6 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_7, + &door_2.part_7 + }, + { + DOOR_2, + IMG_DOOR_2_GFX_PART_8, + &door_2.part_8 + }, + + { + -1, + -1, + NULL + } +}; + + /* forward declaration for internal use */ static void UnmapToolButtons(); static void HandleToolButtons(struct GadgetInfo *); @@ -1088,6 +1202,17 @@ void DrawBackground(int x, int y, int width, int height) #endif #if 1 + +#if 1 + if (IN_GFX_FIELD_FULL(x, y)) + redraw_mask |= REDRAW_FIELD; + else if (IN_GFX_DOOR_1(x, y)) + redraw_mask |= REDRAW_DOOR_1; + else if (IN_GFX_DOOR_2(x, y)) + redraw_mask |= REDRAW_DOOR_2; + else if (IN_GFX_DOOR_3(x, y)) + redraw_mask |= REDRAW_DOOR_3; +#else /* (this only works for the current arrangement of playfield and panels) */ if (x < gfx.dx) redraw_mask |= REDRAW_FIELD; @@ -1095,6 +1220,8 @@ void DrawBackground(int x, int y, int width, int height) redraw_mask |= REDRAW_DOOR_1; else redraw_mask |= REDRAW_DOOR_2; +#endif + #else /* (this is just wrong (when drawing to one of the two door panel areas)) */ redraw_mask |= REDRAW_FIELD; @@ -5170,6 +5297,46 @@ boolean Request(char *text, unsigned int req_state) #endif +static int compareDoorPartOrderInfo(const void *object1, const void *object2) +{ + const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1; + const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2; + int compare_result; + + if (dpo1->sort_priority != dpo2->sort_priority) + compare_result = dpo1->sort_priority - dpo2->sort_priority; + else + compare_result = dpo1->nr - dpo2->nr; + + return compare_result; +} + +void InitDoors() +{ + int i; + + for (i = 0; door_part_controls[i].door_nr != -1; i++) + { + struct DoorPartControlInfo *dpc = &door_part_controls[i]; + struct DoorPartOrderInfo *dpo = &door_part_order[i]; + + /* fill structure for door part draw order */ + dpo->nr = i; + dpo->sort_priority = dpc->pos->sort_priority; + +#if 0 + struct DoorPartPosInfo *pos = dpc->pos; + + printf(":0: step_xoffset == %d, step_yoffset == %d\n", + pos->step_xoffset, pos->step_yoffset); +#endif + } + + /* sort door part controls according to sort_priority and graphic number */ + qsort(door_part_order, MAX_DOOR_PARTS, + sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo); +} + unsigned int OpenDoor(unsigned int door_state) { if (door_state & DOOR_COPY_BACK) @@ -5220,6 +5387,481 @@ unsigned int SetDoorState(unsigned int door_state) return MoveDoor(door_state | DOOR_SET_STATE); } +#if 1 + +// ========== TEST 1 =========================================================== + +int euclid(int a, int b) +{ + return (b ? euclid(b, a % b) : a); +} + +unsigned int MoveDoor(unsigned int door_state) +{ + struct XY panel_pos_list[] = + { + { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 }, + { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 }, + }; + struct Rect door_rect_list[] = + { + { DX, DY, DXSIZE, DYSIZE }, + { VX, VY, VXSIZE, VYSIZE } + }; + static int door1 = DOOR_OPEN_1; + static int door2 = DOOR_CLOSE_2; +#if 1 + unsigned int door_delay = 0; + unsigned int door_delay_value; +#endif +#if 0 + int stepsize = 1; +#endif + int i; + +#if 1 + if (door_1.width < 0 || door_1.width > DXSIZE) + door_1.width = DXSIZE; + if (door_1.height < 0 || door_1.height > DYSIZE) + door_1.height = DYSIZE; + if (door_2.width < 0 || door_2.width > VXSIZE) + door_2.width = VXSIZE; + if (door_2.height < 0 || door_2.height > VYSIZE) + door_2.height = VYSIZE; +#endif + + if (door_state == DOOR_GET_STATE) + return (door1 | door2); + + if (door_state & DOOR_SET_STATE) + { + if (door_state & DOOR_ACTION_1) + door1 = door_state & DOOR_ACTION_1; + if (door_state & DOOR_ACTION_2) + door2 = door_state & DOOR_ACTION_2; + + return (door1 | door2); + } + + if (!(door_state & DOOR_FORCE_REDRAW)) + { + if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1) + door_state &= ~DOOR_OPEN_1; + else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1) + door_state &= ~DOOR_CLOSE_1; + if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2) + door_state &= ~DOOR_OPEN_2; + else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2) + door_state &= ~DOOR_CLOSE_2; + } + +#if 0 + door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay : + door_2.step_delay); + + if (setup.quick_doors) + { + stepsize = 20; /* must be chosen to always draw last frame */ + door_delay_value = 0; + } +#endif + + if (global.autoplay_leveldir) + { + door_state |= DOOR_NO_DELAY; + door_state &= ~DOOR_CLOSE_ALL; + } + +#if 1 + if (game_status == GAME_MODE_EDITOR) + door_state |= DOOR_NO_DELAY; +#endif + + if (door_state & DOOR_ACTION) + { + boolean door_panel_drawn[NUM_DOORS]; + boolean door_part_done[MAX_DOOR_PARTS]; + boolean door_part_done_all; + int num_xsteps[MAX_DOOR_PARTS]; + int num_ysteps[MAX_DOOR_PARTS]; + int max_move_delay = 0; // delay for complete animations of all doors + int max_step_delay = 0; // delay (ms) between two animation frames + int num_move_steps = 0; // number of animation steps for all doors + int current_move_delay = 0; + int k; + + for (i = 0; i < MAX_DOOR_PARTS; i++) + { + int nr = door_part_order[i].nr; + struct DoorPartControlInfo *dpc = &door_part_controls[nr]; + struct GraphicInfo *g = &graphic_info[dpc->graphic]; + int door_token = dpc->door_nr; + + door_part_done[nr] = (!(door_state & door_token) || + !g->bitmap); + } + + for (i = 0; i < MAX_DOOR_PARTS; i++) + { + struct DoorPartControlInfo *dpc = &door_part_controls[i]; + struct GraphicInfo *g = &graphic_info[dpc->graphic]; + struct DoorPartPosInfo *pos = dpc->pos; + int step_xoffset = ABS(pos->step_xoffset); + int step_yoffset = ABS(pos->step_yoffset); + int step_delay = pos->step_delay; + float move_xsize = (step_xoffset ? g->width : 0); + float move_ysize = (step_yoffset ? g->height : 0); + /* + int move_size = (move_xsize && move_ysize ? + MIN(move_xsize, move_ysize) : + move_xsize ? move_xsize : move_ysize); + */ + int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0); + int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0); + /* + int move_xdelay = move_xsteps * step_delay; + int move_ydelay = move_ysteps * step_delay; + int move_delay = (move_xdelay && move_ydelay ? + MIN(move_xdelay, move_ydelay) : + move_xdelay ? move_xdelay : move_ydelay); + */ + int move_steps = (move_xsteps && move_ysteps ? + MIN(move_xsteps, move_ysteps) : + move_xsteps ? move_xsteps : move_ysteps); + int move_delay = move_steps * step_delay; + // int move_delay = MAX(move_xsize, move_ysize) * step_delay; + + max_move_delay = MAX(max_move_delay, move_delay); + max_step_delay = (max_step_delay == 0 ? step_delay : + euclid(max_step_delay, step_delay)); + + num_xsteps[i] = move_xsteps; + num_ysteps[i] = move_ysteps; + } + + num_move_steps = max_move_delay / max_step_delay; + + door_delay_value = max_step_delay; + +#if 0 + door_delay_value *= 10; +#endif + +#if 0 + printf("::: max_move_delay == %d, max_step_delay == %d, num_move_steps == %d\n", + max_move_delay, max_step_delay, num_move_steps); +#endif + +#if 0 + for (i = 0; i < MAX_DOOR_PARTS; i++) + printf("::: door_part_done[%d] == %d\n", i, door_part_done[i]); + printf("\n"); +#endif + + for (k = 0; k < num_move_steps; k++) + { + for (i = 0; i < NUM_DOORS; i++) + door_panel_drawn[i] = FALSE; + + for (i = 0; i < MAX_DOOR_PARTS; i++) + { + int nr = door_part_order[i].nr; + struct DoorPartControlInfo *dpc = &door_part_controls[nr]; + int door_token = dpc->door_nr; + int door_index = DOOR_INDEX_FROM_TOKEN(door_token); + struct GraphicInfo *g = &graphic_info[dpc->graphic]; + struct DoorPartPosInfo *pos = dpc->pos; + struct XY *panel_pos = &panel_pos_list[door_index]; + struct Rect *door_rect = &door_rect_list[door_index]; + int step_delay = pos->step_delay; + int src_xx, src_yy; + int dst_xx, dst_yy; + int width, height; + +#if 0 + // !!! TEST !!! + if (nr != 0 && nr != 8) + continue; +#endif + + if (door_part_done[nr]) + continue; + + if (!(door_state & door_token)) + continue; + + if (!g->bitmap) + continue; + + if (current_move_delay % step_delay) + continue; + + if (!door_panel_drawn[door_index]) + { + BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y, + door_rect->width, door_rect->height, + door_rect->x, door_rect->y); + + door_panel_drawn[door_index] = TRUE; + } + + if ((door_state & door_token) & DOOR_OPEN) + { + int step_factor = step_delay / max_step_delay; + int kx = k / step_factor + 1; + int ky = k / step_factor + 1; + +#if 0 + // if (k == 0) + printf("::: kx == %d, ky == %d\n", kx, ky); +#endif + + if (pos->step_xoffset < 0) + { + src_xx = 0; + dst_xx = pos->x + ABS(kx * pos->step_xoffset); + width = g->width; + + if (dst_xx + width > door_rect->width) + width = door_rect->width - dst_xx; + } + else + { + src_xx = 0; + dst_xx = pos->x - kx * pos->step_xoffset; + + if (dst_xx < 0) + { + src_xx = ABS(dst_xx); + dst_xx = 0; + } + + width = g->width - src_xx; + } + + if (pos->step_yoffset < 0) + { + src_yy = 0; + dst_yy = pos->y + ABS(ky * pos->step_yoffset); + height = g->height; + + if (dst_yy + height > door_rect->height) + height = door_rect->height - dst_yy; + } + else + { + src_yy = 0; + dst_yy = pos->y - ky * pos->step_yoffset; + + if (dst_yy < 0) + { + src_yy = ABS(dst_yy); + dst_yy = 0; + } + + height = g->height - src_yy; + } + +#if 0 + if (width < 0 || height < 0) + door_part_done[nr] = TRUE; +#endif + } + else // DOOR_CLOSE + { + int step_factor = step_delay / max_step_delay; + int num_steps = (num_xsteps[nr] && num_ysteps[nr] ? + MIN(num_xsteps[nr], num_ysteps[nr]) : + num_xsteps[nr] ? num_xsteps[nr] : + num_ysteps[nr]); +#if 1 + int kx = num_steps - k / step_factor - 1; + int ky = num_steps - k / step_factor - 1; +#else + int kx = num_xsteps[nr] - k; + int ky = num_ysteps[nr] - k; +#endif + +#if 0 + // !!! TEST !!! + if (nr != 0) + continue; +#endif + +#if 0 + // if (k == 0) + printf("::: kx == %d, ky == %d\n", kx, ky); +#endif + +#if 0 + if (k == 0) + printf("::: step_xoffset == %d, step_yoffset == %d\n", + pos->step_xoffset, pos->step_yoffset); +#endif + + if (pos->step_xoffset < 0) + { + src_xx = 0; + dst_xx = pos->x + ABS(kx * pos->step_xoffset); + width = g->width; + + if (dst_xx + width > door_rect->width) + width = door_rect->width - dst_xx; + } + else + { + src_xx = 0; + dst_xx = pos->x - kx * pos->step_xoffset; + + if (dst_xx < 0) + { + src_xx = ABS(dst_xx); + dst_xx = 0; + } + + width = g->width - src_xx; + } + + if (pos->step_yoffset < 0) + { + src_yy = 0; + dst_yy = pos->y + ABS(ky * pos->step_yoffset); + height = g->height; + + if (dst_yy + height > door_rect->height) + height = door_rect->height - dst_yy; + } + else + { + src_yy = 0; + dst_yy = pos->y - ky * pos->step_yoffset; + + if (dst_yy < 0) + { + src_yy = ABS(dst_yy); + dst_yy = 0; + } + + height = g->height - src_yy; + } + +#if 0 + printf("::: src_xx, src_yy ; dst_xx, dst_yy ; width, height == %d, %d ; %d, %d ; %d, %d\n", src_xx, src_yy, dst_xx, dst_yy, width, height); +#endif + +#if 0 + if ((pos->step_xoffset != 0 && width >= g->width) || + (pos->step_yoffset != 0 && height >= g->height)) + door_part_done[nr] = TRUE; +#endif + +#if 0 +#if 1 + // !!! TEST !!! + + door_part_done[nr] = TRUE; + + BlitBitmapMasked(g->bitmap, drawto, g->src_x, g->src_y, + g->width, g->height, + door_rect->x + pos->x, door_rect->y + pos->y); + + redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token); +#else + src_xx = (num_xsteps[nr] - k) * pos->step_xoffset; + src_yy = (num_ysteps[nr] - k) * pos->step_yoffset; + dst_xx = pos->x; + dst_yy = pos->y; + width = g->width - src_xx; + height = g->height - src_yy; + + // if (width < ABS(pos->step_xoffset) + + + + + src_xx = g->width - k * pos->step_xoffset; + src_yy = g->height - k * pos->step_yoffset; + dst_xx = pos->x; + dst_yy = pos->y; + + if (width < 0 || height < 0) + door_part_done[nr] = TRUE; +#endif +#endif + } + + if (door_part_done[nr]) + continue; + +#if 0 + // !!! TEST !!! + if (nr != 7) + continue; +#endif + + if (width >= 0 && width <= g->width && + height >= 0 && height <= g->height) + BlitBitmapMasked(g->bitmap, drawto, + g->src_x + src_xx, g->src_y + src_yy, width, height, + door_rect->x + dst_xx, door_rect->y + dst_yy); + // else + // printf("::: %d: width == %d, height == %d\n", nr, width, height); + + redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token); + +#if 1 + if ((((door_state & door_token) & DOOR_OPEN) && + (width < 0 || height < 0)) || + (((door_state & door_token) & DOOR_CLOSE) && + (width >= g->width && height >= g->height))) + door_part_done[nr] = TRUE; +#else + if ((((door_state & door_token) & DOOR_OPEN) && + (width < 0 || height < 0)) || + (((door_state & door_token) & DOOR_CLOSE) && + ((pos->step_xoffset != 0 && width >= g->width) || + (pos->step_yoffset != 0 && height >= g->height)))) + door_part_done[nr] = TRUE; +#endif + } + + if (!(door_state & DOOR_NO_DELAY)) + { + BackToFront(); + + if (game_status == GAME_MODE_MAIN) + DoAnimation(); + + WaitUntilDelayReached(&door_delay, door_delay_value); + + current_move_delay += max_step_delay; + } + + door_part_done_all = TRUE; + + for (i = 0; i < MAX_DOOR_PARTS; i++) + if (!door_part_done[i]) + door_part_done_all = FALSE; + + if (door_part_done_all) + break; + } + } + + // redraw_mask |= REDRAW_ALL; + + if (door_state & DOOR_ACTION_1) + door1 = door_state & DOOR_ACTION_1; + if (door_state & DOOR_ACTION_2) + door2 = door_state & DOOR_ACTION_2; + + return (door1 | door2); +} + +#else + +// ========== OLD ============================================================== + unsigned int MoveDoor(unsigned int door_state) { static int door1 = DOOR_OPEN_1; @@ -5371,6 +6013,11 @@ unsigned int MoveDoor(unsigned int door_state) GC gc_right = bm_right->stored_clip_gc; #endif + int classic_dxsize = 100; + int classic_dysize = 280; + boolean classic_door_1_size = (DXSIZE == classic_dxsize && + DYSIZE == classic_dysize); + if (door_1.anim_mode & ANIM_STATIC_PANEL) { BlitBitmap(bitmap_db_door, drawto, @@ -5383,7 +6030,10 @@ unsigned int MoveDoor(unsigned int door_state) DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2, DXSIZE, DYSIZE - p / 2, DX, DY); +#if 1 + // printf("::: p == %d\n", p); ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2); +#endif } if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE) @@ -5460,7 +6110,7 @@ unsigned int MoveDoor(unsigned int door_state) dst2_x, dst2_y); #endif } - else if (x <= DXSIZE) /* ANIM_DEFAULT */ + else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */ { int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0); @@ -5511,6 +6161,7 @@ unsigned int MoveDoor(unsigned int door_state) BlitBitmapMasked(bm_right, drawto, src1_x, src1_y + ypos4, width, height2 - j, dst1_x, dst1_y + ypos4 + j); + #else int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1; int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1; @@ -5603,6 +6254,11 @@ unsigned int MoveDoor(unsigned int door_state) GC gc_right = bm_right->stored_clip_gc; #endif + int classic_vxsize = 100; + int classic_vysize = 100; + boolean classic_door_2_size = (VXSIZE == classic_vxsize && + VYSIZE == classic_vysize); + if (door_2.anim_mode & ANIM_STATIC_PANEL) { BlitBitmap(bitmap_db_door, drawto, @@ -5692,7 +6348,7 @@ unsigned int MoveDoor(unsigned int door_state) dst2_x, dst2_y); #endif } - else if (x <= VXSIZE) /* ANIM_DEFAULT */ + else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */ { int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0); @@ -5803,6 +6459,8 @@ unsigned int MoveDoor(unsigned int door_state) return (door1 | door2); } +#endif + void DrawSpecialEditorDoor() { #if 1