home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / REND386 / JIREND / KEYBOARD.C < prev    next >
C/C++ Source or Header  |  1993-04-11  |  37KB  |  1,338 lines

  1. /* Keyboard routines */
  2.   
  3. /* Written by Bernie Roehl, July 1992 */
  4.   
  5. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  6.    May be freely used to write software for release into the public domain;
  7.    all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  8.    for permission to incorporate any part of this software into their
  9.    products!
  10.  */
  11.   
  12. #include <stdlib.h>
  13. #include <stdio.h>
  14. #include <dos.h>
  15. #include <time.h>    /* time(), ctime() */
  16. #include <string.h>
  17. #include <math.h>
  18. #include <bios.h>
  19. #include <conio.h>
  20. #include <ctype.h>
  21.   
  22. #include "rend386.h"
  23. #include "intmath.h"
  24. #include "plg.h"
  25. #include "pointer.h"
  26. #include "userint.h"
  27. #include "splits.h"
  28. #include "cursor.h"
  29. #include "segio.h"
  30. #include "eprint.h"
  31.  
  32. //----------------------------------------------------------  
  33. extern STEREO default_stereo;
  34. extern manip_2D_avail;
  35.   
  36. extern int sl_xflip, sl_xoff;
  37. extern long sl_left, sl_top, sl_right, sl_bottom;
  38. extern int sr_xflip, sr_xoff;
  39. extern long sr_left, sr_top, sr_right, sr_bottom;
  40. extern float sl_xrot, sr_xrot;
  41.   
  42. extern long latitude,longitude,center_roll;
  43. extern long center_x,center_y,center_z,center_d;
  44.   
  45. extern char *progname;
  46.   
  47. extern OBJECT *where_split_screen_pt(int *pol, int *vert, int x, int y);
  48.   
  49. extern int redraw, review, reframe, running, do_horizon;
  50. extern OBJLIST *objlist;
  51. extern long spacestep;
  52. extern int stereo_type;
  53. extern int fancy_background, reflection_pool, show_logo, do_screen_clear;
  54. extern VIEW default_view, orig_view, *current_view;
  55. extern STEREO default_stereo;
  56. extern SPLIT *split_tree;
  57. extern unsigned lastkey, nextolastkey;
  58. extern unsigned paint;
  59. extern int show_location, show_compass, show_framerate;
  60.   
  61. //----------------------------------------------------------  
  62.  
  63. #define to_rad(a) ((a) * 3.14159262 / 180.0)
  64. #define sine(x)   sin(to_rad(x/65536L))
  65. #define cosine(x) cos(to_rad(x/65536L))
  66.   
  67. #define F1  0x3B00
  68. #define F2  0x3C00
  69. #define F3  0x3D00
  70. #define F4  0x3E00
  71. #define F5  0x3F00
  72. #define F6  0x4000
  73. #define F7  0x4100
  74. #define F8  0x4200
  75. #define F9  0x4300
  76. #define F10 0x4400
  77.   
  78. #define HOME      0x4700
  79. #define END       0x4F00
  80. #define PGUP      0x4900
  81. #define PGDN      0x5100
  82. #define LEFT      0x4B00
  83. #define RIGHT     0x4D00
  84. #define UP        0x4800
  85. #define DOWN      0x5000
  86. #define SHLEFT    0x4B01
  87. #define SHRIGHT   0x4D01
  88. #define SHUP      0x4801
  89. #define SHDOWN    0x5001
  90. #define SHPGUP    0x4901
  91. #define SHPGDN    0x5101
  92. #define CTRLLEFT  0x7300
  93. #define CTRLRIGHT 0x7400
  94. #define CTRLHOME  0x7700
  95. #define CTRLEND   0x7500
  96. #define CTRLPGUP  0x8400
  97. #define CTRLPGDN  0x7600
  98. #define ESC       0x001B
  99.  
  100. // ---------------------------------------------------  
  101.  
  102. char *helptext[] = {
  103.    "              HELP",
  104.    "ARROWS       move around horizonally",
  105.    "Pgup/Pgdn    move up/down",
  106.    "CTRL+ARROWS  twist head, U u-turns",
  107.    "CTRL PgUp/CTRL PgDn tilt head up/down",
  108.    "+ and - keys zoom in and out",
  109.    "G go to specified x,y,z location",
  110.    "R repeats last move 100x",
  111.    "I gives information  O sets options",
  112.    "0-9 set step size (0 = 10)",
  113.    "* resets to default view",
  114.    "Q quits, ? shows help",
  115.    "V resizes view, ^ saves PCX file",
  116.    "C changes hither/yon clipping",
  117.    "D displays status information",
  118.    "L loads, S saves PLG files",
  119.    "M loads multi-resolution PLG files",
  120.    "F loads figure files",
  121.    "P displays color palette",
  122.    "Z does object manipulation",
  123.    "X invokes extra features",
  124.    NULL
  125. };
  126.   
  127. static char *featmenu[] = {
  128.    "Select Surface type",
  129.    "Choose Color",
  130.    "Paint Polys",
  131.    NULL
  132. };
  133.   
  134. static char *surfmenu[] = {
  135.    "Absolute",
  136.    "Cosine-lit",
  137.    "Metal",
  138.    "Glass",
  139.    NULL
  140. };
  141.   
  142. // ---------------------------------------------------  
  143. int use_old_keys = 0;
  144. int stepsize = 5;
  145. long anglestep = 2L * 65536L;
  146. FILE *save_file = NULL;
  147. int nsaved = 0;
  148. // ---------------------------------------------------  
  149.   
  150. unsigned getkey(void)
  151. {
  152.    unsigned c;
  153.    union REGS regs;
  154.    int shifted;
  155.   
  156.    regs.h.ah = 2;
  157.    int86(0x16, ®s, ®s);
  158.    shifted = (regs.h.al & 3);
  159.    if ((c = bioskey(0)) & 0xFF) c &= 0xFF;
  160.    else if (shifted) c |= 1;
  161.    return c;
  162. }
  163.   
  164. // ---------------------------------------------------  
  165. void disp_palette(void)
  166. {
  167.    int i, j, page;
  168.    page = cursor_hide();
  169.    for (i = 0; i < 16; i++)
  170.       for (j = 0; j < 16; j++)
  171.          user_box(j*10,i*8,j*10+9,i*8+8,i*16+j);
  172.    cursor_show(page);
  173.    reframe = 1;
  174. }
  175.   
  176. extern void disp_info(void);
  177. extern void disp_status(VIEW *v);
  178. // ---------------------------------------------------  
  179. void save_it(OBJECT *obj)
  180. {
  181.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
  182.    {
  183.       char buff[100];
  184.       save_plg(obj, save_file);
  185.       sprintf(buff, "%d object%s saved", ++nsaved,
  186.          (nsaved > 1) ? "s" : "");
  187.       refresh_display();
  188.       popmsg(buff);
  189.       reframe = 1;
  190.    }
  191. }
  192.  
  193. // ---------------------------------------------------  
  194. int advanced(void);
  195. int set_options(void);
  196. int new_features(void);
  197.   
  198. // ---------------------------------------------------  
  199. void do_key(unsigned c)
  200. {
  201.    void joystick_calibration(), *what_area();
  202.    char buff[100];
  203.    FILE *in, *out;
  204.    long x, y, z;
  205.    int i, j;
  206.    MATRIX m,n;
  207.    long av, bv, cv, dv; /* used for 'A' */
  208.    if (check_key(c)) 
  209.       return;
  210.    switch (c)
  211.    {
  212. #ifdef NFF_SAVE   /* not in this release... */
  213.       case 'N':
  214.       case 'n':
  215.          nextolastkey = 0;
  216.          askfor("File to save? ", buff, 15);
  217.          if (buff[0] == '\0') {
  218.             redraw = 1;
  219.             break;
  220.          }
  221.          if ((out = fopen(buff, "w")) == NULL) {
  222.             popmsg("Could not save file");
  223.             getkey();
  224.          }
  225.          else {
  226.             save_nff(out);
  227.             fclose(out);
  228.          }
  229.          reframe = redraw = 1;
  230.          break;
  231. #endif
  232.       case 'M':
  233.       case 'm':
  234.          nextolastkey = 0;
  235.          askfor("File to load? ", buff, 15);
  236.          if (buff[0] == '\0') {
  237.             redraw = 1;
  238.             break;
  239.          }
  240.          if ((in = fopen(buff, "r")) == NULL) {
  241.             popmsg("Could not load file");
  242.             getkey();
  243.          }
  244.          else {
  245.             OBJECT *obj;
  246.             SEGMENT *s;
  247.             set_loadplg_offset(0,0,0);
  248.             set_loadplg_scale(1,1,1);
  249.             obj = load_multi_plg(in);
  250.             select_representation(obj, 0L);
  251.             add_obj_to_split_area(split_tree, obj);
  252.             if ((s = new_seg(NULL)) == NULL) {
  253.                popmsg("Warning -- out of memory!");
  254.                getkey();
  255.             }
  256.             else {
  257.                seg_set_object(s, obj);
  258.                set_object_owner(obj, s);
  259.                update_segment(s);
  260.             }
  261.             if (spacestep < get_object_bounds(obj, &x, &y, &z)/5L)
  262.                spacestep = get_object_bounds(obj, &x, &y, &z)/5L;
  263.             fclose(in);
  264.          }
  265.          reframe = redraw = 1;
  266.          break;
  267.       case 'G':
  268.       case 'g':
  269.          nextolastkey = 0;
  270.          askfor("X,Y,Z: ", buff, 15);
  271.          if (buff[0])
  272.             sscanf(buff, "%ld,%ld,%ld", ¤t_view->ex, ¤t_view->ey, ¤t_view->ez);
  273.          reframe = review = redraw = 1;
  274.          break;
  275.       case LEFT:
  276.          if (use_old_keys)
  277.             latitude -= stepsize * anglestep;
  278.          else
  279.             current_view->pan -= stepsize * anglestep;
  280.          review = redraw = 1;
  281.          break;
  282.       case RIGHT:
  283.          if (use_old_keys)
  284.             latitude += stepsize * anglestep;
  285.          else
  286.             current_view->pan += stepsize * anglestep;
  287.          longitude -= stepsize * anglestep;
  288.          review = redraw = 1;
  289.          break;
  290.       case UP:
  291.          if (use_old_keys)
  292.             longitude += stepsize * anglestep;
  293.          else
  294.          {
  295.             current_view->ex += (stepsize * spacestep) * sine(current_view->pan);
  296.             current_view->ez += (stepsize * spacestep) * cosine(current_view->pan);
  297.          }
  298.          review = redraw = 1;
  299.          break;
  300.       case DOWN:
  301.          if (use_old_keys)
  302.             longitude -= stepsize * anglestep;
  303.          else
  304.          {
  305.             current_view->ex -= (stepsize * spacestep) * sine(current_view->pan);
  306.             current_view->ez -= (stepsize * spacestep) * cosine(current_view->pan);
  307.          }
  308.          review = redraw = 1;
  309.          break;
  310.       case PGUP:
  311.          if (use_old_keys)
  312.             center_d += (stepsize * spacestep);
  313.          else
  314.             current_view->tilt += (stepsize * anglestep);
  315.          review = redraw = 1;
  316.          break;
  317.       case PGDN:
  318.          if (use_old_keys)
  319.             center_d -= (stepsize * spacestep);
  320.          else
  321.             current_view->tilt -= (stepsize * anglestep);
  322.          review = redraw = 1;
  323.          break;
  324.       case CTRLLEFT:
  325.          if (use_old_keys)
  326.             center_roll -= stepsize * anglestep;
  327.          else
  328.          {
  329.             current_view->ex -= (stepsize * spacestep) * cosine(current_view->pan);
  330.             current_view->ez += (stepsize * spacestep) * sine(current_view->pan);
  331.          }
  332.          review = redraw = 1;
  333.          break;
  334.       case CTRLRIGHT:
  335.          if (use_old_keys)
  336.             center_roll += stepsize * anglestep;
  337.          else
  338.          {
  339.             current_view->ex += (stepsize * spacestep) * cosine(current_view->pan);
  340.             current_view->ez -= (stepsize * spacestep) * sine(current_view->pan);
  341.          }
  342.          review = redraw = 1;
  343.          break;
  344.       case CTRLPGUP:
  345.          if (use_old_keys)
  346.             current_view->zoom += stepsize * 65536L/10;
  347.          else
  348.             current_view->ey += (stepsize * spacestep);
  349.          review = redraw = 1;
  350.          break;
  351.       case CTRLPGDN:
  352.          if (use_old_keys)
  353.             current_view->zoom -= stepsize * 65536L/10;
  354.          else
  355.             current_view->ey -= (stepsize * spacestep);
  356.          review = redraw = 1;
  357.          break;
  358.       case CTRLHOME:
  359.          current_view->roll -= (stepsize * anglestep);
  360.          review = redraw = 1;
  361.          break;
  362.       case CTRLEND:
  363.          current_view->roll += (stepsize * anglestep);
  364.          review = redraw = 1;
  365.          break;
  366.       case '+':
  367.          if (stereo_type == MONOSCOPIC)
  368.             current_view->zoom *= 1.1;
  369.          else
  370.             default_stereo.world_scaling *= 1.1;
  371.          review = redraw = 1;
  372.          break;
  373.       case '-':
  374.          if (stereo_type == MONOSCOPIC)
  375.             current_view->zoom /= 1.1;
  376.          else {
  377.             default_stereo.world_scaling /= 1.1;
  378.             if (default_stereo.world_scaling <= 10)
  379.                default_stereo.world_scaling = 11;
  380.          }
  381.          review = redraw = 1;
  382.          break;
  383.       case 'U':
  384.       case 'u':
  385.          current_view->pan += 180*65536L;
  386.          nextolastkey = 0;
  387.          review = redraw = 1;
  388.          break;
  389.       case 'W': // reset rotations, added 'cause its easy to mess them
  390.       case 'w': // up when you are using the GDController ball
  391.          nextolastkey = 0;
  392.          current_view->pan = orig_view.pan;
  393.          current_view->tilt = orig_view.tilt;
  394.          current_view->roll = orig_view.roll;
  395.          review = redraw = 1;
  396.          break;
  397.       case '*':
  398.          nextolastkey = 0;
  399.          if (use_old_keys)
  400.          {
  401.             current_view = &default_view;
  402.             center_d = 10000;
  403.             center_x = 0;
  404.             center_y = 0;
  405.             center_z = 0;
  406.             latitude = 0;
  407.             longitude = 0;
  408.             center_roll = 0;
  409.          }
  410.          else
  411.             default_view = orig_view;
  412.          review = redraw = 1;
  413.          break;
  414.       case SHLEFT:
  415.          x = stepsize*spacestep/10;
  416.          y = 0;
  417.          review = redraw = 1;
  418.          goto fixcenter;  /* save some code (Dave) */
  419.       case SHRIGHT:
  420.          x = -stepsize*spacestep/10 ;
  421.          y = 0;
  422.          review = redraw = 1;
  423.          goto fixcenter;  /* save some code (Dave) */
  424.       case SHUP:
  425.          y = -stepsize*spacestep/10;
  426.          x = 0;
  427.          review = redraw = 1;
  428.          goto fixcenter;  /* save some code (Dave) */
  429.       case SHDOWN:
  430.          y = stepsize*spacestep/10;
  431.          x = 0;
  432.          review = redraw = 1;
  433.          fixcenter:
  434.          z = 0;
  435.          std_matrix(n,longitude,latitude,center_roll,0,0,0);
  436.          matrix_point(n,&x,&y,&z);
  437.          center_x += x;
  438.          center_y += y;
  439.          center_d -= z;
  440.          break;
  441.       case SHPGUP:
  442.          center_z += stepsize*spacestep/10;
  443.          review = redraw = 1;
  444.          break;
  445.       case SHPGDN:
  446.          center_z -= stepsize*spacestep/10;
  447.          review = redraw = 1;
  448.          break;
  449.       case '[':
  450.          nextolastkey = 0;
  451.          if (sl_xflip) sl_xoff++; else sl_xoff--;
  452.          if (sr_xflip) sr_xoff--; else sr_xoff++;
  453.          review = redraw = 1;
  454.          goto stereo_recompute;  /* save some code (Dave) */
  455.       case ']':
  456.          nextolastkey = 0;
  457.          if (sl_xflip) sl_xoff--; else sl_xoff++;
  458.          if (sr_xflip) sr_xoff++; else sr_xoff--;
  459.          review = redraw = 1;
  460.          goto stereo_recompute;  /* save some code (Dave) */
  461.       case '{':
  462.          nextolastkey = 0;
  463.          default_stereo.phys_screen_width++;
  464.          review = redraw = 1;
  465.          goto stereo_recompute;  /* save some code (Dave) */
  466.       case '}':
  467.          nextolastkey = 0;
  468.          default_stereo.phys_screen_width--;
  469.          review = redraw = 1;
  470.          stereo_recompute:
  471.          if (stereo_type != MONOSCOPIC)
  472.          {
  473.             compute_stereo_data(&default_stereo, LEFT_EYE, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  474.             sl_left, sl_top, sl_right, sl_bottom);
  475.   
  476.             compute_stereo_data(&default_stereo, RIGHT_EYE, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  477.             sr_left, sr_top, sr_right, sr_bottom);
  478.          }
  479.          break;
  480.   
  481.       case '0':
  482.          nextolastkey = 0;
  483.          stepsize = 10;
  484.          break;
  485.       case '1': case '2': case '3': case '4': case '5':
  486.       case '6': case '7': case '8': case '9':
  487.          nextolastkey = 0;
  488.          stepsize = c - '0';
  489.          break;
  490.       case 'Q':
  491.       case 'q':
  492.       case ESC:
  493.          nextolastkey = 0;
  494.          popmsg("Really quit?");
  495.          if (toupper(getkey()) == 'Y') running = 0;
  496.          else reframe = redraw = 1;
  497.          break;
  498.       case 'R':
  499.       case 'r':
  500.          nextolastkey = lastkey;
  501.          if (lastkey)
  502.             for (i = 0; i < 100; i++) {
  503.                do_key(lastkey);
  504.                refresh_display();
  505.             }
  506.          break;
  507.       case 'C':
  508.       case 'c':
  509.          nextolastkey = 0;
  510.          popmsg("Change Hither or Yon?");
  511.       switch (toupper(getkey()))
  512.       {
  513.          case 'H':
  514.             askfor("Enter hither value:", buff, 10);
  515.             if (buff[0])
  516.                current_view->hither = atof(buff);
  517.             if (current_view->hither < 1) current_view->hither = 1;
  518.             review = 1;
  519.             break;
  520.          case 'Y':
  521.             askfor("Enter yon value:", buff, 10);
  522.             if (buff[0]) current_view->yon = atof(buff);
  523.             review = 1;
  524.             break;
  525.          default:
  526.             break;
  527.       }
  528.          reframe = redraw = 1;
  529.          break;
  530.       case 'D':
  531.       case 'd':
  532.          nextolastkey = 0;
  533.          disp_status(current_view);
  534.          reframe = redraw = 1;
  535.          break;
  536.       case 'L':
  537.       case 'l':
  538.          nextolastkey = 0;
  539.          askfor("File to load? ", buff, 15);
  540.          if (buff[0] == '\0') {
  541.             redraw = 1;
  542.             break;
  543.          }
  544.          if ((in = fopen(buff, "r")) == NULL) {
  545.             popmsg("Could not load file");
  546.             getkey();
  547.          }
  548.          else {
  549.             OBJECT *obj;
  550.             set_loadplg_offset(0,0,0);
  551.             set_loadplg_scale(1,1,1);
  552.             while ((obj = load_plg(in)) != NULL) {
  553.                SEGMENT *s;
  554.                add_obj_to_split_area(split_tree, obj);
  555.                if ((s = new_seg(NULL)) == NULL) {
  556.                   popmsg("Warning -- out of memory!");
  557.                   getkey();
  558.                }
  559.                else {
  560.                   seg_set_object(s, obj);
  561.                   set_object_owner(obj, s);
  562.                   update_segment(s);
  563.                }
  564.             /*             if (spacestep < get_object_bounds(obj, &x, &y, &z)/5L)
  565.                                                                   spacestep = get_object_bounds(obj, &x, &y, &z)/5L; */
  566.             }
  567.             fclose(in);
  568.          }
  569.          reframe = redraw = 1;
  570.          break;
  571.       case 'S':
  572.       case 's':
  573.          nextolastkey = 0;
  574.          askfor("File to save? ", buff, 15);
  575.          if (buff[0] == '\0') {
  576.             redraw = 1;
  577.             break;
  578.          }
  579.          if ((save_file = fopen(buff, "w")) == NULL) {
  580.             popmsg("Could not open file");
  581.             getkey();
  582.          }
  583.          else {
  584.             nsaved = 0;
  585.             walk_split_tree(split_tree, save_it);
  586.             fclose(save_file);
  587.          }
  588.          reframe = redraw = 1;
  589.          break;
  590.       case 'Z':
  591.       case 'z':
  592.          nextolastkey = 0;
  593.          advanced();
  594.          while (bioskey(1)) bioskey(0); /* flush keyboard buffer */
  595.          reframe = redraw = 1;
  596.          break;
  597.       case 'I':
  598.       case 'i':
  599.          nextolastkey = 0;
  600.          disp_info();
  601.          reframe = redraw = 1;
  602.          break;
  603.       case 'P':
  604.       case 'p':
  605.          nextolastkey = 0;
  606.          disp_palette();
  607.          getkey();
  608.          reframe = redraw = 1;
  609.          break;
  610.       case 'F':
  611.       case 'f':
  612.          nextolastkey = 0;
  613.          askfor("Figure file to read? ", buff, 15);
  614.          if (buff[0] == '\0') {
  615.             reframe = redraw = 1;
  616.             break;
  617.          }
  618.          if ((in = fopen(buff, "r")) == NULL) {
  619.             popmsg("Could not load figure file");
  620.             getkey();
  621.          }
  622.          else {
  623.             SEGMENT *s, *readseg();
  624.             int c;
  625.             while ((c = getc(in)) != '{')
  626.                if (c == EOF) {
  627.                   popmsg("Early EOF!");
  628.                   getkey();
  629.                   break;
  630.                }
  631.             set_readseg_objlist(objlist);
  632.             if ((s = readseg(in, NULL)) == NULL) {
  633.                popmsg("Error reading figure file");
  634.                getkey();
  635.             }
  636.             else
  637.                update_segment(s);
  638.          }
  639.          reframe = redraw = 1;
  640.          break;
  641.       case 'H':
  642.       case 'h':
  643.       case '?':
  644.          nextolastkey = 0;
  645.          poptext(helptext);
  646.          getkey();
  647.          reframe = redraw = 1;
  648.          break;
  649.       case 'O':
  650.       case 'o':
  651.          nextolastkey = 0;
  652.          set_options();
  653.          reframe = redraw = 1;
  654.          break;
  655. #ifdef RESIZE_IMPLEMENTED
  656.       case 'V':
  657.       case 'v':
  658.          nextolastkey = 0;
  659.          resize_viewport();
  660.          reframe = review = redraw = 1;
  661.          break;
  662. #endif
  663.       case 'X':
  664.       case 'x':
  665.          nextolastkey = 0;
  666.          new_features();
  667.          while (bioskey(1)) bioskey(0); /* flush keyboard buffer */
  668.          reframe = review = redraw = 1;
  669.          break;
  670.       case '^':
  671.          nextolastkey = 0;
  672.          save_pcx_file();
  673.       default:
  674.          break;
  675.    }
  676. }
  677.   
  678. extern long last_render_time;
  679.   
  680. void do_joy(joystick_data *joy)
  681. {
  682.    long dist = spacestep*stepsize;
  683.    float cosvalue, sinvalue;
  684.    int x = joy->x;
  685.    int y = joy->y;
  686.    int sscale = last_render_time;
  687.   
  688.    if (abs(x) < 10 && abs(y) < 10) return;
  689.   
  690.    if (x > 10) x -= 10;
  691.    else
  692.    {
  693.       if (x > -10) x = 0;
  694.       else x += 10;
  695.    }
  696.    if (y > 10) y -= 10;
  697.    else
  698.    {
  699.       if (y > -10) y = 0;
  700.       else y += 10;
  701.    }
  702.    cosvalue = cosine(current_view->pan);
  703.    sinvalue = sine(current_view->pan);
  704.    switch (joy->buttons)
  705.    {
  706.       case 0:/* no buttons down */
  707.          current_view->pan += (x * anglestep*stepsize)/1200*sscale;
  708.          current_view->ex -= (y * dist * sinvalue)/100*sscale ;
  709.          current_view->ez -= (y * dist * cosvalue)/100*sscale ;
  710.          review = redraw = 1;
  711.          break;
  712.       case 1:/* first button down */
  713.          current_view->tilt -= (y * anglestep*stepsize)/2000*sscale;
  714.          current_view->ex -= (x * dist * cosvalue)/400*sscale ;
  715.          current_view->ez += (x * dist * sinvalue)/400*sscale ;
  716.          review = redraw = 1;
  717.          break;
  718.       case 2:/* second button down */
  719.          current_view->ex -= (x * dist * cosvalue)/400*sscale ;
  720.          current_view->ez += (x * dist * sinvalue)/400*sscale ;
  721.          current_view->ey -= (y * spacestep*stepsize)/400*sscale ;
  722.          review = redraw = 1;
  723.          break;
  724.       case 3:/* both buttons down */
  725.          current_view->roll += (x * anglestep*stepsize)/400*sscale;
  726.          current_view->zoom += (y*65536L) /4000*sscale;
  727.          review = redraw = 1;
  728.          break;
  729.       default:
  730.          break;
  731.    }
  732. }
  733.  
  734. //-------------------------------------------------------  
  735. static char *adv_menu[] = {
  736.    "Move",
  737.    "Rotate",
  738.    "Twirl",
  739.    "Alter",
  740.    "Paint",
  741.    "Info",
  742.    "Save",
  743.    "Delete",
  744.    "Unselect",
  745.    "Hack off",
  746.    "Join to",
  747.    "Figure...",
  748.    "Next rep",
  749.    NULL
  750. };
  751.   
  752. POINTER pointer;
  753.   
  754. static char *surface_menu[] = {
  755. "Normal", "Cosine-lit", "Metal", "Glass", NULL };
  756.   
  757. static char *figure_menu[] = {
  758.    "Figure select",
  759.    "Delete",
  760.    "Save",
  761.    "Copy",
  762.    "Info",
  763.    NULL
  764. };
  765.   
  766. //-------------------------------------------------------  
  767. void select_tree(SEGMENT *s)
  768. {
  769.    SEGMENT *p;
  770.    OBJECT *obj;
  771.    if ((obj = seg_get_object(s)) != NULL) highlight_obj(obj);
  772.    for (p = child_segment(s); p; p = sibling_segment(p))
  773.       select_tree(p);
  774. }
  775.   
  776. void count_tree(SEGMENT *s, int *nsegs, int *nverts, int *npolys)
  777. {
  778.    SEGMENT *p;
  779.    OBJECT *obj;
  780.    ++*nsegs;
  781.    if ((obj = seg_get_object(s)) != NULL) {
  782.       int nv, np;
  783.       get_obj_info(obj, &nv, &np);
  784.       *nverts += nv;
  785.       *npolys += np;
  786.    }
  787.    for (p = child_segment(s); p; p = sibling_segment(p))
  788.       count_tree(p, nsegs, nverts, npolys);
  789. }
  790.   
  791. static void zap_obj(OBJECT *obj)
  792. {
  793.    remove_from_objlist(obj);
  794.    delete_obj(obj);
  795. }
  796.   
  797. int nselected = 0;
  798.   
  799. void count_selected(OBJECT *obj)
  800. {
  801.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
  802.       ++nselected;
  803. }
  804.   
  805. int nobjs = 0, nverts = 0, npolys = 0;
  806.   
  807. void gather_info(OBJECT *obj)
  808. {
  809.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
  810.    {
  811.       int nv, np;
  812.       ++nobjs;
  813.       get_obj_info(obj, &nv, &np);
  814.       nverts += nv;
  815.       npolys += np;
  816.    }
  817. }
  818.   
  819. long ptx, pty, ptz;
  820.   
  821. long oldx, oldy, oldz, oldcx, oldcy, oldcz, dx, dy, dz;
  822.   
  823.   
  824. void move_it(OBJECT *obj)
  825. {
  826.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
  827.    {
  828.       SEGMENT *s;
  829.       if ((s = get_object_owner(obj)) != NULL)
  830.       {
  831.          rel_move_segment(s, ptx - oldx, pty - oldy, ptz - oldz);
  832.          update_segment(s);
  833.       }
  834.    }
  835. }
  836.   
  837. void rot_it(OBJECT *obj)
  838. {
  839.    int i;
  840.   
  841.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED)
  842.    {
  843.       SEGMENT *s;
  844.       if ((s = get_object_owner(obj)) != NULL)
  845.       {
  846.          rel_rot_segment(s, ptx, pty, ptz, RYXZ);
  847.          update_segment(s);
  848.       }
  849.    }
  850. }
  851.   
  852. unsigned surf;
  853.   
  854. void surf_it(OBJECT *obj)
  855. {
  856.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED) {
  857.       int nv, np, i;
  858.       get_obj_info(obj, &nv, &np);
  859.       for (i = 0; i < np; ++i) {
  860.          unsigned color;
  861.          get_poly_info(obj, i, &color, &nv, NULL, 0);
  862.          set_poly_color(obj, i, (color & 0xCFFF) | surf);
  863.       }
  864.    }
  865. }
  866.   
  867. void color_it(OBJECT *obj)
  868. {
  869.    if (get_obj_flags(obj) & OBJ_HIGHLIGHTED) {
  870.       int nv, np, i;
  871.       get_obj_info(obj, &nv, &np);
  872.       for (i = 0; i < np; ++i)
  873.          set_poly_color(obj, i, 0x8000 | paint);
  874.    }
  875. }
  876.   
  877. void unhi_it(OBJECT *obj)
  878. {
  879.    set_obj_flags(obj, get_obj_flags(obj) & ~OBJ_HIGHLIGHTED);
  880.    unhighlight_obj(obj);
  881. }
  882.   
  883. void hack_it(OBJECT *obj)
  884. {
  885.    SEGMENT *s;
  886.    if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) && (s = get_object_owner(obj)) != NULL) {
  887.       detach_segment(s);
  888.       update_segment(s);
  889.    }
  890. }
  891.   
  892. SEGMENT *newparent = NULL;
  893.   
  894. void join_it(OBJECT *obj)
  895. {
  896.    SEGMENT *s;
  897.    if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) &&
  898.       (s = get_object_owner(obj)) != NULL)
  899.    {
  900.       attach_segment(s, newparent);
  901.       update_segment(s);
  902.    }
  903. }
  904.   
  905. void nuke_it(OBJECT *obj)
  906. {
  907.    if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED)) {
  908.       SEGMENT *s;
  909.       if ((s = get_object_owner(obj)) != NULL)
  910.          seg_set_object(s, NULL);
  911.       remove_from_objlist(obj);
  912.       delete_obj(obj);
  913.    }
  914. }
  915.   
  916. void next_it(OBJECT *obj)
  917. {
  918.    next_rep(obj);
  919. }
  920.   
  921. extern PDRIVER *cursor_device;
  922.   
  923. int advanced(void)
  924. {
  925.    SEGMENT *s;
  926.    OBJECT *obj;
  927.    void pointer_to_world();
  928.    int nsegs = 0;
  929.    char buff[100], *p;
  930.    FILE *out;
  931.    char c, d;
  932.    unsigned char oldflags;
  933.    int mx, my;
  934.    unsigned buttons;
  935.    time_t now;
  936.    int click = 0;
  937.   
  938.    init_pointer(&pointer);
  939.   
  940.    nselected = 0;
  941.    walk_split_tree(split_tree, count_selected);
  942.    if (nselected == 0)
  943.    {
  944.       popmsg("No objects selected!");
  945.       delay(600);
  946.       return 0;
  947.    }
  948.   
  949.    poptext(adv_menu);
  950.    switch (c = toupper(getkey()))
  951.    {
  952.       case 'N':
  953.          walk_split_tree(split_tree, next_it);
  954.          break;
  955.       case 'S':
  956.          refresh_display();
  957.          if (askfor("Enter filename: ", buff, 20) == 0x1B) break;
  958.          if (buff[0] == '\0') {
  959.             reframe = redraw = 1;
  960.             break;
  961.          }
  962.          nobjs = 0;
  963.          if ((save_file = fopen(buff, "w")) == NULL)
  964.          {
  965.             popmsg("Could not create file");
  966.             reframe = 1;
  967.             getkey();
  968.             break;
  969.          }
  970.          nsaved = 0;
  971.          walk_split_tree(split_tree, save_it);
  972.          fclose(save_file);
  973.          save_file = NULL;
  974.          refresh_display();
  975.          sprintf(buff, "Saved %d object%s", nobjs, (nobjs > 1) ? "s" : "");
  976.          popmsg(buff);
  977.          getkey();
  978.          fclose(out);
  979.          break;
  980.       case 'I':
  981.          refresh_display();
  982.          nobjs = nverts = npolys = 0;
  983.          walk_split_tree(split_tree, gather_info);
  984.          sprintf(buff, "%d obj%s, %d vertice%s, %d polygon%s", nobjs, (nobjs == 1) ? "" : "s", nverts, (nverts == 1) ? "" : "s", npolys, (npolys == 1) ? "" : "s");
  985.          popmsg(buff);
  986.          getkey();
  987.          break;
  988.   
  989.       case 'M':
  990.          refresh_display();
  991.          if (!manip_2D_avail) break;
  992.          pointer_read(cursor_device, &pointer);
  993.          pointer_to_world(&pointer, current_view, &ptx, &pty, &ptz);
  994.          click = 0;
  995.          while (click == 0)
  996.          {
  997.             refresh_display();
  998.             oldx = ptx;
  999.             oldy = pty;
  1000.             oldz = ptz;
  1001.             click = PNEW_BUT & pointer_read(cursor_device, &pointer);
  1002.             if (!(pointer.buttons & 1)) click = 0;
  1003.             pointer_to_world(&pointer, current_view, &ptx, &pty, &ptz);
  1004.             walk_split_tree(split_tree, move_it);
  1005.          }
  1006.          refresh_display();
  1007.          break;
  1008.       case 'R':
  1009.       case 'T':
  1010.          refresh_display();
  1011.          if (!manip_2D_avail) break;
  1012.          pointer_read(cursor_device, &pointer);
  1013.          oldcx = oldx = pointer.x;
  1014.          oldcy = oldy = pointer.y;
  1015.          oldcz = oldz = pointer.z;
  1016.          while ((pointer.buttons & 0x01) == 0)
  1017.          {
  1018.             if (c == 'R')
  1019.             {
  1020.                ptx = 32768L*(pointer.y - oldy);
  1021.                pty = -32768L*(pointer.x - oldx);
  1022.                ptz = -32768L*(pointer.z - oldz);
  1023.             }
  1024.             else
  1025.             {
  1026.                ptx = 3270L*(pointer.y - oldcy);
  1027.                pty = -3270L*(pointer.x - oldcx);
  1028.                ptz = -3270L*(pointer.z - oldcz);
  1029.             }
  1030.             rotate_to_view(current_view, &ptx, &pty, &ptz);
  1031.             walk_split_tree(split_tree, rot_it);
  1032.             oldx = pointer.x;
  1033.             oldy = pointer.y;
  1034.             oldz = pointer.z;
  1035.             refresh_display();
  1036.             pointer_read(cursor_device, &pointer);
  1037.          }
  1038.   
  1039.          while (pointer.buttons & 0x01) pointer_read(cursor_device, &pointer);
  1040.          refresh_display();
  1041.          break;
  1042.   
  1043.       case 'A':
  1044.          refresh_display();
  1045.          poptext(surface_menu);
  1046.       switch (toupper(getkey())) {
  1047.          case 'N':
  1048.             surf = 0x0000;
  1049.             break;
  1050.          case 'C':
  1051.             surf = 0x1000;
  1052.             break;
  1053.          case 'M':
  1054.             surf = 0x2000;
  1055.             break;
  1056.          case 'G':
  1057.             surf = 0x3000;
  1058.             break;
  1059.          default:
  1060.             return 0;
  1061.       }
  1062.          walk_split_tree(split_tree, surf_it);
  1063.          refresh_display();
  1064.          break;
  1065.       case 'P':
  1066.          walk_split_tree(split_tree, color_it);
  1067.          refresh_display();
  1068.          break;
  1069.       case 'D':
  1070.          refresh_display();
  1071.          sprintf(buff, "Delete %d object%s!  Are you sure?", nselected, (nselected > 1) ? "s" : "");
  1072.          popmsg(buff);
  1073.          reframe = 1;
  1074.          if (toupper(getkey()) != 'Y') break;
  1075.          refresh_display();
  1076.          walk_split_tree(split_tree, nuke_it);
  1077.          refresh_display();
  1078.          break;
  1079.       case 'U':
  1080.          walk_split_tree(split_tree, unhi_it);
  1081.          refresh_display();
  1082.          break;
  1083.       case 'H':
  1084.          refresh_display();
  1085.          walk_split_tree(split_tree, hack_it);
  1086.          break;
  1087.       case 'J':
  1088.          if (!can_point_2D()) break;
  1089.          if (!manip_2D_avail) break;
  1090.          refresh_display();
  1091.          popmsg("Click on new parent");
  1092.          reframe = 1;
  1093.          refresh_display();
  1094.          newparent = NULL;
  1095.          do {
  1096.             OBJECT *newobj;
  1097.   
  1098.             move_till_click(cursor_device, 1, &mx, &my);
  1099.             newobj = where_split_screen_pt(NULL, NULL, mx, my);
  1100.             if (newobj)
  1101.                if ((get_obj_flags(newobj) & OBJ_HIGHLIGHTED) == 0)
  1102.                   newparent = get_object_owner(newobj);
  1103.          }
  1104.          while (newparent == NULL);
  1105.          walk_split_tree(split_tree, join_it);
  1106.          break;
  1107.       case 'F':
  1108.          refresh_display();
  1109.          poptext(figure_menu);
  1110.          for (obj = first_in_objlist(objlist); obj; obj = next_in_objlist(obj))
  1111.             if ((get_obj_flags(obj) & OBJ_HIGHLIGHTED) && (s = get_object_owner(obj)) != NULL)
  1112.                break;
  1113.          if (obj == NULL || s == NULL) {
  1114.             popmsg("No objects selected!");
  1115.             getkey();
  1116.             return 0;
  1117.          }
  1118.          switch (toupper(getkey())) {
  1119.             case 'F':
  1120.                select_tree(find_root_segment(s)); /* and down again */
  1121.                break;
  1122.             case 'D':
  1123.                refresh_display();
  1124.                popmsg("Delete entire figure! Are you sure?");
  1125.                if (toupper(getkey()) != 'Y') break;
  1126.                refresh_display();
  1127.                delete_segment(find_root_segment(s), zap_obj);
  1128.                break;
  1129.             case 'I':
  1130.                count_tree(find_root_segment(s), &nsegs, &nverts, &npolys);
  1131.                sprintf(buff, "%d segs, %d verts, %d polys", nsegs, nverts, npolys);
  1132.                popmsg(buff);
  1133.                getkey();
  1134.                break;
  1135.             case 'S':
  1136.                refresh_display();
  1137.                askfor("Filename: ", buff, 20);
  1138.                if (buff[0] == '\0') break;
  1139.                refresh_display();
  1140.                if ((out = fopen(buff, "w")) == NULL) {
  1141.                   popmsg("Could not create file");
  1142.                   getkey();
  1143.                   break;
  1144.                }
  1145.                askfor("Comment: ", buff, 20);
  1146.                if ((p = strchr(buff, ';')) != NULL) *p = '\0';
  1147.                fprintf(out, "Comment = %s;\n", buff);
  1148.                time(&now);
  1149.                strcpy(buff, ctime(&now));
  1150.                if ((p = strchr(buff, '\n')) != NULL) *p = '\0';
  1151.                fprintf(out, "Comment = Saved from %s %s;\n", progname, buff);
  1152.                writeseg(out, find_root_segment(s), 0);
  1153.                fclose(out);
  1154.                break;
  1155.             default:
  1156.                return 0;
  1157.          }
  1158.          break;
  1159.       default:
  1160.          break;
  1161.    }
  1162.    return 0;
  1163. }
  1164.   
  1165. static char *optmenu[] = {
  1166.    "Background",
  1167.    "Reflection",
  1168.    "Logo",
  1169.    "Screen clear",
  1170.    "Ambient light",
  1171.    "Directional light",
  1172.    "Horizon",
  1173.    "Motion step size",
  1174.    "Keyboard mode",
  1175.    "Position display",
  1176.    "Compass display",
  1177.    "Frame rate display",
  1178. NULL
  1179. };
  1180.   
  1181. int set_options(void)
  1182. {
  1183.    char buff[20];
  1184.    poptext(optmenu);
  1185.    switch (toupper(getkey())) {
  1186.       case 'B':
  1187.          fancy_background = !fancy_background;
  1188.          break;
  1189.       case 'R':
  1190.          reflection_pool = !reflection_pool;
  1191.          current_view->bottom = reflection_pool ? 160 : 199;
  1192.          break;
  1193.       case 'L':
  1194.          show_logo = !show_logo;
  1195.          if (!show_logo) reset_screens();
  1196.          break;
  1197.       case 'S':
  1198.          do_screen_clear = !do_screen_clear;
  1199.          popmsg(do_screen_clear ? "Will clear" : "Won't clear");
  1200.          delay(600);
  1201.          break;
  1202.       case 'D':
  1203.          current_view->directional = !current_view->directional;
  1204.          popmsg(current_view->directional ? "Spotlight" : "Point Source");
  1205.          delay(600);
  1206.          break;
  1207.       case 'H':
  1208.          do_horizon = !do_horizon;
  1209.          if (!do_horizon) reset_screens();
  1210.          popmsg(do_horizon ? "Horizon" : "No Horizon");
  1211.          delay(600);
  1212.          break;
  1213.       case 'A':
  1214.          askfor("Ambient light: ", buff, 15);
  1215.          current_view->ambient = atoi(buff) & 0xFF;
  1216.          break;
  1217.       case 'M':
  1218.          popmsg("Space or Angle?");
  1219.       switch (toupper(getkey())) {
  1220.          case 'S':
  1221.             askfor("New space step: ", buff, 15);
  1222.             if (buff[0]) spacestep = atoi(buff);
  1223.             break;
  1224.          case 'A':
  1225.             askfor("New angle step: ", buff, 15);
  1226.             if (buff[0]) anglestep = atof(buff) * 65536L;
  1227.             break;
  1228.          default:
  1229.             break;
  1230.       }
  1231.          break;
  1232.       case 'K':
  1233.          use_old_keys = !use_old_keys;
  1234.          review = 1;
  1235.          break;
  1236.       case 'P':
  1237.          show_location = !show_location;
  1238.          if (!show_location) reset_screens();
  1239.          break;
  1240.       case 'C':
  1241.          show_compass = !show_compass;
  1242.          if (!show_compass) reset_screens();
  1243.          break;
  1244.       case 'F':
  1245.          show_framerate = !show_framerate;
  1246.          if (!show_framerate) reset_screens();
  1247.          break;
  1248.       default:
  1249.          break;
  1250.    }
  1251.    return 0;
  1252. }
  1253.   
  1254. static unsigned stype[] = {
  1255. 0, 0x1000, 0x2000, 0x3000 };
  1256.   
  1257. unsigned paint = 1;
  1258. static unsigned surface = 0x1000;
  1259. static unsigned paintcolor = 1;
  1260.   
  1261. int new_features(void)
  1262. {
  1263.    int x, y, c, i;
  1264.    unsigned buttons;
  1265.    char buff[100];
  1266.   
  1267.    if (!can_point_2D()) return 3;
  1268.   
  1269.    poptext(featmenu);
  1270.    reframe = 1;
  1271.    c = toupper(getkey());
  1272.    switch (c)
  1273.    {
  1274.       case 'S':/* select surface */
  1275.          poptext(surfmenu);
  1276.          reframe = 1;
  1277.       switch (toupper(getkey())) {
  1278.          case 'N':
  1279.             surface = stype[0];
  1280.             break;
  1281.          case 'C':
  1282.             surface = stype[1];
  1283.             break;
  1284.          case 'M':
  1285.             surface = stype[2];
  1286.             break;
  1287.          case 'G':
  1288.             surface = stype[3];
  1289.             break;
  1290.       }
  1291.          if (surface == 0)
  1292.             paint = paintcolor;
  1293.          else
  1294.             paint = (surface | ((paintcolor << 4) & 0x0FF0) + 10); /* hue, brightness *16 */
  1295.          refresh_display();
  1296.          break;
  1297.   
  1298.       case 'C':/* select color */
  1299.          if (!manip_2D_avail) break;
  1300.          disp_palette();
  1301.          disp_palette();
  1302.          reframe = 1;
  1303.          do {
  1304.             move_till_click(cursor_device, 1, &x, &y);
  1305.          }
  1306.          while (y>128 || x>160);
  1307.          paintcolor = 16*(y/8) + x/10;
  1308.          if (surface == 0)
  1309.             paint = paintcolor;
  1310.          else
  1311.             paint = (surface | ((paintcolor << 4) & 0x0FF0) + 10); /* hue, brightness *16 */
  1312.          refresh_display();
  1313.          break;
  1314.   
  1315.       case 'P':
  1316.          refresh_display();
  1317.          do {
  1318.             if (kbhit()) break;
  1319.             while (move_2D(cursor_device, &x, &y, &buttons) == 0 && !kbhit());
  1320.             if (buttons & 0x01) {
  1321.                OBJECT *obj;
  1322.                int poly;
  1323.                obj = where_split_screen_pt(&poly, NULL, x, y);
  1324.                if (obj) {
  1325.                   set_poly_color(obj, poly, paint);
  1326.                   refresh_display();
  1327.                }
  1328.             }
  1329.          }
  1330.          while (!(buttons & 0x02));
  1331.          break;
  1332.       default:
  1333.          break;
  1334.    }
  1335.    return 0;
  1336. }
  1337.   
  1338.