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