home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / source / cameravi.m < prev    next >
Encoding:
Text File  |  1996-08-08  |  16.0 KB  |  971 lines

  1. #import "qedefs.h"
  2.  
  3. id cameraview_i;
  4.  
  5. BOOL    timedrawing = 0;
  6.  
  7. @implementation CameraView
  8.  
  9. /*
  10. ==================
  11. initFrame:
  12. ==================
  13. */
  14. - initFrame:(const NXRect *)frameRect
  15. {
  16.     int        size;
  17.     
  18.     [super initFrame: frameRect];
  19.     
  20.     cameraview_i = self;
  21.     
  22.     xa = ya = za = 0;
  23.     
  24.     [self matrixFromAngles];
  25.     
  26.     origin[0] = 64;
  27.     origin[1] = 64;
  28.     origin[2] = 48;
  29.     
  30.     move = 16;
  31.     
  32.     size = bounds.size.width * bounds.size.height;
  33.     zbuffer = malloc (size*4);
  34.     imagebuffer = malloc (size*4);
  35.     
  36.     return self;
  37. }
  38.  
  39. - setXYOrigin: (NXPoint *)pt
  40. {
  41.     origin[0] = pt->x;
  42.     origin[1] = pt->y;
  43.     return self;
  44. }
  45.  
  46. - setZOrigin: (float)pt
  47. {
  48.     origin[2] = pt;
  49.     return self;
  50. }
  51.  
  52. - setOrigin: (vec3_t)org angle: (float)angle
  53. {
  54.     VectorCopy (org, origin);
  55.     ya = angle;
  56.     [self matrixFromAngles];
  57.     return self;
  58. }
  59.  
  60. - getOrigin: (vec3_t)org
  61. {
  62.     VectorCopy (origin, org);
  63.     return self;
  64. }
  65.  
  66. - (float)yawAngle
  67. {
  68.     return ya;
  69. }
  70.  
  71. - upFloor:sender
  72. {
  73.     sb_floor_dir = 1;
  74.     sb_floor_dist = 99999;
  75.     [map_i makeAllPerform: @selector(feetToFloor)];
  76.     if (sb_floor_dist == 99999)
  77.     {
  78.         qprintf ("already on top floor");
  79.         return self;
  80.     }
  81.     qprintf ("up floor");
  82.     origin[2] += sb_floor_dist;
  83.     [quakeed_i updateCamera];
  84.     return self;
  85. }
  86.  
  87. - downFloor: sender
  88. {
  89.     sb_floor_dir = -1;
  90.     sb_floor_dist = -99999;
  91.     [map_i makeAllPerform: @selector(feetToFloor)];
  92.     if (sb_floor_dist == -99999)
  93.     {
  94.         qprintf ("already on bottom floor");
  95.         return self;
  96.     }
  97.     qprintf ("down floor");
  98.     origin[2] += sb_floor_dist;
  99.     [quakeed_i updateCamera];
  100.     return self;
  101. }
  102.  
  103. /*
  104. ===============================================================================
  105.  
  106. UI TARGETS
  107.  
  108. ===============================================================================
  109. */
  110.  
  111. /*
  112. ============
  113. homeView
  114. ============
  115. */
  116. - homeView: sender
  117. {
  118.     xa = za = 0;
  119.     
  120.     [self matrixFromAngles];
  121.  
  122.     [quakeed_i updateAll];
  123.  
  124.     qprintf ("homed view angle");
  125.     
  126.     return self;
  127. }
  128.  
  129. - drawMode: sender
  130. {
  131.     drawmode = [sender selectedCol];
  132.     [quakeed_i updateCamera];
  133.     return self;
  134. }
  135.  
  136. - setDrawMode: (drawmode_t)mode
  137. {
  138.     drawmode = mode;
  139.     [mode_radio_i selectCellAt:0: mode];
  140.     [quakeed_i updateCamera];
  141.     return self;
  142. }
  143.  
  144. /*
  145. ===============================================================================
  146.  
  147. TRANSFORMATION METHODS
  148.  
  149. ===============================================================================
  150. */
  151.  
  152. - matrixFromAngles
  153. {
  154.     if (xa > M_PI*0.4)
  155.         xa = M_PI*0.4;
  156.     if (xa < -M_PI*0.4)
  157.         xa = -M_PI*0.4;
  158.         
  159. // vpn
  160.     matrix[2][0] = cos(xa)*cos(ya);
  161.     matrix[2][1] = cos(xa)*sin(ya);
  162.     matrix[2][2] = sin(xa);
  163.  
  164. // vup    
  165.     matrix[1][0] = cos(xa+M_PI/2)*cos(ya);
  166.     matrix[1][1] = cos(xa+M_PI/2)*sin(ya);
  167.     matrix[1][2] = sin(xa+M_PI/2);
  168.  
  169. // vright
  170.     CrossProduct (matrix[2], matrix[1], matrix[0]);
  171.  
  172.     return self;
  173. }
  174.  
  175.  
  176. - inverseTransform: (vec_t *)invec to:(vec_t *)outvec
  177. {
  178.     vec3_t        inverse[3];
  179.     vec3_t        temp;
  180.     int            i,j;
  181.     
  182.     for (i=0 ; i<3 ; i++)
  183.         for (j=0 ; j<3 ; j++)
  184.             inverse[i][j] = matrix[j][i];
  185.     
  186.     temp[0] = DotProduct(invec, inverse[0]);
  187.     temp[1] = DotProduct(invec, inverse[1]);
  188.     temp[2] = DotProduct(invec, inverse[2]);        
  189.  
  190.     VectorAdd (temp, origin, outvec);
  191.  
  192.     return self;
  193. }
  194.  
  195.  
  196.  
  197. /*
  198. ===============================================================================
  199.  
  200.                         DRAWING METHODS
  201.  
  202. ===============================================================================
  203. */
  204.  
  205. typedef struct
  206. {
  207.     vec3_t    trans;
  208.     int        clipflags;
  209.     vec3_t    screen;            // only valid if clipflags == 0
  210. } campt_t;
  211. #define    CLIP_RIGHT    1
  212. #define    CLIP_LEFT    2
  213. #define    CLIP_TOP    4
  214. #define    CLIP_BOTTOM    8
  215. #define    CLIP_FRONT    16
  216.  
  217. int        cam_cur;
  218. campt_t    campts[2];
  219.  
  220. vec3_t    r_matrix[3];
  221. vec3_t    r_origin;
  222. float    mid_x, mid_y;
  223. float    topscale = (240.0/3)/160;
  224. float    bottomscale = (240.0*2/3)/160;
  225.  
  226. extern    plane_t    frustum[5];
  227.  
  228. void MakeCampt (vec3_t in, campt_t *pt)
  229. {
  230.     vec3_t        temp;
  231.     float        scale;
  232.     
  233. // transform the points
  234.     VectorSubtract (in, r_origin, temp);
  235.     
  236.     pt->trans[0] = DotProduct(temp, r_matrix[0]);
  237.     pt->trans[1] = DotProduct(temp, r_matrix[1]);
  238.     pt->trans[2] = DotProduct(temp, r_matrix[2]);        
  239.  
  240. // check clip flags    
  241.     if (pt->trans[2] < 1)
  242.         pt->clipflags = CLIP_FRONT;
  243.     else
  244.         pt->clipflags = 0;
  245.  
  246.     if (pt->trans[0] > pt->trans[2])
  247.         pt->clipflags |= CLIP_RIGHT;
  248.     else if (-pt->trans[0] > pt->trans[2])
  249.         pt->clipflags |= CLIP_LEFT;
  250.         
  251.     if (pt->trans[1] > pt->trans[2]*topscale )
  252.         pt->clipflags |= CLIP_TOP;
  253.     else if (-pt->trans[1] > pt->trans[2]*bottomscale )
  254.         pt->clipflags |= CLIP_BOTTOM;
  255.         
  256.     if (pt->clipflags)
  257.         return;
  258.         
  259. // project
  260.     scale = mid_x/pt->trans[2];
  261.     pt->screen[0] = mid_x + pt->trans[0]*scale;
  262.     pt->screen[1] = mid_y + pt->trans[1]*scale;
  263. }
  264.  
  265.  
  266. void CameraMoveto(vec3_t p)
  267. {
  268.     campt_t    *pt;
  269.     
  270.     if (upath->numberOfPoints > 2048)
  271.         lineflush ();
  272.         
  273.     pt = &campts[cam_cur];
  274.     cam_cur ^= 1;
  275.     MakeCampt (p,pt);
  276.     if (!pt->clipflags)
  277.     {    // onscreen, so move there immediately
  278.         UPmoveto (upath, pt->screen[0], pt->screen[1]);
  279.     }
  280. }
  281.  
  282. void ClipLine (vec3_t p1, vec3_t p2, int planenum)
  283. {
  284.     float    d, d2, frac;
  285.     vec3_t    new;
  286.     plane_t    *pl;
  287.     float    scale;
  288.     
  289.     if (planenum == 5)
  290.     {    // draw it!
  291.         scale = mid_x/p1[2];
  292.         new[0] = mid_x + p1[0]*scale;
  293.         new[1] = mid_y + p1[1]*scale;
  294.         UPmoveto (upath, new[0], new[1]);
  295.         
  296.         scale = mid_x/p2[2];
  297.         new[0] = mid_x + p2[0]*scale;
  298.         new[1] = mid_y + p2[1]*scale;
  299.         UPlineto (upath, new[0], new[1]);
  300.         return;
  301.     }
  302.  
  303.     pl = &frustum[planenum];
  304.     
  305.     d = DotProduct (p1, pl->normal) - pl->dist;    
  306.     d2 = DotProduct (p2, pl->normal) - pl->dist;
  307.     if (d <= ON_EPSILON && d2 <= ON_EPSILON)
  308.     {    // off screen
  309.         return;
  310.     }
  311.     
  312.     if (d >= 0 && d2 >= 0)
  313.     {    // on front
  314.         ClipLine (p1, p2, planenum+1);
  315.         return;
  316.     }
  317.     
  318.     frac = d/(d-d2);
  319.     new[0] = p1[0] + frac*(p2[0]-p1[0]);
  320.     new[1] = p1[1] + frac*(p2[1]-p1[1]);
  321.     new[2] = p1[2] + frac*(p2[2]-p1[2]);
  322.     
  323.     if (d > 0)
  324.         ClipLine (p1, new, planenum+1);
  325.     else
  326.         ClipLine (new, p2, planenum+1);
  327. }
  328.  
  329. int    c_off, c_on, c_clip;
  330.  
  331. void CameraLineto(vec3_t p)
  332. {
  333.     campt_t        *p1, *p2;
  334.     int            bits;
  335.     
  336.     p2 = &campts[cam_cur];
  337.     cam_cur ^= 1;
  338.     p1 = &campts[cam_cur];
  339.     MakeCampt (p, p2);
  340.  
  341.     if (p1->clipflags & p2->clipflags)
  342.     {
  343.         c_off++;
  344.         return;        // entirely off screen
  345.     }
  346.     
  347.     bits = p1->clipflags | p2->clipflags;
  348.     
  349.     if (! bits )
  350.     {
  351.         c_on++;
  352.     UPmoveto (upath, p1->screen[0], p1->screen[1]);
  353.         UPlineto (upath, p2->screen[0], p2->screen[1]);
  354.         return;        // entirely on screen
  355.     }
  356.     
  357. // needs to be clipped
  358.     c_clip++;
  359.  
  360.     ClipLine (p1->trans, p2->trans, 0);
  361. }
  362.  
  363.  
  364. /*
  365. =============
  366. drawSolid
  367. =============
  368. */
  369. - drawSolid
  370. {
  371.     unsigned char    *planes[5];
  372.         
  373. //
  374. // draw it
  375. //
  376.     VectorCopy (origin, r_origin);
  377.     VectorCopy (matrix[0], r_matrix[0]);
  378.     VectorCopy (matrix[1], r_matrix[1]);
  379.     VectorCopy (matrix[2], r_matrix[2]);
  380.     
  381.     r_width = bounds.size.width;
  382.     r_height = bounds.size.height;
  383.     r_picbuffer = imagebuffer;
  384.     r_zbuffer = zbuffer;
  385.  
  386.     r_drawflat = (drawmode == dr_flat);
  387.     
  388.     REN_BeginCamera ();
  389.     REN_ClearBuffers ();
  390.  
  391. //
  392. // render the setbrushes
  393. //    
  394.     [map_i makeAllPerform: @selector(CameraRenderSelf)];
  395.  
  396. //
  397. // display the output
  398. //
  399.     [[self window] setBackingType:NX_RETAINED];
  400.     
  401.     planes[0] = (unsigned char *)imagebuffer;
  402.     NXDrawBitmap(
  403.         &bounds,  
  404.         r_width, 
  405.         r_height,
  406.         8,
  407.         3,
  408.         32,
  409.         r_width*4,
  410.         NO,
  411.         NO,
  412.         NX_RGBColorSpace,
  413.         planes
  414.     );
  415.  
  416.     NXPing ();
  417.     [[self window] setBackingType:NX_BUFFERED];
  418.     
  419.     
  420.     
  421.     return self;
  422. }
  423.  
  424.  
  425. /*
  426. ===================
  427. drawWire
  428. ===================
  429. */
  430. - drawWire: (const NXRect *)rect
  431. {
  432. // copy current info to globals for the C callbacks    
  433.     mid_x = bounds.size.width / 2;
  434.     mid_y = 2 * bounds.size.height / 3;
  435.  
  436.     VectorCopy (origin, r_origin);
  437.     VectorCopy (matrix[0], r_matrix[0]);
  438.     VectorCopy (matrix[1], r_matrix[1]);
  439.     VectorCopy (matrix[2], r_matrix[2]);
  440.     
  441.     r_width = bounds.size.width;
  442.     r_height = bounds.size.height;
  443.     r_picbuffer = imagebuffer;
  444.     r_zbuffer = zbuffer;
  445.  
  446.     REN_BeginCamera ();
  447.     
  448. // erase window
  449.     NXEraseRect (rect);
  450.     
  451. // draw all entities
  452.     linestart (0,0,0);
  453.     [map_i makeUnselectedPerform: @selector(CameraDrawSelf)];
  454.     lineflush ();
  455.  
  456.     return self;
  457. }
  458.  
  459. /*
  460. ===================
  461. drawSelf
  462. ===================
  463. */
  464. - drawSelf:(const NXRect *)rects :(int)rectCount
  465. {
  466.     static float    drawtime;    // static to shut up compiler warning
  467.  
  468.     if (timedrawing)
  469.         drawtime = I_FloatTime ();
  470.  
  471.     if (drawmode == dr_texture || drawmode == dr_flat)
  472.         [self drawSolid];
  473.     else
  474.         [self drawWire: rects];
  475.  
  476.     if (timedrawing)
  477.     {
  478.         NXPing ();
  479.         drawtime = I_FloatTime() - drawtime;
  480.         printf ("CameraView drawtime: %5.3f\n", drawtime);
  481.     }
  482.  
  483.     return self;
  484. }
  485.  
  486.  
  487. /*
  488. =============
  489. XYDrawSelf
  490. =============
  491. */
  492. - XYDrawSelf
  493. {
  494.     
  495.     PSsetrgbcolor (0,0,1.0);
  496.     PSsetlinewidth (0.15);
  497.     PSmoveto (origin[0]-16,origin[1]);
  498.     PSrlineto (16,8);
  499.     PSrlineto (16,-8);
  500.     PSrlineto (-16,-8);
  501.     PSrlineto (-16,8);
  502.     PSrlineto (32,0);
  503.     
  504.     PSmoveto (origin[0],origin[1]);
  505.     PSrlineto (64*cos(ya+M_PI/4), 64*sin(ya+M_PI/4));
  506.     PSmoveto (origin[0],origin[1]);
  507.     PSrlineto (64*cos(ya-M_PI/4), 64*sin(ya-M_PI/4));
  508.     
  509.     PSstroke ();
  510.     
  511.     return self;
  512. }
  513.  
  514. /*
  515. =============
  516. ZDrawSelf
  517. =============
  518. */
  519. - ZDrawSelf
  520. {
  521.     PSsetrgbcolor (0,0,1.0);
  522.     PSsetlinewidth (0.15);
  523.     
  524.     PSmoveto (-16,origin[2]);
  525.     PSrlineto (16,8);
  526.     PSrlineto (16,-8);
  527.     PSrlineto (-16,-8);
  528.     PSrlineto (-16,8);
  529.     PSrlineto (32,0);
  530.     
  531.     PSmoveto (-15,origin[2]-47);
  532.     PSrlineto (29,0);
  533.     PSrlineto (0,54);
  534.     PSrlineto (-29,0);
  535.     PSrlineto (0,-54);
  536.  
  537.     PSstroke ();
  538.  
  539.     return self;
  540. }
  541.  
  542.  
  543. /*
  544. ===============================================================================
  545.  
  546.                         XYZ mouse view methods
  547.  
  548. ===============================================================================
  549. */
  550.  
  551. /*
  552. ================
  553. modalMoveLoop
  554. ================
  555. */
  556. - modalMoveLoop: (NXPoint *)basept :(vec3_t)movemod : converter
  557. {
  558.     vec3_t        originbase;
  559.     NXEvent        *event;
  560.     NXPoint        newpt;
  561. //    NXPoint        brushpt;
  562.     vec3_t        delta;
  563. //    id            ent;
  564.     int            i;
  565. //    vec3_t        temp;
  566.     
  567.     qprintf ("moving camera position");
  568.  
  569.     VectorCopy (origin, originbase);    
  570.         
  571. //
  572. // modal event loop using instance drawing
  573. //
  574.     goto drawentry;
  575.  
  576.     while (event->type != NX_LMOUSEUP && event->type != NX_RMOUSEUP)
  577.     {
  578.         //
  579.         // calculate new point
  580.         //
  581.         newpt = event->location;
  582.         [converter convertPoint:&newpt  fromView:NULL];
  583.                 
  584.         delta[0] = newpt.x-basept->x;
  585.         delta[1] = newpt.y-basept->y;
  586.         delta[2] = delta[1];        // height change
  587.         
  588.         for (i=0 ; i<3 ; i++)
  589.             origin[i] = originbase[i]+movemod[i]*delta[i];
  590.         
  591. #if 0    // FIXME    
  592.         //
  593.         // if command is down, look towards brush or entity
  594.         //
  595.         if (event->flags & NX_SHIFTMASK)
  596.         {
  597.             ent = [quakemap_i selectedEntity];
  598.             if (ent)
  599.             {
  600.                 [ent origin: temp];
  601.                 brushpt.x = temp[0];
  602.                 brushpt.y = temp[1];
  603.             }
  604.             else
  605.                 brushpt = [brush_i centerPoint];
  606.             ya = atan2 (brushpt.y - newpt.y, brushpt.x - newpt.x);
  607.             [self matrixFromAngles];
  608.         }
  609. #endif
  610.                     
  611. drawentry:
  612.         //
  613.         // instance draw new frame
  614.         //
  615.         [quakeed_i newinstance];
  616.         [self display];
  617.         
  618.         event = [NXApp getNextEvent: NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK
  619.             | NX_RMOUSEUPMASK | NX_RMOUSEDRAGGEDMASK | NX_APPDEFINEDMASK];
  620.     
  621.         if (event->type == NX_KEYDOWN)
  622.         {
  623.             [self _keyDown: event];
  624.             [self display];
  625.             goto drawentry;
  626.         }
  627.         
  628.     }
  629.  
  630.     return self;
  631. }
  632.  
  633. //============================================================================
  634.  
  635. /*
  636. ===============
  637. XYmouseDown
  638. ===============
  639. */
  640. - (BOOL)XYmouseDown: (NXPoint *)pt flags:(int)flags    // return YES if brush handled
  641. {    
  642.     vec3_t        movemod;
  643.     
  644.     if (fabs(pt->x - origin[0]) > 16
  645.     || fabs(pt->y - origin[1]) > 16 )
  646.         return NO;
  647.     
  648. #if 0    
  649.     if (flags & NX_ALTERNATEMASK)
  650.     {    // up / down drag
  651.         movemod[0] = 0;
  652.         movemod[1] = 0;
  653.         movemod[2] = 1;
  654.     }
  655.     else
  656. #endif
  657.     {    
  658.         movemod[0] = 1;
  659.         movemod[1] = 1;
  660.         movemod[2] = 0;
  661.     }
  662.     
  663.     [self modalMoveLoop: pt : movemod : xyview_i];
  664.     
  665.     return YES;
  666. }
  667.  
  668.  
  669. /*
  670. ===============
  671. ZmouseDown
  672. ===============
  673. */
  674. - (BOOL)ZmouseDown: (NXPoint *)pt flags:(int)flags    // return YES if brush handled
  675. {    
  676.     vec3_t        movemod;
  677.     
  678.     if (fabs(pt->y - origin[2]) > 16
  679.     || pt->x < -8 || pt->x > 8 )
  680.         return NO;
  681.         
  682.     movemod[0] = 0;
  683.     movemod[1] = 0;
  684.     movemod[2] = 1;
  685.     
  686.     [self modalMoveLoop: pt : movemod : zview_i];
  687.  
  688.     return YES;
  689. }
  690.  
  691.  
  692. //=============================================================================
  693.  
  694. /*
  695. ===================
  696. viewDrag:
  697. ===================
  698. */
  699. - viewDrag:(NXPoint *)pt
  700. {
  701.     float    dx,dy;
  702.     NXEvent        *event;
  703.     NXPoint        newpt;
  704.     
  705. //
  706. // modal event loop using instance drawing
  707. //
  708.     goto drawentry;
  709.  
  710.     while (event->type != NX_RMOUSEUP)
  711.     {
  712.         //
  713.         // calculate new point
  714.         //
  715.         newpt = event->location;
  716.         [self convertPoint:&newpt  fromView:NULL];
  717.  
  718.         dx = newpt.x - pt->x;
  719.         dy = newpt.y - pt->y;
  720.         *pt = newpt;
  721.     
  722.         ya -= dx/bounds.size.width*M_PI/2 * 4;
  723.         xa += dy/bounds.size.width*M_PI/2 * 4;
  724.     
  725.         [self matrixFromAngles];
  726.         
  727. drawentry:
  728.         [quakeed_i newinstance];
  729.         [self display];
  730.         
  731.         event = [NXApp getNextEvent: 
  732.             NX_KEYDOWNMASK | NX_RMOUSEUPMASK | NX_RMOUSEDRAGGEDMASK];
  733.     
  734.         if (event->type == NX_KEYDOWN)
  735.         {
  736.             [self _keyDown: event];
  737.             [self display];
  738.             goto drawentry;
  739.         }
  740.         
  741.     }
  742.  
  743.     return self;
  744. }
  745.  
  746.  
  747. //=============================================================================
  748.  
  749. /*
  750. ===================
  751. mouseDown
  752. ===================
  753. */
  754. - mouseDown:(NXEvent *)theEvent
  755. {
  756.     NXPoint            pt;
  757.     int                i;
  758.     vec3_t            p1, p2;
  759.     float            forward, right, up;
  760.     int                flags;
  761.         
  762.     pt = theEvent->location;
  763.     
  764.     [self convertPoint:&pt  fromView:NULL];
  765.  
  766.     VectorCopy (origin, p1);
  767.     forward = 160;
  768.     right = pt.x - 160;
  769.     up = pt.y - 240*2/3;
  770.     for (i=0 ; i<3 ; i++)
  771.         p2[i] = forward*matrix[2][i] + up*matrix[1][i] + right*matrix[0][i];
  772.     for (i=0 ; i<3 ; i++)
  773.         p2[i] = p1[i] + 100*p2[i];
  774.  
  775.     flags = theEvent->flags & (NX_SHIFTMASK | NX_CONTROLMASK | NX_ALTERNATEMASK | NX_COMMANDMASK);
  776.  
  777. //
  778. // bare click to select a texture
  779. //
  780.     if (flags == 0)
  781.     {
  782.         [map_i getTextureRay: p1 : p2];
  783.         return self;
  784.     }
  785.     
  786. //
  787. // shift click to select / deselect a brush from the world
  788. //
  789.     if (flags == NX_SHIFTMASK)
  790.     {        
  791.         [map_i selectRay: p1 : p2 : NO];
  792.         return self;
  793.     }
  794.  
  795.     
  796. //
  797. // cmd-shift click to set a target/targetname entity connection
  798. //
  799.     if (flags == (NX_SHIFTMASK|NX_COMMANDMASK) )
  800.     {
  801.         [map_i entityConnect: p1 : p2];
  802.         return self;
  803.     }
  804.  
  805. //
  806. // alt click = set entire brush texture
  807. //
  808.     if (flags == NX_ALTERNATEMASK)
  809.     {
  810.         if (drawmode != dr_texture)
  811.         {
  812.             qprintf ("No texture setting except in texture mode!\n");
  813.             NopSound ();
  814.             return self;
  815.         }        
  816.         [map_i setTextureRay: p1 : p2 : YES];
  817.         [quakeed_i updateAll];
  818.         return self;
  819.     }
  820.         
  821. //
  822. // ctrl-alt click = set single face texture
  823. //
  824.     if (flags == (NX_CONTROLMASK | NX_ALTERNATEMASK) )
  825.     {
  826.         if (drawmode != dr_texture)
  827.         {
  828.             qprintf ("No texture setting except in texture mode!\n");
  829.             NopSound ();
  830.             return self;
  831.         }
  832.         [map_i setTextureRay: p1 : p2 : NO];
  833.         [quakeed_i updateAll];
  834.         return self;
  835.     }
  836.         
  837.  
  838.     qprintf ("bad flags for click");
  839.     NopSound ();
  840.     
  841.     return self;
  842. }
  843.  
  844. /*
  845. ===================
  846. rightMouseDown
  847. ===================
  848. */
  849. - rightMouseDown:(NXEvent *)theEvent
  850. {
  851.     NXPoint            pt;
  852.     int                flags;
  853.         
  854.     pt = theEvent->location;
  855.     
  856.     [self convertPoint:&pt  fromView:NULL];
  857.  
  858.     flags = theEvent->flags & (NX_SHIFTMASK | NX_CONTROLMASK | NX_ALTERNATEMASK | NX_COMMANDMASK);
  859.  
  860. //
  861. // click = drag camera
  862. //
  863.     if (flags == 0)
  864.     {
  865.         qprintf ("looking");
  866.         [self viewDrag: &pt];
  867.         qprintf ("");
  868.         return self;
  869.     }        
  870.  
  871.     qprintf ("bad flags for click");
  872.     NopSound ();
  873.     
  874.     return self;
  875. }
  876.  
  877. /*
  878. ===============
  879. keyDown
  880. ===============
  881. */
  882.  
  883. #define    KEY_RIGHTARROW        0xae
  884. #define    KEY_LEFTARROW        0xac
  885. #define    KEY_UPARROW            0xad
  886. #define    KEY_DOWNARROW        0xaf
  887.  
  888.  
  889. - _keyDown: (NXEvent *)theEvent
  890. {
  891.     int    ch;
  892.     
  893.     ch = tolower(theEvent->data.key.charCode);
  894.     
  895.     switch (ch)
  896.     {
  897.     case 13:
  898.         return self;
  899.         
  900.     case 'a':
  901.     case 'A':
  902.         xa += M_PI/8;
  903.         [self matrixFromAngles];
  904.         [quakeed_i updateCamera];
  905.         return self;
  906.         
  907.     case 'z':
  908.     case 'Z':
  909.         xa -= M_PI/8;
  910.         [self matrixFromAngles];
  911.         [quakeed_i updateCamera];
  912.         return self;
  913.         
  914.     case KEY_RIGHTARROW:
  915.         ya -= M_PI*move/(64*2);
  916.         [self matrixFromAngles];
  917.         [quakeed_i updateCamera];
  918.         break;
  919.         
  920.     case KEY_LEFTARROW:
  921.         ya += M_PI*move/(64*2);
  922.         [self matrixFromAngles];
  923.         [quakeed_i updateCamera];
  924.         break;
  925.         
  926.     case KEY_UPARROW:
  927.         origin[0] += move*cos(ya);
  928.         origin[1] += move*sin(ya);
  929.         [quakeed_i updateCamera];
  930.         break;
  931.         
  932.     case KEY_DOWNARROW:
  933.         origin[0] -= move*cos(ya);
  934.         origin[1] -= move*sin(ya);
  935.         [quakeed_i updateCamera];
  936.         break;
  937.         
  938.     case '.':
  939.         origin[0] += move*cos(ya-M_PI_2);
  940.         origin[1] += move*sin(ya-M_PI_2);
  941.         [quakeed_i updateCamera];
  942.         break;
  943.         
  944.     case ',':
  945.         origin[0] -= move*cos(ya-M_PI_2);
  946.         origin[1] -= move*sin(ya-M_PI_2);
  947.         [quakeed_i updateCamera];
  948.         break;
  949.         
  950.     case 'd':
  951.     case 'D':
  952.         origin[2] += move;
  953.         [quakeed_i updateCamera];
  954.         break;
  955.         
  956.     case 'c':
  957.     case 'C':
  958.         origin[2] -= move;
  959.         [quakeed_i updateCamera];
  960.         break;
  961.         
  962.     }
  963.  
  964.     
  965.     return self;
  966. }
  967.  
  968.  
  969. @end
  970.  
  971.