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