Logo Search packages:      
Sourcecode: xconq version File versions  Download package

macdesign.c

/* Game designer handling for the Mac interface to Xconq.
   Copyright (C) 1992-1998 Stanley T. Shebs.

Xconq is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.  See the file COPYING. */

#include "conq.h"
#define make_raw_wind(d,f) (((f) << 3) | (d))
#include "macconq.h"

#ifdef DESIGNERS

#define numtooltypes 12

static void init_design_cursors(void);
static void create_design_window(void);
static void draw_design_window_tool(enum tooltype tool);
static void mark_allowed_unit_types(void);
static void mark_allowed_sides(void);
static void feature_rename_dialog(Feature *feature);
static void paint_on_drag(Map *map, int h0, int v0, int mods);
static void border_on_drag(Map *map, int h0, int v0, int mods, int paintmode);
static void connect_on_drag(Map *map, int h0, int v0, int mods, int paintmode);
static void designer_reshape_dialog(Module *module);

extern MenuHandle featuremenu;

extern short *feature_menu_fids;

WindowPtr designwin = nil;

ControlHandle ttypepopup = nil;
ControlHandle utypepopup = nil;
ControlHandle mtypepopup = nil;
ControlHandle sidepopup = nil;
ControlHandle feature_add_button = nil;
ControlHandle feature_remove_button = nil;
ControlHandle feature_edit_button = nil;
ControlHandle featurepopup = nil;

CursHandle paintcursors[numtooltypes];
CursHandle bordpaintor;
CursHandle connpaintor;
CursHandle coatpaintor;

/* This is the number of tools actually used. */

short numtoolsused = 0;

/* This is the width and height of each design tool's entry. */

short dtoolw = 120;
short dtoolh = 36;

/* The type of designer tool currently in use. */

enum tooltype tooltype = notool;

/* All the state of the designer palette. */

short curbrushradius;
short curttype;
short curbgttype;
short curdepth = 1;
short curutype;
short cursidenumber;
short curmtype;
short curmamount;
short curfid;
Feature *curfeature;
short curelevation;
short curtemperature;
short curcloudtype;
short curcloudbottom;
short curcloudheight;
short curwinddir;
short curwindforce;
short curtview;
short curuview;

short paintcontrolmode;

/* These are globals used in drag painting. */

short painttype;
short paintpeop;
short paintctrl;
short paintfid;
short painttview;
short paintuview = FALSE;  /* need a checkbox for this eventually */

short enabledtooltype[12];

void
enable_designing(int forsure)
{
      Map *map;
      extern int compromised;

      if (dside == NULL || dside->designer)
        return;
      if (!forsure && !compromised) {
            switch (CautionAlert(aConfirmDesign, nil)) {
                  case aiConfirmDesignOK:
                        break;
                  case aiConfirmDesignCancel:
                        return;
            }
      }
      /* Actually change designer status, this will call back to alter displays. */
      net_become_designer(dside);
      /* Create and add the designer's palette. */
      show_design_window();
      /* This is necessary in order to enable closeups that have no map 
      or vp associated with them. Also needed to permit the designer to 
      select an enemy unit. */
      dside->see_all = TRUE;
      /* Force all maps to see_all; designer can disable manually if
         desired. */
      for_all_maps(map) {
            if (!map->see_all) {
                  map->see_all = TRUE;
                  map->vp->show_all = TRUE;
                  force_update(map->window);
            }
      }
}

void
disable_designing()
{
      Map *map;

      if (dside == NULL || !dside->designer)
        return;
      /* Hide (but don't destroy) the designer's palette. */
      if (designwin != nil) {
            close_window(designwin);
      }
      /* Actually change designer status, this will call back to alter all displays. */
      net_become_nondesigner(dside);
#if 0 
      /* Set maps back to old see_all state if necessary. */
      if (!dside->see_all) {
            for_all_maps(map) {
                  map->see_all = FALSE;
                  /* Note that we have to update all maps, because a designer's
                     no-see_all map draws unseen areas grayed out. */
                  force_update(map->window);
            }
      }
#else
      /* Set dside->see-all to whatever was true for the frontmap or to
      true by default. */
      if (frontmap)
            dside->see_all = frontmap->see_all;
      else  dside->see_all = TRUE;
      for_all_maps(map) {
            map->see_all = dside->see_all;
            force_update(map->window);
      }
#endif
}

/* Each type of design tool has a distinct cursor. */

void
init_design_cursors()
{
      paintcursors[terraintool] = GetCursor(cCell);
      bordpaintor = GetCursor(cBord);
      connpaintor = GetCursor(cConn);
      coatpaintor = GetCursor(cCoat);
      paintcursors[unittool] = GetCursor(cUnit);
      paintcursors[peopletool] = GetCursor(cPeople);
      paintcursors[materialtool] = GetCursor(cMaterial);
      paintcursors[featuretool] = GetCursor(cFeature);
      paintcursors[elevationtool] = GetCursor(cElevation);
      paintcursors[temperaturetool] = GetCursor(cTemperature);
      paintcursors[cloudstool] = GetCursor(cClouds);
      paintcursors[windstool] = GetCursor(cWinds);
      paintcursors[viewtool] = GetCursor(cView);
}

/* Adjust the cursor to reflect the current designer tool. */

CursHandle
adjust_designer_cursor(Point mouse, RgnHandle region)
{
      if (tooltype == terraintool && !t_is_cell(curttype)) {
            switch (t_subtype(curttype)) {
                  case bordersubtype:
                        return bordpaintor;
                  case connectionsubtype:
                        return connpaintor;
                  case coatingsubtype:
                        return coatpaintor;
                  default:
                        terrain_subtype_warning("cursor adjust", curttype);
                        return nil;
            }
      }
      return paintcursors[tooltype];
}

/* This is the top-level access to bring up the design window, can be called
   anywhere, anytime. */

void
show_design_window()
{
      if (designwin == nil) {
            create_design_window();
      } else       {
            SelectTheWindow(designwin);
            ActivateWindow(designwin, true);
      }
}

/* Create the designer tool window. */

void
create_design_window()
{
      int i;

      if (hasColorQD) {
            designwin = GetNewCWindow(wFloatFixed, NULL, NULL);
      } else {
            designwin = GetNewWindow(wFloatFixed, NULL, NULL);
      }
      SetWTitle(designwin, "\pDesign");
      /* Make the current side be the one with the display. */
      cursidenumber = side_number(dside);
      build_terrain_type_menu();
      build_unit_type_menu();
      build_side_menu();
      build_material_type_menu();
      build_feature_menu();
      ttypepopup = GetNewControl(mTerrainTypes, designwin);
      utypepopup = GetNewControl(mUnitTypes, designwin);
      sidepopup = GetNewControl(mSides, designwin);
      mtypepopup = GetNewControl(mMaterialTypes, designwin);
      featurepopup = GetNewControl(mFeatures, designwin);
      feature_add_button = GetNewControl(cFeatureAddButton, designwin);
      feature_remove_button = GetNewControl(cFeatureRemoveButton, designwin);
      feature_edit_button = GetNewControl(cFeatureEditButton, designwin);
      /* Just put the window at the left edge of the screen. */
      MoveWindow(designwin, 3, 280, true);
      init_design_cursors();
      enabledtooltype[notool] = TRUE;
      enabledtooltype[terraintool] = TRUE;
      enabledtooltype[unittool] = TRUE;
      enabledtooltype[peopletool] = TRUE;
      enabledtooltype[featuretool] = TRUE;
      enabledtooltype[brushsizetool] = TRUE;
      enabledtooltype[materialtool] = any_materials_in_terrain;
      enabledtooltype[elevationtool] = !world_is_flat();
      enabledtooltype[temperaturetool] = any_temp_variation;
      enabledtooltype[cloudstool] = any_clouds;
      enabledtooltype[windstool] = any_wind_variation;
      enabledtooltype[viewtool] = !g_see_all();

      /* Count the number of tools in use and size window accordingly. */
      for (i = 0; i < numtooltypes; ++i) {
            if (enabledtooltype[i])
                ++ numtoolsused;
      }
      SizeWindow(designwin, dtoolw - 1, numtoolsused * dtoolh - 1, 1);

      /* Make this a floating window! */
      MakeFloat(designwin);
      SelectTheWindow(designwin);
}

void
draw_design_window()
{
      int i;
      GrafPtr oldport;

      if (!active_display(dside) || designwin == nil) return;
      GetPort(&oldport);
      SetPort(designwin);
      TextFont(small_font_id);
      TextSize(12);
      /* Draw each tool's palette item. */
      for (i = 0; i < numtooltypes; ++i) {
            draw_design_window_tool(i);
      }
      DrawControls(designwin);
      SetPort(oldport);
}

void
draw_design_window_tool(enum tooltype tool)
{
      int enabled = TRUE, paintable = TRUE, len;
      char *toolname = NULL, *auxtoolname = NULL;
      Rect tmprect, imagerect;
      char imbuf[BUFSIZE];
      Str255 tmpstr;
      int i;

      /* Don't draw unused tools. */
      if (enabledtooltype[tool] == FALSE)
            return;
      SetRect(&tmprect, 0, 0, dtoolw, dtoolh);
      /* Don't include unused tools in offset. */
      for (i = 0; i < tool; ++i) {
            if (enabledtooltype[i] == TRUE)
                 OffsetRect(&tmprect, 0, dtoolh);
      }
      EraseRect(&tmprect);
      /* Confine the image to a square subrect on the left side of the window. */
      imagerect = tmprect;
      imagerect.right = imagerect.left + dtoolh;
      imbuf[0] = '\0';
      switch (tool) {
            case notool:
                  toolname = "Normal";
                  break;
            case terraintool:
                  toolname = t_type_name(curttype);
                  InsetRect(&imagerect, (dtoolh - hws[4]) / 2, (dtoolh - hhs[4]) / 2);
                  /* Only do bg terrain type if painting cell terrain. */
                  if (t_is_cell(curttype)) {
                        auxtoolname = t_type_name(curbgttype);
                        /* bg type is always a cell subtype. */
                        OffsetRect(&imagerect, 3, 3);
                        draw_terrain_sample(designwin, imagerect, curbgttype, 4);
                        OffsetRect(&imagerect, -6, -6);
                  }
                  draw_terrain_sample(designwin, imagerect, curttype, 4);
                  break;
            case unittool:
                  toolname = u_type_name(curutype);
                  InsetRect(&imagerect, (dtoolh - 32) / 2, (dtoolh - 32) / 2);
                  draw_unit_image(designwin, imagerect.left, imagerect.top, 32, 32, curutype, cursidenumber, 
                                                (frontmap ? frontmap->sidecolors : default_sidecolors) , 0, 0,
                                                (frontmap ? frontmap->draw_emblems : default_draw_emblems));
                  /* Gray out the unit if not allowed for the current side. */
                  paintable = type_allowed_on_side(curutype, side_n(cursidenumber));
                  break;
            case peopletool:
                  toolname = shortest_side_title(side_n(cursidenumber), spbuf);
                  if (paintcontrolmode) {
                        strcpy(tmpbuf, "(");
                        strcat(tmpbuf, toolname);
                        strcat(tmpbuf, " ctrl)");
                        strcpy(spbuf, tmpbuf);
                        toolname = spbuf;
                  }
                  InsetRect(&imagerect, (dtoolh - 16) / 2, (dtoolh - 16) / 2);
                  draw_side_emblem(designwin, imagerect.left, imagerect.top, 16, 16,
                                           cursidenumber, shadow_emblem);
                  break;
            case featuretool:
                  if (enabledtooltype[featuretool]) {
                        if (curfeature == NULL) {
                              curfeature = find_feature(curfid);
                        }
                        if (curfeature != NULL) {
                              toolname = curfeature->name;
                              auxtoolname = curfeature->typename;
                        } else if (curfid == 0) {
                              toolname = "(no feature)";
                              auxtoolname = " ";
                        } else {
                              sprintf(spbuf, "(#%d)", curfid);
                              toolname = spbuf;
                              auxtoolname = " ";
                        }
                  } else {
                        toolname = "Feature";
                        auxtoolname = " ";
                        enabled = FALSE;
                  }
                  break;
            case brushsizetool:
                  OffsetRect(&imagerect, dtoolh/2 - curbrushradius, dtoolh/2 - curbrushradius);
                  imagerect.right = imagerect.left + curbrushradius + 1;
                  imagerect.bottom = imagerect.top + curbrushradius + 1;
                  FillOval(&imagerect, QDPat(black));
                  if (curbrushradius > 0) {
                        sprintf(imbuf, "%d", curbrushradius);
                  }
                  toolname = "Brush";
                  break;
            case materialtool:
                  if (enabledtooltype[materialtool]) {
                        toolname = m_type_name(curmtype);
                        sprintf(imbuf, "%d", curmamount);
                  } else {
                        toolname = "Material";
                        enabled = FALSE;
                  }
                  break;
            case elevationtool:
                  if (enabledtooltype[elevationtool]) {
                        sprintf(spbuf, "Elev %d", curelevation);
                        toolname = spbuf;
                  } else {
                        toolname = "Elevation";
                        enabled = FALSE;
                  }
                  break;
            case temperaturetool:
                  if (enabledtooltype[temperaturetool]) {
                        sprintf(spbuf, "Temp %dí", curtemperature);
                        toolname = spbuf;
                  } else {
                        toolname = "Temperature";
                        enabled = FALSE;
                  }
                  break;
            case cloudstool:
                  if (enabledtooltype[cloudstool]) {
                        draw_terrain_sample(designwin, imagerect, curbgttype, 4);
                        if (curcloudtype > 0) {
                              InsetRect(&imagerect, (dtoolh - hws[4]) / 2, (dtoolh - hhs[4]) / 2);
                              draw_clouds(imagerect.left, imagerect.top, 4, curcloudtype);
                              sprintf(spbuf, "Cloudy (%d)", curcloudtype);
                              toolname = spbuf;
                        } else {
                              toolname = "Clear";
                        }
                  } else {
                        toolname = "Clouds";
                        enabled = FALSE;
                  }
                  break;
            case windstool:
                  if (enabledtooltype[windstool]) {
                        InsetRect(&imagerect, (dtoolh - hws[4]) / 2, (dtoolh - hhs[4]) / 2);
                        draw_winds(imagerect.left, imagerect.top, 4, make_raw_wind(curwinddir, curwindforce));
                        if (curwindforce > 0) {
                              sprintf(spbuf, "Winds %s, %d", dirnames[curwinddir], curwindforce);
                              toolname = spbuf;
                        } else {
                              toolname = "Calm";
                        }
                  } else {
                        toolname = "Winds";
                        enabled = FALSE;
                  }
                  break;
            case viewtool:
                  if (enabledtooltype[viewtool]) {
                        toolname = "View";
                  } else {
                        toolname = "View";
                        enabled = FALSE;
                  }
                  break;
            default:
                  /* ??? */
                  break;
      }
      /* Draw a (short) text string in the image area. */
      if (strlen(imbuf) > 0) {
            MoveTo(tmprect.left + (dtoolh - StringWidth(tmpstr)) / 2, tmprect.bottom - 5);
            DrawText(imbuf, 0, strlen(imbuf));
      }
      /* (should add to following text-drawing code to account for font changes) */
      if (toolname != NULL) {
            MoveTo(tmprect.left + dtoolh, tmprect.top + (auxtoolname != NULL ? dtoolh / 4 + 4
                                                                                       : dtoolh / 2 + 5));
            /* Let feature name take up both image and tool name space. */
            if (tool == featuretool) {
                  Move(2 - dtoolh, 0);
                  len = min(13, strlen(toolname));
            } else {
                  len = min(8, strlen(toolname));
            }
            DrawText(toolname, 0, len);
      }
      if (auxtoolname != NULL) {
            MoveTo(tmprect.left + dtoolh, tmprect.top + (dtoolh * 3) / 4);
            /* Let feature type take up both image and tool name space. */
            if (tool == featuretool) {
                  Move(2 - dtoolh, 0);
                  len = min(5, strlen(auxtoolname));
            } else {
                  len = min(8, strlen(auxtoolname));
            }
            DrawText(auxtoolname, 0, len);
      }
      if (!paintable) {
            gray_out_rect(&tmprect);
      }
      if (!enabled) {
            gray_out_rect(&tmprect);
      }
      /* Draw gray dividing lines. */
      PenPat(QDPat(gray));
      MoveTo(tmprect.right - 1, tmprect.top);  Line(0, dtoolh);
      MoveTo(tmprect.left, tmprect.bottom - 1);  Line(dtoolw, 0);
      PenNormal();
      /* Highlight the currently selected tool with a heavy outline rect. */
      if (tool == tooltype) {
            tmprect.bottom -= 1;  tmprect.right -= 1;
            InvertRect(&tmprect);
            InsetRect(&tmprect, 3, 3);
            InvertRect(&tmprect);
            if (!enabledtooltype[tool]) {
                  InsetRect(&tmprect, -3, -3);
                  gray_out_rect(&tmprect);
            }
      }
}

/* Respond to a mouse down in the designer's window. */

/* This macro implements cycling of a variable through a set of consecutive
   values, with direction controlled by the shift key.  If the limit is 0,
   then the cycling part is not done. */

#define OPTION_CYCLE(var, lo, hi, n, mods)  \
  if ((hi) - (lo) > 0) {  \
    (var) = (((var) + ((mods) & shiftKey ? -(n) : (n)) - (lo) + ((hi) - (lo))) % ((hi) - (lo))) + (lo);  \
  } else {  \
    (var) = ((var) + ((mods) & shiftKey ? -(n) : (n)));  \
  }

void
do_mouse_down_design(Point mouse, int mods)
{
      int oldtool, poppedtool, newutype, newbgttype, toolchoice, clicked, i;
      Feature *feature;
      Rect tmprect;
      ControlHandle control;
      long choice;
      extern int nextfid;

      tmprect.left = 0;  tmprect.right = dtoolw;
      oldtool = poppedtool = tooltype;
      /* Find the box that was clicked. */
      clicked = mouse.v / dtoolh;
      toolchoice = 0;
      /* Convert it into toolchoice. */ 
      for(toolchoice = 0; toolchoice < numtooltypes; toolchoice++) {
            if (toolchoice == clicked && enabledtooltype[toolchoice] == TRUE)
                  break;
            /* Skip disabled tooltypes. */
             if (enabledtooltype[toolchoice] == FALSE)
                  ++clicked;
      }
      FindControl(mouse, designwin, &control);
      if (control == ttypepopup) {
            TrackControl(control, mouse, (void *) -1);
            choice = LoWord(GetCtlValue(control));
            if (choice > 0)
              curttype = choice - 1;
            poppedtool = terraintool;
      } else if (control == utypepopup) {
            mark_allowed_unit_types();
            TrackControl(control, mouse, (void *) -1);
            choice = LoWord(GetCtlValue(control));
            if (choice > 0)
              curutype = choice - 1;
            poppedtool = unittool;
      } else if (control == sidepopup) {
            mark_allowed_sides();
            TrackControl(control, mouse, (void *) -1);
            choice = LoWord(GetCtlValue(control));
            if (choice > 0) {
                  cursidenumber = choice - 1;
                  if (cursidenumber > numsides)
                    cursidenumber = 0;
            }
            poppedtool = peopletool;
      } else if (control == mtypepopup) {
            TrackControl(control, mouse, (void *) -1);
            choice = LoWord(GetCtlValue(control));
            if (choice > 0)
              curmtype = choice - 1;
            poppedtool = materialtool;
      } else if (control == featurepopup) {
            TrackControl(control, mouse, (void *) -1);
            choice = LoWord(GetCtlValue(control));
            if (choice > 0) {
                  curfid = feature_menu_fids[choice - 1];
                  curfeature = find_feature(curfid);
            }
            poppedtool = featuretool;
      } else if (control == feature_add_button) {
            sprintf(spbuf, "%d", nextfid);
            feature = net_create_feature("feature", copy_string(spbuf));
            if (feature != NULL) {
                  curfeature = feature;
                  curfid = feature->id;
                  feature_rename_dialog(feature);
                  build_feature_menu();
            }
            poppedtool = featuretool;
      } else if (control == feature_remove_button) {
            net_destroy_feature(curfeature);
            /* Fall back to a known valid current feature. */
            curfeature = NULL;
            curfid = 0;
            build_feature_menu();
      } else if (control == feature_edit_button) {
            feature_rename_dialog(curfeature);
            build_feature_menu();
            poppedtool = featuretool;
      } else if (enabledtooltype[toolchoice]) {
            /* Any other click selects the tool. */
            if (toolchoice != brushsizetool)
              tooltype = toolchoice;
            /* Now handle any shortcuts. */
            switch (toolchoice) {
                  case notool:
                        break;
                  case terraintool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click cycle through all
                                 the "foreground" terrain types. */
                              OPTION_CYCLE(curttype, 0, numttypes, 1, mods);
                        } else if ((mods & cmdKey) && t_is_cell(curttype)) {
                              /* Cmd-click and Cmd-Shift-click cycle through all
                                 the "background" terrain types. */
                              newbgttype = curbgttype;
                              do {
                                    OPTION_CYCLE(newbgttype, 0, numttypes, 1, mods);
                                    if (newbgttype == curbgttype)
                                      break;
                              } while (!t_is_cell(newbgttype));
                              curbgttype = newbgttype;
                        }
                        break;
                  case unittool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click cycle through all
                                 the types allowed for the current side. */
                              newutype = curutype;
                              do {
                                    OPTION_CYCLE(newutype, 0, numutypes, 1, mods);
                                    if (newutype == curutype) break;
                              } while (!type_allowed_on_side(newutype, side_n(cursidenumber)));
                              curutype = newutype;
                        }
                        break;
                  case peopletool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click cycle around all the sides. */
                              OPTION_CYCLE(cursidenumber, 0, numsides + 1, 1, mods);
                        } else if (mods & cmdKey) {
                              paintcontrolmode = !paintcontrolmode;
                        }
                        break;
                  case featuretool:
                        if (mods & optionKey && nextfid > 1) {
                              /* Option-click and Option-Shift-click cycle around the features. */
                              OPTION_CYCLE(curfid, 0, nextfid, 1, mods);
                              curfeature = find_feature(curfid);
                        }
                        break;
                  case brushsizetool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click cycle through brush sizes. */
                              OPTION_CYCLE(curbrushradius, 0, 100, 1, mods);
                        }
                        break;
                  case materialtool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click cycle around amounts. */
                              OPTION_CYCLE(curmamount, 0, 10000, 1, mods);
                        } else if (mods & cmdKey) {
                              /* Command-click and Command-Shift-click adjust by 10. */
                              OPTION_CYCLE(curmamount, 0, 10000, 10, mods);
                        }
                        break;
                  case elevationtool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click adjust the elevation. */
                              OPTION_CYCLE(curelevation, minelev, maxelev + 1, 1, mods);
                        } else if (mods & cmdKey) {
                              /* Command-click and Command-Shift-click adjust by 10. */
                              OPTION_CYCLE(curelevation, minelev, maxelev + 1, 10, mods);
                        }
                        break;
                  case temperaturetool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click adjust the temp. */
                              OPTION_CYCLE(curtemperature, mintemp, maxtemp + 1, 1, mods);
                        } else if (mods & cmdKey) {
                              /* Command-click and Command-Shift-click adjust by 10. */
                              OPTION_CYCLE(curtemperature, mintemp, maxtemp + 1, 10, mods);
                        }
                        break;
                  case cloudstool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click adjust the cloud type. */
                              OPTION_CYCLE(curcloudtype, 0, 4, 1, mods);
                        }
                        break;
                  case windstool:
                        if (mods & optionKey) {
                              /* Option-click and Option-Shift-click adjust the wind force. */
                              OPTION_CYCLE(curwindforce, minwindforce, maxwindforce, 1, mods);
                        } else if (mods & cmdKey) {
                              /* Cmd-click and Cmd-Shift-click adjust the direction. */
                              OPTION_CYCLE(curwinddir, 0, NUMDIRS, 1, mods);
                        }
                        break;
                  case viewtool:
                        /* Nothing to do? */
                        break;
                  default:
                        break;
            }
      }
      /* Draw the old and new tools. */
      if (oldtool != tooltype) {
            draw_design_window_tool(oldtool);
      }
      if (poppedtool != tooltype) {
            draw_design_window_tool(poppedtool);
      }
      draw_design_window_tool(tooltype);
      if (toolchoice != tooltype)
        draw_design_window_tool(toolchoice);
      /* As a special case, redraw the unit tool if the side tool was touched. */
      if (tooltype == peopletool || poppedtool == peopletool) {
            draw_design_window_tool(unittool);
      }
      /* (should only draw controls in relevant tools - restrict region?) */
      DrawControls(designwin);
}

void
mark_allowed_unit_types()
{
      Side *side = side_n(cursidenumber);
      int u;

      for_all_unit_types(u) {
            EnableItem(utypemenu, u + 1);
            SetItemMark(utypemenu, u + 1,
                              (type_allowed_on_side(u, side) ? diamondMark : noMark));
      }
}

void
mark_allowed_sides()
{
      Side *side;

      for_all_sides(side) {
            EnableItem(sidemenu, side_number(side) + 1);
            SetItemMark(sidemenu, side_number(side) + 1,
                              (type_allowed_on_side(curutype, side) ? diamondMark : noMark));
      }
}

void
feature_rename_dialog(Feature *feature)
{
      short done = FALSE, ditem;
      char *newtypename, *newname;
      Str255 tmpstr;
      DialogPtr win;
      short itemtype;  Handle itemhandle;  Rect itemrect;

      if (feature == NULL)
        return;
      win = GetNewDialog(dFeatureRename, NULL, (DialogPtr) -1L);
      /* Seed the text items with the original names. */
      newtypename = feature->typename;
      if (newtypename == NULL)
        newtypename = "";
      GetDItem(win, diFeatureRenameType, &itemtype, &itemhandle, &itemrect);
      c2p(newtypename, tmpstr);
      SetIText(itemhandle, tmpstr);
      newname = feature->name;
      if (newname == NULL)
        newname = "";
      GetDItem(win, diFeatureRenameName, &itemtype, &itemhandle, &itemrect);
      c2p(newname, tmpstr);
      SetIText(itemhandle, tmpstr);
      ShowWindow(win);
      while (!done) {
            SetCursor(&QD(arrow));
            ModalDialog(NULL, &ditem);
            switch (ditem) {
                  case diRenameOK:
                        GetDItem(win, diFeatureRenameType, &itemtype, &itemhandle, &itemrect);
                        net_set_feature_type_name(feature, get_string_from_item(itemhandle));
                        GetDItem(win, diFeatureRenameName, &itemtype, &itemhandle, &itemrect);
                        net_set_feature_name(feature, get_string_from_item(itemhandle));
                        /* Fall into next case. */
                  case diRenameCancel:
                        done = TRUE;
                        break;
            }
      }
      DisposeDialog(win);
      update_all_map_windows();
}

/* Handling of mousedowns in the map when designing. */

void
apply_designer_tool(Map *map, int h, int v, int mods)
{
      int x, y, dir;
      int oldt, oldpeop, oldctrl, oldfid, oldtview, olduview;
      Unit *unit;

      m_nearest_boundary(map, h, v, &x, &y, &dir);
      switch (tooltype) {
            case terraintool:
                  /* Dispatch on terrain subtype. */
                  switch (t_subtype(curttype)) {
                        case cellsubtype:
                              /* Choose to paint fg or bg type, depending on what's already
                                 there. */
                              oldt = terrain_at(x, y);
                              painttype = (curttype == oldt ? curbgttype : curttype);
                              net_paint_cell(dside, x, y, curbrushradius, painttype);
                              paint_on_drag(map, h, v, mods);
                              break;
                        case bordersubtype:
                              /* Toggle border on first mouse down. */
                              net_paint_border(dside, x, y, dir, curttype, -1);
                              /* Dragging then adds or removes, depending on toggle's result. */
                              border_on_drag(map, h, v, mods, border_at(x, y, dir, curttype));
                              break;
                        case connectionsubtype:
                              /* Toggle connection on first mouse down. */
                              net_paint_connection(dside, x, y, dir, curttype, -1);
                              /* Dragging then adds or removes, depending on toggle's result. */
                              connect_on_drag(map, h, v, mods, connection_at(x, y, dir, curttype));
                              break;
                        case coatingsubtype:
                              net_paint_coating(dside, x, y, curbrushradius, curttype, curdepth);
                              paint_on_drag(map, h, v, mods);
                              break;
                        default:
                              terrain_subtype_warning("apply tool", curttype);
                              break;
                  }
                  return;
            case unittool:
                  /* A last check, should never(?) fail. */
                  if (!type_allowed_on_side(curutype, side_n(cursidenumber))) {
                        beep();
                        return;
                  }
                  unit = net_designer_create_unit(dside, curutype, cursidenumber, x, y);
                  if (unit != NULL) {
                        /* Make the new unit automatically be the current selection. */
                        unselect_all(map);
                        select_unit_on_map(map, unit);
                        draw_selections_at(map, unit->x, unit->y);
                  } else {
                        /* Beep if the creation failed for some reason. */
                        beep();
                  }
                  /* No use for drag painting here, unlike most other tools. */
                  break;
            case peopletool:
                  if (paintcontrolmode) {
                        /* Paint side or clear, inverting from what is already here. */
                        oldctrl = control_side_at(x, y);
                        paintctrl = (cursidenumber == oldctrl ? NOCONTROL : cursidenumber);
                        net_paint_control(dside, x, y, curbrushradius, paintctrl);
                  } else {
                        /* Paint people or clear, inverting from what is already here. */
                        oldpeop = people_side_at(x, y);
                        paintpeop = (cursidenumber == oldpeop ? NOBODY : cursidenumber);
                        net_paint_people(dside, x, y, curbrushradius, paintpeop);
                  }
                  paint_on_drag(map, h, v, mods);
                  break;
            case featuretool:
                  oldfid = raw_feature_at(x, y);
                  paintfid = (curfid == oldfid ? 0 : curfid);
                  net_paint_feature(dside, x, y, curbrushradius, paintfid);
                  paint_on_drag(map, h, v, mods);
                  break;
            case materialtool:
                  net_paint_material(dside, x, y, curbrushradius, curmtype, curmamount);
                  paint_on_drag(map, h, v, mods);
                  break;
            case elevationtool:
                  net_paint_elevation(dside, x, y, curbrushradius, 0, curelevation, 0);
                  paint_on_drag(map, h, v, mods);
                  break;
            case temperaturetool:
                  net_paint_temperature(dside, x, y, curbrushradius, curtemperature);
                  paint_on_drag(map, h, v, mods);
                  break;
            case cloudstool:
                  net_paint_clouds(dside, x, y, curbrushradius, curcloudtype, curcloudbottom, curcloudheight);
                  paint_on_drag(map, h, v, mods);
                  break;
            case windstool:
                  net_paint_winds(dside, x, y, curbrushradius, curwinddir, curwindforce);
                  paint_on_drag(map, h, v, mods);
                  break;
            case viewtool:
                  if (dside->terrview == NULL || dside->unit_views == NULL)
                    break;
                  oldtview = terrain_view(dside, x, y);
                  painttview = (oldtview == UNSEEN ? buildtview(terrain_at(x, y)) : UNSEEN);
                  net_paint_view(dside, x, y, curbrushradius, painttview, paintuview);
                  /* (should paint other view layers also) */
                  paint_on_drag(map, h, v, mods);
                  break;
            default:
                  beep();
      }
}

void
paint_on_drag(Map *map, int h0, int v0, int mods)
{
      Point pt0, pt1, newmouse;
      int drawn = FALSE, x, y;
      Rect tmprect;

      SetPt(&pt0, h0, v0);
      SetPt(&pt1, h0, v0);
      SetRect(&tmprect, h0, v0, h0, v0);
      while (WaitMouseUp()) {
            GetMouse(&newmouse);
            if (!EqualPt(pt1, newmouse) /* && PtInRect(newmouse, &(map->window->portRect)) */) {
                  pt1 = newmouse;
                  if (m_nearest_cell(map, pt1.h, pt1.v, &x, &y)) {
                        switch (tooltype) {
                              case terraintool:
                                    /* Dispatch on terrain subtype. */
                                    switch (t_subtype(curttype)) {
                                          /* This sort of drag-paint only works for area fillers,
                                             bords/conns use different algorithm. */
                                          case cellsubtype:
                                                net_paint_cell(dside, x, y, curbrushradius, painttype);
                                                break;
                                          case coatingsubtype:
                                                net_paint_coating(dside, x, y, curbrushradius, curttype, curdepth);
                                                break;
                                    }
                                    break;
                              case peopletool:
                                    if (paintcontrolmode)
                                      net_paint_control(dside, x, y, curbrushradius, paintctrl);
                                    else
                                      net_paint_people(dside, x, y, curbrushradius, paintpeop);
                                    break;
                              case materialtool:
                                    net_paint_material(dside, x, y, curbrushradius, curmtype, curmamount);
                                    break;
                              case featuretool:
                                    net_paint_feature(dside, x, y, curbrushradius, paintfid);
                                    break;
                              case elevationtool:
                                    net_paint_elevation(dside, x, y, curbrushradius, 0, curelevation, 0);
                                    break;
                              case temperaturetool:
                                    net_paint_temperature(dside, x, y, curbrushradius, curtemperature);
                                    break;
                              case cloudstool:
                                    net_paint_clouds(dside, x, y, curbrushradius, curcloudtype, curcloudbottom, curcloudheight);
                                    break;
                              case windstool:
                                    net_paint_winds(dside, x, y, curbrushradius, curwinddir, curwindforce);
                                    break;
                              case viewtool:
                                    /* If we're painting "seen" area, always set it to be the terrain
                                       etc actually at the given location. */
                                    if (painttview != UNSEEN)
                                      painttview = buildtview(terrain_at(x, y));
                                    Dprintf("painttview is %d\n", painttview);
                                    net_paint_view(dside, x, y, curbrushradius, painttview, paintuview);
                                    /* (should paint other view layers also) */
                                    break;
                              default:
                                    break;
                        }
                  }
            }
      }
}

void
border_on_drag(Map *map, int h0, int v0, int mods, int paintmode)
{
      Point pt0, pt1, newmouse;
      int drawn = FALSE, x, y, dir;
      Rect tmprect;

      SetPt(&pt0, h0, v0);
      SetPt(&pt1, h0, v0);
      SetRect(&tmprect, h0, v0, h0, v0);
      while (WaitMouseUp()) {
            GetMouse(&newmouse);
            if (!EqualPt(pt1, newmouse) /* && PtInRect(newmouse, &(map->window->portRect)) */) {
                  pt1 = newmouse;
                  m_nearest_boundary(map, pt1.h, pt1.v, &x, &y, &dir);
                  if (inside_area(x, y)) {
                        net_paint_border(dside, x, y, dir, curttype, paintmode);
                  }
            }
      }
}

void
connect_on_drag(Map *map, int h0, int v0, int mods, int paintmode)
{
      Point pt0, pt1, newmouse;
      int drawn = FALSE, x, y, dir;
      Rect tmprect;

      SetPt(&pt0, h0, v0);
      SetPt(&pt1, h0, v0);
      SetRect(&tmprect, h0, v0, h0, v0);
      while (WaitMouseUp()) {
            GetMouse(&newmouse);
            if (!EqualPt(pt1, newmouse) /* && PtInRect(newmouse, &(map->window->portRect)) */) {
                  pt1 = newmouse;
                  m_nearest_boundary(map, pt1.h, pt1.v, &x, &y, &dir);
                  if (inside_area(x, y)) {
                        net_paint_connection(dside, x, y, dir, curttype, paintmode);
                  }
            }
      }
}

/* This allows the designer to choose which parts of a game to write out. */

int defunitids; /* should be module slot */

void
designer_save_dialog()
{
      int done = FALSE;
      short ditem;
      char namebuf[BUFSIZE];
      Str255 tmpstr;
      Point pnt;
      WindowPtr win;
      Module *module;
    SFReply reply;
      short itemtype;  Handle itemhandle;  Rect itemrect;
      
      win = GetNewDialog(dDesignerSave, NULL, (DialogPtr) -1L);
      module = create_game_module(NULL);
      module->title = "Designer-saved data";
      if (module == NULL) {
            beep();
            return;
      }
      init_module_reshape(module);
      /* Only rarely does the designer not want to compress all the area layers. */
      module->compress_layers = TRUE;
      GetDItem(win, diDesignerSaveCompress, &itemtype, &itemhandle, &itemrect);
      SetCtlValue((ControlHandle) itemhandle, module->compress_layers);
      while (!done) {
            SetCursor(&QD(arrow));
            ModalDialog(NULL, &ditem);
            switch (ditem) {
                  case diDesignerSaveOK:
                        get_string_from_ditem(diDesignerSaveName, namebuf);
                        module->name = copy_string(namebuf);
                        set_flag_from_ditem(diDesignerSaveTypes, module->def_types);
                        set_flag_from_ditem(diDesignerSaveTables, module->def_tables);
                        set_flag_from_ditem(diDesignerSaveGlobals, module->def_globals);
                        set_flag_from_ditem(diDesignerSaveWorld, module->def_world);
                        set_flag_from_ditem(diDesignerSaveAreas, module->def_areas);
                        set_flag_from_ditem(diDesignerSaveAreaTerrain, module->def_area_terrain);
                        set_flag_from_ditem(diDesignerSaveAreaMisc, module->def_area_misc);
                        set_flag_from_ditem(diDesignerSaveAreaWeather, module->def_area_weather);
                        set_flag_from_ditem(diDesignerSaveAreaMaterial, module->def_area_material);
                        set_flag_from_ditem(diDesignerSaveSides, module->def_sides);
                        set_flag_from_ditem(diDesignerSaveSideViews, module->def_side_views);
                        set_flag_from_ditem(diDesignerSavePlayers, module->def_players);
                        set_flag_from_ditem(diDesignerSaveUnits, module->def_units);
                        set_flag_from_ditem(diDesignerSaveUnitIds, defunitids);
                        set_flag_from_ditem(diDesignerSaveUnitProps, module->def_unit_props);
                        set_flag_from_ditem(diDesignerSaveUnitMoves, module->def_unit_acts);
                        set_flag_from_ditem(diDesignerSaveUnitPlans, module->def_unit_plans);
                        set_flag_from_ditem(diDesignerSaveScoring, module->def_scoring);
                        set_flag_from_ditem(diDesignerSaveHistory, module->def_history);
                        set_flag_from_ditem(diDesignerSaveCompress, module->compress_layers);
                        /* Collect the file and path to save to. */
                        SetPt(&pnt, 100, 100);
                        sprintf(spbuf, "%s.g", namebuf);
                        c2p(spbuf, tmpstr);
                        SFPutFile(pnt, "\pSave game data as", tmpstr, /*(DlgHookProcPtr)*/ nil, &reply);
                        if (reply.good) {
                              /* Make the location of the file be the current volume. */
                              SetVol(reply.fName, reply.vRefNum);
                              p2c(((char *) reply.fName), namebuf);
                              module->filename = copy_string(namebuf);
                              SetCursor(*watchcursor);
                              if (!write_game_module(module)) {
                                    run_warning("Couldn't write the module \"%s\"!", module->filename);
                                    /* Don't fall through, might be able to fix by changing save options. */
                                    break;
                              }
                              /* Mark as an Xconq game. */
                              set_game_file_type(module->filename);
                              SetCursor(&QD(arrow));
                        } else {
                              break;
                        }
                        /* Fall through to next case. */
                  case diDesignerSaveCancel:
                        done = TRUE;
                        break;
                  case diDesignerSaveTypes:
                  case diDesignerSaveTables:
                  case diDesignerSaveGlobals:
                  case diDesignerSaveWorld:
                  case diDesignerSaveAreas:
                  case diDesignerSaveAreaTerrain:
                  case diDesignerSaveAreaMisc:
                  case diDesignerSaveAreaWeather:
                  case diDesignerSaveAreaMaterial:
                  case diDesignerSaveSides:
                  case diDesignerSaveSideNames:
                  case diDesignerSaveSideProps:
                  case diDesignerSaveSideViews:
                  case diDesignerSavePlayers:
                  case diDesignerSaveUnits:
                  case diDesignerSaveUnitIds:
                  case diDesignerSaveUnitProps:
                  case diDesignerSaveUnitMoves:
                  case diDesignerSaveUnitPlans:
                  case diDesignerSaveScoring:
                  case diDesignerSaveHistory:
                  case diDesignerSaveCompress:
                        /* Toggle check boxes. */
                        GetDItem(win, ditem, &itemtype, &itemhandle, &itemrect);
                        SetCtlValue((ControlHandle) itemhandle,
                                          !GetCtlValue((ControlHandle) itemhandle));
                        break;
                  case diDesignerSaveModule:
                        /* (should bring up a dialog to set module properties) */
                        break;
                  case diDesignerSaveReshape:
                        /* Bring up *another* modal dialog. */
                        designer_reshape_dialog(module);
                        break;
            }
      }
      DisposeDialog(win);
      update_all_map_windows();
}

/* A special dialog that allows for saving a world of different dimensions than is
   currently being used in the game. */

void
designer_reshape_dialog(Module *module)
{
      int done = FALSE;
      short ditem;
      WindowPtr win;
      Str255 tmpstr;
      short itemtype;  Handle itemhandle;  Rect itemrect;
      
      win = GetNewDialog(dDesignerReshape, NULL, (DialogPtr) -1L);
      while (!done) {
            put_number_into_ditem(diDesignerReshapeOrigWidth, area.width);
            put_number_into_ditem(diDesignerReshapeOrigHeight, area.height);
            put_number_into_ditem(diDesignerReshapeOrigWorld, world.circumference);
            put_number_into_ditem(diDesignerReshapeOrigSubWidth, module->subarea_width);
            put_number_into_ditem(diDesignerReshapeOrigSubHeight, module->subarea_height);
            put_number_into_ditem(diDesignerReshapeOrigSubX, module->subarea_x);
            put_number_into_ditem(diDesignerReshapeOrigSubY, module->subarea_y);
            put_number_into_ditem(diDesignerReshapeOutputSubWidth, module->final_subarea_width);
            put_number_into_ditem(diDesignerReshapeOutputSubHeight, module->final_subarea_height);
            put_number_into_ditem(diDesignerReshapeOutputSubX, module->final_subarea_x);
            put_number_into_ditem(diDesignerReshapeOutputSubY, module->final_subarea_y);
            put_number_into_ditem(diDesignerReshapeOutputWidth, module->final_width);
            put_number_into_ditem(diDesignerReshapeOutputHeight, module->final_height);
            put_number_into_ditem(diDesignerReshapeOutputWorld, module->final_circumference);
/*          put_number_into_ditem(diDesignerReshapeFillTerrain, module->fill_terrain); */
            SetCursor(&QD(arrow));
            ModalDialog(NULL, &ditem);
            switch (ditem) {
                  case diDesignerReshapeOK:
                        get_number_from_ditem(diDesignerReshapeOrigSubWidth, module->subarea_width);
                        get_number_from_ditem(diDesignerReshapeOrigSubHeight, module->subarea_height);
                        get_number_from_ditem(diDesignerReshapeOrigSubX, module->subarea_x);
                        get_number_from_ditem(diDesignerReshapeOrigSubY, module->subarea_y);
                        get_number_from_ditem(diDesignerReshapeOutputSubWidth, module->final_subarea_width);
                        get_number_from_ditem(diDesignerReshapeOutputSubHeight, module->final_subarea_height);
                        get_number_from_ditem(diDesignerReshapeOutputSubX, module->final_subarea_x);
                        get_number_from_ditem(diDesignerReshapeOutputSubY, module->final_subarea_y);
                        get_number_from_ditem(diDesignerReshapeOutputWidth, module->final_width);
                        get_number_from_ditem(diDesignerReshapeOutputHeight, module->final_height);
                        get_number_from_ditem(diDesignerReshapeOutputWorld, module->final_circumference);
/*                      get_number_from_ditem(diDesignerReshapeFillTerrain, module->fill_terrain);  */
                        /* Fall through to next case. */
                  case diDesignerReshapeCancel:
                        done = TRUE;
                        break;
            }
      }
      DisposeDialog(win);
      update_all_map_windows();
}

#endif /* DESIGNERS */

Generated by  Doxygen 1.6.0   Back to index