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