]> icculus.org git repositories - btb/d2x.git/blob - main/editor/medmisc.c
remove rcs tags
[btb/d2x.git] / main / editor / medmisc.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Miscellaneous functions stripped out of med.c
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "conf.h"
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #ifdef __MSDOS__
29 #include <process.h>
30 #endif
31
32 #include "gr.h"
33 #include "ui.h"
34 #include "3d.h"
35
36 #include "u_mem.h"
37 #include "error.h"
38 #include "mono.h"
39 #include "key.h"
40 #include "func.h"
41
42 #include "inferno.h"
43 #include "editor/editor.h"
44 #include "segment.h"
45
46 #include "render.h"
47 #include "screens.h"
48 #include "object.h"
49
50 #include "texpage.h"            // For texpage_goto_first
51 #include "meddraw.h"            // For draw_World
52 #include "game.h"
53
54 //return 2d distance, i.e, sqrt(x*x + y*y)
55 #ifdef __WATCOMC__
56 long dist_2d(long x,long y);
57
58 #pragma aux dist_2d parm [eax] [ebx] value [eax] modify [ecx edx] = \
59         "imul   eax"                    \
60         "xchg   ebx,eax"                \
61         "mov    ecx,edx"                \
62         "imul   eax"                    \
63         "add    eax,ebx"                \
64         "adc    edx,ecx"                \
65         "call   quad_sqrt";
66 #else
67 #include <math.h>
68 long dist_2d(long x,long y) {
69         return (long)sqrt((double)x * (double)x + (double)y * (double)y);
70 }
71 #endif
72
73 // Given mouse movement in dx, dy, returns a 3x3 rotation matrix in RotMat.
74 // Taken from Graphics Gems III, page 51, "The Rolling Ball"
75
76 void GetMouseRotation( int idx, int idy, vms_matrix * RotMat )
77 {
78         fix dr, cos_theta, sin_theta, denom, cos_theta1;
79         fix Radius = i2f(100);
80         fix dx,dy;
81         fix dxdr,dydr;
82
83         idy *= -1;
84
85         dx = i2f(idx); dy = i2f(idy);
86
87         dr = dist_2d(dx,dy);
88
89         denom = dist_2d(Radius,dr);
90
91         cos_theta = fixdiv(Radius,denom);
92         sin_theta = fixdiv(dr,denom);
93
94         cos_theta1 = f1_0 - cos_theta;
95
96         dxdr = fixdiv(dx,dr);
97         dydr = fixdiv(dy,dr);
98
99         RotMat->rvec.x = cos_theta + fixmul(fixmul(dydr,dydr),cos_theta1);
100         RotMat->uvec.x = - fixmul(fixmul(dxdr,dydr),cos_theta1);
101         RotMat->fvec.x = fixmul(dxdr,sin_theta);
102
103         RotMat->rvec.y = RotMat->uvec.x;
104         RotMat->uvec.y = cos_theta + fixmul(fixmul(dxdr,dxdr),cos_theta1);
105         RotMat->fvec.y = fixmul(dydr,sin_theta);
106
107         RotMat->rvec.z = -RotMat->fvec.x;
108         RotMat->uvec.z = -RotMat->fvec.y;
109         RotMat->fvec.z = cos_theta;
110
111 }
112
113 int Gameview_lockstep;          //if set, view is locked to Curseg
114
115 int ToggleLockstep()
116 {
117         Gameview_lockstep = !Gameview_lockstep;
118     if (Gameview_lockstep == 0) {
119         if (last_keypress != KEY_L)
120             diagnostic_message("[L] - Lock mode OFF");
121         else
122             diagnostic_message("Lock mode OFF");
123     }
124     if (Gameview_lockstep) {
125         if (last_keypress != KEY_L)
126             diagnostic_message("[L] Lock mode ON");
127         else
128             diagnostic_message("Lock mode ON");
129
130       Cursegp = &Segments[ConsoleObject->segnum];
131                 med_create_new_segment_from_cursegp();
132                 set_view_target_from_segment(Cursegp);
133                 Update_flags = UF_ED_STATE_CHANGED;
134         }
135     return Gameview_lockstep;
136 }
137
138 int medlisp_delete_segment(void)
139 {
140     if (!med_delete_segment(Cursegp)) {
141         if (Lock_view_to_cursegp)
142             set_view_target_from_segment(Cursegp);
143                   autosave_mine(mine_filename);
144                   strcpy(undo_status[Autosave_count], "Delete Segment UNDONE.");
145         Update_flags |= UF_WORLD_CHANGED;
146         mine_changed = 1;
147         diagnostic_message("Segment deleted.");
148         warn_if_concave_segments();     // This could be faster -- just check if deleted segment was concave, warn accordingly
149     }
150
151         return 1;
152 }
153
154 int medlisp_scale_segment(void)
155 {
156         vms_matrix      rotmat;
157         vms_vector      scale;
158
159         scale.x = fl2f((float) func_get_param(0));
160         scale.y = fl2f((float) func_get_param(1));
161         scale.z = fl2f((float) func_get_param(2));
162         med_create_new_segment(&scale);
163         med_rotate_segment(Cursegp,vm_angles_2_matrix(&rotmat,&Seg_orientation));
164         Update_flags |= UF_WORLD_CHANGED;
165         mine_changed = 1;
166
167         return 1;
168 }
169
170 int medlisp_rotate_segment(void)
171 {
172         vms_matrix      rotmat;
173
174         Seg_orientation.p = func_get_param(0);
175         Seg_orientation.b = func_get_param(1);
176         Seg_orientation.h = func_get_param(2);
177         med_rotate_segment(Cursegp,vm_angles_2_matrix(&rotmat,&Seg_orientation));
178         Update_flags |= UF_WORLD_CHANGED | UF_VIEWPOINT_MOVED;
179         mine_changed = 1;
180         return 1;
181 }
182
183 int ToggleLockViewToCursegp(void)
184 {
185         Lock_view_to_cursegp = !Lock_view_to_cursegp;
186         Update_flags = UF_ED_STATE_CHANGED;
187         if (Lock_view_to_cursegp) {
188         if (last_keypress != KEY_V+KEY_CTRLED)
189             diagnostic_message("[ctrl-V] View locked to Cursegp.");
190         else
191             diagnostic_message("View locked to Cursegp.");
192         set_view_target_from_segment(Cursegp);
193     } else {
194         if (last_keypress != KEY_V+KEY_CTRLED)
195             diagnostic_message("[ctrl-V] View not locked to Cursegp.");
196         else
197             diagnostic_message("View not locked to Cursegp.");
198     }
199     return Lock_view_to_cursegp;
200 }
201
202 int ToggleDrawAllSegments()
203 {
204         Draw_all_segments = !Draw_all_segments;
205         Update_flags = UF_ED_STATE_CHANGED;
206     if (Draw_all_segments == 1) {
207         if (last_keypress != KEY_A+KEY_CTRLED)
208             diagnostic_message("[ctrl-A] Draw all segments ON.");
209         else
210             diagnostic_message("Draw all segments ON.");
211     }
212     if (Draw_all_segments == 0) {
213         if (last_keypress != KEY_A+KEY_CTRLED)
214             diagnostic_message("[ctrl-A] Draw all segments OFF.");
215         else
216             diagnostic_message("Draw all segments OFF.");
217     }
218     return Draw_all_segments;
219 }
220
221 int     Big_depth=6;
222
223 int IncreaseDrawDepth(void)
224 {
225         Big_depth++;
226         Update_flags = UF_ED_STATE_CHANGED;
227         return 1;
228 }
229
230 int DecreaseDrawDepth(void)
231 {
232         if (Big_depth > 1) {
233                 Big_depth--;
234                 Update_flags = UF_ED_STATE_CHANGED;
235         }
236         return 1;
237 }
238
239
240 int ToggleCoordAxes()
241 {
242                         //  Toggle display of coordinate axes.
243         Show_axes_flag = !Show_axes_flag;
244         LargeView.ev_changed = 1;
245     if (Show_axes_flag == 1) {
246         if (last_keypress != KEY_D+KEY_CTRLED)
247             diagnostic_message("[ctrl-D] Coordinate axes ON.");
248         else
249             diagnostic_message("Coordinate axes ON.");
250     }
251     if (Show_axes_flag == 0) {
252         if (last_keypress != KEY_D+KEY_CTRLED)
253             diagnostic_message("[ctrl-D] Coordinate axes OFF.");
254         else
255             diagnostic_message("Coordinate axes OFF.");
256     }
257     return Show_axes_flag;
258 }
259
260 int med_keypad_goto_prev()
261 {
262         ui_pad_goto_prev();
263         return 0;
264 }
265
266 int med_keypad_goto_next()
267 {
268         ui_pad_goto_next();
269         return 0;
270 }
271
272 int med_keypad_goto()
273 {
274         ui_pad_goto(func_get_param(0));
275         return 0;
276 }
277
278 int render_3d_in_big_window=0;
279
280 int medlisp_update_screen()
281 {
282         int vn;
283
284 if (!render_3d_in_big_window)
285         for (vn=0;vn<N_views;vn++)
286                 if (Views[vn]->ev_changed || (Update_flags & (UF_WORLD_CHANGED|UF_VIEWPOINT_MOVED|UF_ED_STATE_CHANGED))) {
287                         draw_world(Views[vn]->ev_canv,Views[vn],Cursegp,Big_depth);
288                         Views[vn]->ev_changed = 0;
289                 }
290
291         if (Update_flags & (UF_WORLD_CHANGED|UF_GAME_VIEW_CHANGED|UF_ED_STATE_CHANGED)) {
292                 grs_canvas temp_canvas;
293                 grs_canvas *render_canv,*show_canv;
294                 
295                 if (render_3d_in_big_window) {
296                         
297                         gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0,
298                                 LargeView.ev_canv->cv_bitmap.bm_w,LargeView.ev_canv->cv_bitmap.bm_h);
299
300                         render_canv = &temp_canvas;
301                         show_canv = LargeView.ev_canv;
302
303                 }
304                 else {
305                         render_canv     = VR_offscreen_buffer;
306                         show_canv       = Canv_editor_game;
307                 }
308
309                 gr_set_current_canvas(render_canv);
310                 render_frame(0, 0);
311
312                 Assert(render_canv->cv_bitmap.bm_w == show_canv->cv_bitmap.bm_w &&
313                                  render_canv->cv_bitmap.bm_h == show_canv->cv_bitmap.bm_h);
314
315                 ui_mouse_hide();
316                 gr_bm_ubitblt(show_canv->cv_bitmap.bm_w,show_canv->cv_bitmap.bm_h,
317                                                   0,0,0,0,&render_canv->cv_bitmap,&show_canv->cv_bitmap);
318                 ui_mouse_show();
319         }
320
321         Update_flags=UF_NONE;       //clear flags
322
323         return 1;
324 }
325
326 void med_point_2_vec(grs_canvas *canv,vms_vector *v,short sx,short sy)
327 {
328         gr_set_current_canvas(canv);
329
330         g3_start_frame();
331         g3_set_view_matrix(&Viewer->pos,&Viewer->orient,Render_zoom);
332
333         g3_point_2_vec(v,sx,sy);
334
335         g3_end_frame();
336 }
337
338
339  
340 void draw_world_from_game(void)
341 {
342         if (ModeFlag == 2)
343                 draw_world(Views[0]->ev_canv,Views[0],Cursegp,Big_depth);
344 }
345
346 int UndoCommand()
347 {   int u;
348
349     u = undo();
350     if (Lock_view_to_cursegp)
351                 set_view_target_from_segment(Cursegp);
352     if (u == 0) {
353         if (Autosave_count==9) diagnostic_message(undo_status[0]);
354             else
355                 diagnostic_message(undo_status[Autosave_count+1]);
356         }
357         else
358          if (u == 1) diagnostic_message("Can't Undo.");
359         else
360          if (u == 2) diagnostic_message("Can't Undo - Autosave OFF");
361     Update_flags |= UF_WORLD_CHANGED;
362          mine_changed = 1;
363     warn_if_concave_segments();
364     return 1;
365 }
366
367
368 int ToggleAutosave()
369 {
370         Autosave_flag = !Autosave_flag;
371         if (Autosave_flag == 1) 
372       diagnostic_message("Autosave ON.");
373         else
374                 diagnostic_message("Autosave OFF.");
375    return Autosave_flag;
376 }
377
378
379 int AttachSegment()
380 {
381    if (med_attach_segment(Cursegp, &New_segment, Curside, AttachSide)==4) // Used to be WBACK instead of Curside
382         diagnostic_message("Cannot attach segment - already a connection on current side.");
383    else {
384                 if (Lock_view_to_cursegp)
385                         set_view_target_from_segment(Cursegp);
386                 vm_angvec_make(&Seg_orientation,0,0,0);
387                 Curside = WBACK;
388                 Update_flags |= UF_WORLD_CHANGED;
389            autosave_mine(mine_filename);
390            strcpy(undo_status[Autosave_count], "Attach Segment UNDONE.\n");
391                 mine_changed = 1;
392                 warn_if_concave_segment(Cursegp);
393       }
394         return 1;
395 }
396
397 int ForceTotalRedraw()
398 {
399         Update_flags = UF_ALL;
400         return 1;
401 }
402
403
404 #if ORTHO_VIEWS
405 int SyncLargeView()
406 {
407         // Make large view be same as one of the orthogonal views.
408         Large_view_index = (Large_view_index + 1) % 3;  // keep in 0,1,2 for top, front, right
409         switch (Large_view_index) {
410                 case 0: LargeView.ev_matrix = TopView.ev_matrix; break;
411                 case 1: LargeView.ev_matrix = FrontView.ev_matrix; break;
412                 case 2: LargeView.ev_matrix = RightView.ev_matrix; break;
413         }
414         Update_flags |= UF_VIEWPOINT_MOVED;
415         return 1;
416 }
417 #endif
418
419 int DeleteCurSegment()
420 {
421         // Delete current segment.
422     med_delete_segment(Cursegp);
423     autosave_mine(mine_filename);
424     strcpy(undo_status[Autosave_count], "Delete segment UNDONE.");
425     if (Lock_view_to_cursegp)
426                 set_view_target_from_segment(Cursegp);
427     Update_flags |= UF_WORLD_CHANGED;
428     mine_changed = 1;
429     diagnostic_message("Segment deleted.");
430     warn_if_concave_segments();     // This could be faster -- just check if deleted segment was concave, warn accordingly
431
432     return 1;
433 }
434
435 int CreateDefaultNewSegment()
436 {
437         // Create a default segment for New_segment.
438         vms_vector  tempvec;
439         med_create_new_segment(vm_vec_make(&tempvec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE));
440         mine_changed = 1;
441
442         return 1;
443 }
444
445 int CreateDefaultNewSegmentandAttach()
446 {
447         CreateDefaultNewSegment();
448         AttachSegment();
449
450         return 1;
451 }
452
453 int ExchangeMarkandCurseg()
454 {
455         // If Markedsegp != Cursegp, and Markedsegp->segnum != -1, exchange Markedsegp and Cursegp
456         if (Markedsegp)
457                 if (Markedsegp->segnum != -1) {
458                         segment *tempsegp;
459                         int     tempside;
460                         tempsegp = Markedsegp;  Markedsegp = Cursegp;   Cursegp = tempsegp;
461                         tempside = Markedside;  Markedside = Curside;   Curside = tempside;
462                         med_create_new_segment_from_cursegp();
463                         Update_flags |= UF_ED_STATE_CHANGED;
464                         mine_changed = 1;
465                 }
466         return 1;
467 }
468
469 int medlisp_add_segment()
470 {
471         AttachSegment();
472 //segment *ocursegp = Cursegp;
473 //      med_attach_segment(Cursegp, &New_segment, Curside, WFRONT); // Used to be WBACK instead of Curside
474 //med_propagate_tmaps_to_segments(ocursegp,Cursegp);
475 //      set_view_target_from_segment(Cursegp);
476 ////    while (!vm_angvec_make(&Seg_orientation,0,0,0));
477 //      Curside = WBACK;
478
479         return 1;
480 }
481
482
483 int ClearSelectedList(void)
484 {
485         N_selected_segs = 0;
486         Update_flags |= UF_WORLD_CHANGED;
487
488         diagnostic_message("Selected list cleared.");
489
490         return 1;
491 }
492
493
494 int ClearFoundList(void)
495 {
496         N_found_segs = 0;
497         Update_flags |= UF_WORLD_CHANGED;
498
499         diagnostic_message("Found list cleared.");
500
501         return 1;
502 }
503
504
505
506
507 // ---------------------------------------------------------------------------------------------------
508 // Do chase mode.
509 //      View current segment (Cursegp) from the previous segment.
510 void set_chase_matrix(segment *sp)
511 {
512         int                     v;
513         vms_vector      forvec = ZERO_VECTOR, upvec;
514         vms_vector      tv = ZERO_VECTOR;
515         segment         *psp;
516
517         // move back two segments, if possible, else move back one, if possible, else use current
518         if (IS_CHILD(sp->children[WFRONT])) {
519                 psp = &Segments[sp->children[WFRONT]];
520                 if (IS_CHILD(psp->children[WFRONT]))
521                         psp = &Segments[psp->children[WFRONT]];
522         } else
523                 psp = sp;
524
525         for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++)
526                 vm_vec_add2(&forvec,&Vertices[sp->verts[v]]);
527         vm_vec_scale(&forvec,F1_0/MAX_VERTICES_PER_SEGMENT);
528
529         for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++)
530                 vm_vec_add2(&tv,&Vertices[psp->verts[v]]);
531         vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT);
532
533         Ed_view_target = forvec;
534
535         vm_vec_sub2(&forvec,&tv);
536
537         extract_up_vector_from_segment(psp,&upvec);
538
539         if (!((forvec.x == 0) && (forvec.y == 0) && (forvec.z == 0)))
540                 vm_vector_2_matrix(&LargeView.ev_matrix,&forvec,&upvec,NULL);
541 }
542
543
544
545 // ---------------------------------------------------------------------------------------------------
546 void set_view_target_from_segment(segment *sp)
547 {
548         vms_vector      tv = ZERO_VECTOR;
549         int                     v;
550
551         if (Funky_chase_mode)
552                 {
553                 mprintf((0, "Trying to set chase mode\n"));
554                 //set_chase_matrix(sp);
555                 }
556         else {
557                 for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++)
558                         vm_vec_add2(&tv,&Vertices[sp->verts[v]]);
559
560                 vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT);
561
562                 Ed_view_target = tv;
563
564         }
565         Update_flags |= UF_VIEWPOINT_MOVED;
566
567 }
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584