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