rnd-20140305-3-src
[rocksndiamonds.git] / src / tools.c
index 5b32c1c2cc83eff3b40b65ebaa1266f18ab34ed0..c0009b4013e74d852eeeec8dabba46579c1691e2 100644 (file)
@@ -58,7 +58,7 @@ static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
 
 struct DoorPartControlInfo
 {
-  int door_nr;
+  int door_token;
   int graphic;
   struct DoorPartPosInfo *pos;
 };
@@ -5326,16 +5326,179 @@ static int compareDoorPartOrderInfo(const void *object1, const void *object2)
   return compare_result;
 }
 
+void InitGraphicCompatibilityInfo_Doors()
+{
+  struct
+  {
+    int door_token;
+    int part_1, part_8;
+    struct DoorInfo *door;
+  }
+  doors[] =
+  {
+    { DOOR_1,  IMG_DOOR_1_GFX_PART_1,  IMG_DOOR_1_GFX_PART_8,  &door_1 },
+    { DOOR_2,  IMG_DOOR_2_GFX_PART_1,  IMG_DOOR_2_GFX_PART_8,  &door_2 },
+
+    { -1,      -1,                     -1,                     NULL    }
+  };
+  struct Rect door_rect_list[] =
+  {
+    { DX, DY, DXSIZE, DYSIZE },
+    { VX, VY, VXSIZE, VYSIZE }
+  };
+  int i, j;
+
+  for (i = 0; doors[i].door_token != -1; i++)
+  {
+    int door_token = doors[i].door_token;
+    int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
+    int part_1 = doors[i].part_1;
+    int part_8 = doors[i].part_8;
+    int part_2 = part_1 + 1;
+    int part_3 = part_1 + 2;
+    struct DoorInfo *door = doors[i].door;
+    struct Rect *door_rect = &door_rect_list[door_index];
+    boolean door_gfx_redefined = FALSE;
+
+    /* check if any door part graphic definitions have been redefined */
+
+    for (j = 0; door_part_controls[j].door_token != -1; j++)
+    {
+      struct DoorPartControlInfo *dpc = &door_part_controls[j];
+      struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
+
+      if (dpc->door_token == door_token && fi->redefined)
+       door_gfx_redefined = TRUE;
+    }
+
+    /* check for old-style door graphic/animation modifications */
+
+    if (!door_gfx_redefined)
+    {
+      if (door->anim_mode & ANIM_STATIC_PANEL)
+      {
+       door->panel.step_xoffset = 0;
+       door->panel.step_yoffset = 0;
+      }
+
+      if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
+      {
+       struct GraphicInfo *g_part_1 = &graphic_info[part_1];
+       struct GraphicInfo *g_part_2 = &graphic_info[part_2];
+       int num_door_steps, num_panel_steps;
+
+       /* remove door part graphics other than the two default wings */
+
+       for (j = 0; door_part_controls[j].door_token != -1; j++)
+       {
+         struct DoorPartControlInfo *dpc = &door_part_controls[j];
+         struct GraphicInfo *g = &graphic_info[dpc->graphic];
+
+         if (dpc->graphic >= part_3 &&
+             dpc->graphic <= part_8)
+           g->bitmap = NULL;
+       }
+
+       /* set graphics and screen positions of the default wings */
+
+       g_part_1->width  = door_rect->width;
+       g_part_1->height = door_rect->height;
+       g_part_2->width  = door_rect->width;
+       g_part_2->height = door_rect->height;
+       g_part_2->src_x = door_rect->width;
+       g_part_2->src_y = g_part_1->src_y;
+
+       door->part_2.x = door->part_1.x;
+       door->part_2.y = door->part_1.y;
+
+       if (door->width != -1)
+       {
+         g_part_1->width = door->width;
+         g_part_2->width = door->width;
+
+         // special treatment for graphics and screen position of right wing
+         g_part_2->src_x += door_rect->width - door->width;
+         door->part_2.x  += door_rect->width - door->width;
+       }
+
+       if (door->height != -1)
+       {
+         g_part_1->height = door->height;
+         g_part_2->height = door->height;
+
+         // special treatment for graphics and screen position of bottom wing
+         g_part_2->src_y += door_rect->height - door->height;
+         door->part_2.y  += door_rect->height - door->height;
+       }
+
+       /* set animation delays for the default wings and panels */
+
+       door->part_1.step_delay = door->step_delay;
+       door->part_2.step_delay = door->step_delay;
+       door->panel.step_delay  = door->step_delay;
+
+       /* set animation draw order for the default wings */
+
+       door->part_1.sort_priority = 2; /* draw left wing over ... */
+       door->part_2.sort_priority = 1; /*          ... right wing */
+
+       /* set animation draw offset for the default wings */
+
+       if (door->anim_mode & ANIM_HORIZONTAL)
+       {
+         door->part_1.step_xoffset = door->step_offset;
+         door->part_1.step_yoffset = 0;
+         door->part_2.step_xoffset = door->step_offset * -1;
+         door->part_2.step_yoffset = 0;
+
+         num_door_steps = g_part_1->width / door->step_offset;
+       }
+       else    // ANIM_VERTICAL
+       {
+         door->part_1.step_xoffset = 0;
+         door->part_1.step_yoffset = door->step_offset;
+         door->part_2.step_xoffset = 0;
+         door->part_2.step_yoffset = door->step_offset * -1;
+
+         num_door_steps = g_part_1->height / door->step_offset;
+       }
+
+       /* set animation draw offset for the default panels */
+
+       if (door->step_offset > 1)
+       {
+         num_panel_steps = 2 * door_rect->height / door->step_offset;
+         door->panel.start_step = num_panel_steps - num_door_steps;
+       }
+       else
+       {
+         num_panel_steps = door_rect->height / door->step_offset;
+         door->panel.start_step = num_panel_steps - num_door_steps / 2;
+         door->panel.step_delay *= 2;
+       }
+      }
+    }
+  }
+}
+
 void InitDoors()
 {
   int i;
 
-  for (i = 0; door_part_controls[i].door_nr != -1; i++)
+  for (i = 0; door_part_controls[i].door_token != -1; i++)
   {
     struct DoorPartControlInfo *dpc = &door_part_controls[i];
     struct DoorPartOrderInfo *dpo = &door_part_order[i];
 
-    /* fill structure for door part draw order */
+    /* initialize "start_step_opening" and "start_step_closing", if needed */
+    if (dpc->pos->start_step_opening == 0 &&
+       dpc->pos->start_step_closing == 0)
+    {
+      // dpc->pos->start_step_opening = dpc->pos->start_step;
+      dpc->pos->start_step_closing = dpc->pos->start_step;
+    }
+
+    /* fill structure for door part draw order (sorted below) */
     dpo->nr = i;
     dpo->sort_priority = dpc->pos->sort_priority;
 
@@ -5490,6 +5653,7 @@ unsigned int MoveDoor(unsigned int door_state)
   if (door_state & DOOR_ACTION)
   {
     boolean door_panel_drawn[NUM_DOORS];
+    boolean door_part_skip[MAX_DOOR_PARTS];
     boolean door_part_done[MAX_DOOR_PARTS];
     boolean door_part_done_all;
     int num_steps[MAX_DOOR_PARTS];
@@ -5503,9 +5667,10 @@ unsigned int MoveDoor(unsigned int door_state)
     {
       struct DoorPartControlInfo *dpc = &door_part_controls[i];
       struct GraphicInfo *g = &graphic_info[dpc->graphic];
-      int door_token = dpc->door_nr;
+      int door_token = dpc->door_token;
 
-      door_part_done[i] = (!(door_state & door_token) ||
+      door_part_done[i] = FALSE;
+      door_part_skip[i] = (!(door_state & door_token) ||
                           !g->bitmap);
     }
 
@@ -5523,13 +5688,21 @@ unsigned int MoveDoor(unsigned int door_state)
 
     for (i = 0; i < MAX_DOOR_PARTS; i++)
     {
-      struct DoorPartControlInfo *dpc = &door_part_controls[i];
-      struct GraphicInfo *g = &graphic_info[dpc->graphic];
+      int nr = door_part_order[i].nr;
+      struct DoorPartControlInfo *dpc = &door_part_controls[nr];
       struct DoorPartPosInfo *pos = dpc->pos;
+      struct GraphicInfo *g = &graphic_info[dpc->graphic];
+      int door_token = dpc->door_token;
+      boolean is_panel = DOOR_PART_IS_PANEL(nr);
       int step_xoffset = ABS(pos->step_xoffset);
       int step_yoffset = ABS(pos->step_yoffset);
-      int start_step = pos->start_step;
       int step_delay = pos->step_delay;
+      int current_door_state = door_state & door_token;
+      boolean door_opening = ((current_door_state & DOOR_OPEN)  != 0);
+      boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
+      boolean part_opening = (is_panel ? door_closing : door_opening);
+      int start_step = (part_opening ? pos->start_step_opening :
+                       pos->start_step_closing);
       float move_xsize = (step_xoffset ? g->width  : 0);
       float move_ysize = (step_yoffset ? g->height : 0);
       int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
@@ -5539,13 +5712,13 @@ unsigned int MoveDoor(unsigned int door_state)
                        move_xsteps ? move_xsteps : move_ysteps) - start_step;
       int move_delay = move_steps * step_delay;
 
-      if (door_part_done[i])
+      if (door_part_skip[nr])
        continue;
 
       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_steps[i] = move_steps;
+      num_steps[nr] = move_steps;
 
 #if 0
 #if 0
@@ -5573,6 +5746,8 @@ unsigned int MoveDoor(unsigned int door_state)
 
     for (k = 0; k < num_move_steps; k++)
     {
+      door_part_done_all = TRUE;
+
       for (i = 0; i < NUM_DOORS; i++)
        door_panel_drawn[i] = FALSE;
 
@@ -5580,22 +5755,25 @@ unsigned int MoveDoor(unsigned int door_state)
       {
        int nr = door_part_order[i].nr;
        struct DoorPartControlInfo *dpc = &door_part_controls[nr];
-       int door_token = dpc->door_nr;
+       struct DoorPartPosInfo *pos = dpc->pos;
+       struct GraphicInfo *g = &graphic_info[dpc->graphic];
+       int door_token = dpc->door_token;
        int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
        boolean is_panel = DOOR_PART_IS_PANEL(nr);
-       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];
        Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
        int current_door_state = door_state & door_token;
        boolean door_opening = ((current_door_state & DOOR_OPEN)  != 0);
-       boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
-       boolean mode_opening = (is_panel ? door_closing : door_opening);
+       boolean door_closing = !door_opening;
+       boolean part_opening = (is_panel ? door_closing : door_opening);
+       boolean part_closing = !part_opening;
+       int start_step = (part_opening ? pos->start_step_opening :
+                         pos->start_step_closing);
        int step_delay = pos->step_delay;
        int step_factor = step_delay / max_step_delay;
        int k1 = (step_factor ? k / step_factor + 1 : k);
-       int k2 = (mode_opening ? k1 : num_steps[nr] - k1);
+       int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
        int kk = (k2 < 0 ? 0 : k2);
        int src_x, src_y, src_xx, src_yy;
        int dst_x, dst_y, dst_xx, dst_yy;
@@ -5613,12 +5791,18 @@ unsigned int MoveDoor(unsigned int door_state)
 
 #if 0
        // !!! TEST !!! 
-       if (nr != 0)
+       if (nr != 16 && nr != 0)
          continue;
 #endif
 
 #if 0
-       if (door_part_done[nr])
+       // !!! TEST !!! 
+       if (!is_panel)
+         continue;
+#endif
+
+#if 1
+       if (door_part_skip[nr])
          continue;
 #endif
 
@@ -5713,6 +5897,14 @@ unsigned int MoveDoor(unsigned int door_state)
        dst_x = door_rect->x + dst_xx;
        dst_y = door_rect->y + dst_yy;
 
+#if 0
+       if (DOOR_PART_IS_PANEL(nr))
+       {
+         printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
+                width, height, g->width, g->height, src_x, src_y);
+       }
+#endif
+
        if (width  >= 0 && width  <= g->width &&
            height >= 0 && height <= g->height)
        {
@@ -5744,9 +5936,24 @@ unsigned int MoveDoor(unsigned int door_state)
 
        redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
 
+#if 1
+       if ((part_opening && (width < 0         || height < 0)) ||
+           (part_closing && (width >= g->width && height >= g->height)))
+         door_part_done[nr] = TRUE;
+#else
        if ((door_opening && (width < 0         || height < 0)) ||
            (door_closing && (width >= g->width && height >= g->height)))
          door_part_done[nr] = TRUE;
+#endif
+
+       // continue door part animations, but not panel after door has closed
+       if (!door_part_done[nr] && !(is_panel && door_closing))
+         door_part_done_all = FALSE;
+
+#if 0
+       if (!door_part_done[nr])
+         printf("::: k == %d, nr == %d\n", k, nr);
+#endif
       }
 
       if (!(door_state & DOOR_NO_DELAY))
@@ -5761,14 +5968,18 @@ unsigned int MoveDoor(unsigned int door_state)
        current_move_delay += max_step_delay;
       }
 
+#if 0
       door_part_done_all = TRUE;
 
       for (i = 0; i < MAX_DOOR_PARTS; i++)
-       if (!door_part_done[i])
+       if (!door_part_done[i] &&
+           !(DOOR_PART_IS_PANEL(i) && door_closing))
          door_part_done_all = FALSE;
-
+#endif
+#if 1
       if (door_part_done_all)
        break;
+#endif
     }
   }
 
@@ -5777,6 +5988,12 @@ unsigned int MoveDoor(unsigned int door_state)
   if (door_state & DOOR_ACTION_2)
     door2 = door_state & DOOR_ACTION_2;
 
+#if 0
+  printf("::: DOORS DONE %08x\n", door_state);
+  Delay(3000);
+  printf("::: GO!\n");
+#endif
+
   return (door1 | door2);
 }
 
@@ -6531,8 +6748,8 @@ void CreateToolButtons()
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_INFO_TEXT, toolbutton_info[i].infotext,
-                     GDI_X, dx + pos->x,
-                     GDI_Y, dy + pos->y,
+                     GDI_X, dx + GDI_ACTIVE_POS(pos->x),
+                     GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
                      GDI_WIDTH, gfx->width,
                      GDI_HEIGHT, gfx->height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
@@ -6691,8 +6908,8 @@ void CreateToolButtons()
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_INFO_TEXT, toolbutton_info[i].infotext,
-                     GDI_X, DX + toolbutton_info[i].x,
-                     GDI_Y, DY + toolbutton_info[i].y,
+                     GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
+                     GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
                      GDI_WIDTH, toolbutton_info[i].width,
                      GDI_HEIGHT, toolbutton_info[i].height,
                      GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
@@ -11165,7 +11382,9 @@ void ChangeViewportPropertiesIfNeeded()
     InitGfxBuffers();
 #endif
 
+#if 0
     if (gfx_game_mode == GAME_MODE_MAIN)
+#endif
     {
 #if 1
       init_gadgets_and_toons = TRUE;