CameraView.m 16 KB

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