Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
/*
2
 * Portions of this file are copyright Rebirth contributors and licensed as
3
 * described in COPYING.txt.
4
 * Portions of this file are copyright Parallax Software and licensed
5
 * according to the Parallax license below.
6
 * See COPYING.txt for license details.
7
 
8
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9
SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12
IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14
FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17
COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Miscellaneous functions stripped out of med.c
23
 *
24
 */
25
 
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <stdarg.h>
29
#include <string.h>
30
#include "gr.h"
31
#include "ui.h"
32
#include "3d.h"
33
#include "u_mem.h"
34
#include "dxxerror.h"
35
#include "key.h"
36
#include "mouse.h"
37
#include "func.h"
38
#include "inferno.h"
39
#include "editor/editor.h"
40
#include "editor/esegment.h"
41
#include "editor/medmisc.h"
42
#include "gameseg.h"
43
#include "segment.h"
44
#include "render.h"
45
#include "screens.h"
46
#include "object.h"
47
#include "texpage.h"            // For texpage_goto_first
48
#include "meddraw.h"            // For draw_World
49
#include "game.h"
50
#include "kdefs.h"
51
 
52
#if DXX_USE_OGL
53
#include "ogl_init.h"
54
#endif
55
 
56
#include "compiler-range_for.h"
57
 
58
//return 2d distance, i.e, sqrt(x*x + y*y)
59
#ifdef __WATCOMC__
60
long dist_2d(long x,long y);
61
 
62
#pragma aux dist_2d parm [eax] [ebx] value [eax] modify [ecx edx] = \
63
        "imul   eax"                    \
64
        "xchg   ebx,eax"                \
65
        "mov    ecx,edx"                \
66
        "imul   eax"                    \
67
        "add    eax,ebx"                \
68
        "adc    edx,ecx"                \
69
        "call   quad_sqrt";
70
#else
71
#include <math.h>
72
static long dist_2d(long x,long y) {
73
        return sqrt(static_cast<double>(x) * static_cast<double>(x) + static_cast<double>(y) * static_cast<double>(y));
74
}
75
#endif
76
 
77
// Given mouse movement in dx, dy, returns a 3x3 rotation matrix in RotMat.
78
// Taken from Graphics Gems III, page 51, "The Rolling Ball"
79
 
80
void GetMouseRotation( int idx, int idy, vms_matrix * RotMat )
81
{
82
        fix dr, cos_theta, sin_theta, denom, cos_theta1;
83
        fix Radius = i2f(100);
84
        fix dx,dy;
85
        fix dxdr,dydr;
86
 
87
        idy *= -1;
88
 
89
        dx = i2f(idx); dy = i2f(idy);
90
 
91
        dr = dist_2d(dx,dy);
92
 
93
        denom = dist_2d(Radius,dr);
94
 
95
        cos_theta = fixdiv(Radius,denom);
96
        sin_theta = fixdiv(dr,denom);
97
 
98
        cos_theta1 = f1_0 - cos_theta;
99
 
100
        dxdr = fixdiv(dx,dr);
101
        dydr = fixdiv(dy,dr);
102
 
103
        RotMat->rvec.x = cos_theta + fixmul(fixmul(dydr,dydr),cos_theta1);
104
        RotMat->uvec.x = - fixmul(fixmul(dxdr,dydr),cos_theta1);
105
        RotMat->fvec.x = fixmul(dxdr,sin_theta);
106
 
107
        RotMat->rvec.y = RotMat->uvec.x;
108
        RotMat->uvec.y = cos_theta + fixmul(fixmul(dxdr,dxdr),cos_theta1);
109
        RotMat->fvec.y = fixmul(dydr,sin_theta);
110
 
111
        RotMat->rvec.z = -RotMat->fvec.x;
112
        RotMat->uvec.z = -RotMat->fvec.y;
113
        RotMat->fvec.z = cos_theta;
114
 
115
}
116
 
117
int Gameview_lockstep;          //if set, view is locked to Curseg
118
 
119
int ToggleLockstep()
120
{
121
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
122
        auto &Vertices = LevelSharedVertexState.get_vertices();
123
        Gameview_lockstep = !Gameview_lockstep;
124
    if (Gameview_lockstep == 0) {
125
        //if (keypress != KEY_L)
126
            diagnostic_message("[Ctrl-L] - Lock mode OFF");
127
        //else
128
        //    diagnostic_message("Lock mode OFF");
129
    }
130
    if (Gameview_lockstep) {
131
        //if (keypress != KEY_L)
132
            diagnostic_message("[Ctrl-L] Lock mode ON");
133
        //else
134
        //    diagnostic_message("Lock mode ON");
135
 
136
                Cursegp = imsegptridx(ConsoleObject->segnum);
137
                med_create_new_segment_from_cursegp();
138
                auto &vcvertptr = Vertices.vcptr;
139
                set_view_target_from_segment(vcvertptr, Cursegp);
140
                Update_flags = UF_ED_STATE_CHANGED;
141
        }
142
    return Gameview_lockstep;
143
}
144
 
145
int medlisp_delete_segment(void)
146
{
147
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
148
        auto &Vertices = LevelSharedVertexState.get_vertices();
149
    if (!med_delete_segment(Cursegp)) {
150
        if (Lock_view_to_cursegp)
151
                {
152
                        auto &vcvertptr = Vertices.vcptr;
153
            set_view_target_from_segment(vcvertptr, Cursegp);
154
                }
155
                  autosave_mine(mine_filename);
156
                undo_status[Autosave_count] = "Delete Segment UNDONE.";
157
        Update_flags |= UF_WORLD_CHANGED;
158
        mine_changed = 1;
159
        diagnostic_message("Segment deleted.");
160
        warn_if_concave_segments();     // This could be faster -- just check if deleted segment was concave, warn accordingly
161
    }
162
 
163
        return 1;
164
}
165
 
166
int medlisp_scale_segment(void)
167
{
168
        vms_vector      scale;
169
 
170
        scale.x = fl2f(static_cast<float>(func_get_param(0)));
171
        scale.y = fl2f(static_cast<float>(func_get_param(1)));
172
        scale.z = fl2f(static_cast<float>(func_get_param(2)));
173
        med_create_new_segment(scale);
174
        med_rotate_segment(Cursegp,vm_angles_2_matrix(Seg_orientation));
175
        Update_flags |= UF_WORLD_CHANGED;
176
        mine_changed = 1;
177
 
178
        return 1;
179
}
180
 
181
int medlisp_rotate_segment(void)
182
{
183
        Seg_orientation.p = func_get_param(0);
184
        Seg_orientation.b = func_get_param(1);
185
        Seg_orientation.h = func_get_param(2);
186
        med_rotate_segment(Cursegp,vm_angles_2_matrix(Seg_orientation));
187
        Update_flags |= UF_WORLD_CHANGED | UF_VIEWPOINT_MOVED;
188
        mine_changed = 1;
189
        return 1;
190
}
191
 
192
int ToggleLockViewToCursegp(void)
193
{
194
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
195
        auto &Vertices = LevelSharedVertexState.get_vertices();
196
        Lock_view_to_cursegp = !Lock_view_to_cursegp;
197
        Update_flags = UF_ED_STATE_CHANGED;
198
        if (Lock_view_to_cursegp) {
199
        //if (keypress != KEY_V+KEY_CTRLED)
200
            diagnostic_message("[ctrl-V] View locked to Cursegp.");
201
        //else
202
        //    diagnostic_message("View locked to Cursegp.");
203
                auto &vcvertptr = Vertices.vcptr;
204
        set_view_target_from_segment(vcvertptr, Cursegp);
205
    } else {
206
        //if (keypress != KEY_V+KEY_CTRLED)
207
            diagnostic_message("[ctrl-V] View not locked to Cursegp.");
208
        //else
209
        //    diagnostic_message("View not locked to Cursegp.");
210
    }
211
    return Lock_view_to_cursegp;
212
}
213
 
214
int ToggleDrawAllSegments()
215
{
216
        Draw_all_segments = !Draw_all_segments;
217
        Update_flags = UF_ED_STATE_CHANGED;
218
    if (Draw_all_segments == 1) {
219
        //if (keypress != KEY_A+KEY_CTRLED)
220
            diagnostic_message("[ctrl-A] Draw all segments ON.");
221
        //else
222
        //    diagnostic_message("Draw all segments ON.");
223
    }
224
    if (Draw_all_segments == 0) {
225
        //if (keypress != KEY_A+KEY_CTRLED)
226
            diagnostic_message("[ctrl-A] Draw all segments OFF.");
227
        //else
228
        //    diagnostic_message("Draw all segments OFF.");
229
    }
230
    return Draw_all_segments;
231
}
232
 
233
int     Big_depth=6;
234
 
235
int IncreaseDrawDepth(void)
236
{
237
        Big_depth++;
238
        Update_flags = UF_ED_STATE_CHANGED;
239
        return 1;
240
}
241
 
242
int DecreaseDrawDepth(void)
243
{
244
        if (Big_depth > 1) {
245
                Big_depth--;
246
                Update_flags = UF_ED_STATE_CHANGED;
247
        }
248
        return 1;
249
}
250
 
251
 
252
int ToggleCoordAxes()
253
{
254
                        //  Toggle display of coordinate axes.
255
        Show_axes_flag = !Show_axes_flag;
256
        LargeView.ev_changed = 1;
257
    if (Show_axes_flag == 1) {
258
        //if (keypress != KEY_D+KEY_CTRLED)
259
            diagnostic_message("[ctrl-D] Coordinate axes ON.");
260
        //else
261
        //    diagnostic_message("Coordinate axes ON.");
262
    }
263
    if (Show_axes_flag == 0) {
264
        //if (keypress != KEY_D+KEY_CTRLED)
265
            diagnostic_message("[ctrl-D] Coordinate axes OFF.");
266
        //else
267
        //    diagnostic_message("Coordinate axes OFF.");
268
    }
269
    return Show_axes_flag;
270
}
271
 
272
int med_keypad_goto_prev()
273
{
274
        ui_pad_goto_prev();
275
        return 0;
276
}
277
 
278
int med_keypad_goto_next()
279
{
280
        ui_pad_goto_next();
281
        return 0;
282
}
283
 
284
int med_keypad_goto()
285
{
286
        ui_pad_goto(func_get_param(0));
287
        return 0;
288
}
289
 
290
int render_3d_in_big_window=0;
291
 
292
int medlisp_update_screen()
293
{
294
#if 1   //def OGL
295
        Update_flags = UF_ALL;
296
#endif
297
 
298
        if (!render_3d_in_big_window)
299
                range_for (const auto vn, Views)
300
                        if (vn->ev_changed || (Update_flags & (UF_WORLD_CHANGED | UF_VIEWPOINT_MOVED | UF_ED_STATE_CHANGED)))
301
                        {
302
                                draw_world(vn->ev_canv, vn, Cursegp, Big_depth);
303
                                vn->ev_changed = 0;
304
                        }
305
 
306
        if (Update_flags & (UF_WORLD_CHANGED|UF_GAME_VIEW_CHANGED|UF_ED_STATE_CHANGED)) {
307
                grs_canvas *render_canv,*show_canv;
308
 
309
                if (render_3d_in_big_window) {
310
                        render_canv = LargeView.ev_canv;
311
                        show_canv = LargeView.ev_canv;
312
                }
313
                else {
314
                        render_canv     = Canv_editor_game;
315
                        show_canv       = Canv_editor_game;
316
                }
317
 
318
                gr_set_current_canvas(render_canv);
319
                render_frame(*grd_curcanv, 0);
320
 
321
                Assert(render_canv->cv_bitmap.bm_w == show_canv->cv_bitmap.bm_w &&
322
                                 render_canv->cv_bitmap.bm_h == show_canv->cv_bitmap.bm_h);
323
                (void)show_canv;
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(*grd_curcanv);
336
        g3_set_view_matrix(Viewer->pos,Viewer->orient,Render_zoom);
337
        g3_point_2_vec(v,sx,sy);
338
        g3_end_frame();
339
}
340
 
341
void draw_world_from_game(void)
342
{
343
        if (ModeFlag == 2)
344
                draw_world(Views[0]->ev_canv,Views[0],Cursegp,Big_depth);
345
}
346
 
347
int UndoCommand()
348
{  
349
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
350
        auto &Vertices = LevelSharedVertexState.get_vertices();
351
        int u;
352
 
353
    u = undo();
354
    if (Lock_view_to_cursegp)
355
        {
356
                auto &vcvertptr = Vertices.vcptr;
357
                set_view_target_from_segment(vcvertptr, Cursegp);
358
        }
359
    if (u == 0) {
360
        if (Autosave_count==9) diagnostic_message(undo_status[0]);
361
            else
362
                diagnostic_message(undo_status[Autosave_count+1]);
363
        }
364
        else
365
         if (u == 1) diagnostic_message("Can't Undo.");
366
        else
367
         if (u == 2) diagnostic_message("Can't Undo - Autosave OFF");
368
    Update_flags |= UF_WORLD_CHANGED;
369
         mine_changed = 1;
370
    warn_if_concave_segments();
371
    return 1;
372
}
373
 
374
 
375
int ToggleAutosave()
376
{
377
        Autosave_flag = !Autosave_flag;
378
        if (Autosave_flag == 1)
379
      diagnostic_message("Autosave ON.");
380
        else
381
                diagnostic_message("Autosave OFF.");
382
   return Autosave_flag;
383
}
384
 
385
 
386
int AttachSegment()
387
{
388
        auto &LevelSharedVertexState = LevelSharedSegmentState.get_vertex_state();
389
        auto &Vertices = LevelSharedVertexState.get_vertices();
390
   if (med_attach_segment(Cursegp, vmsegptr(&New_segment), Curside, AttachSide)==4) // Used to be WBACK instead of Curside
391
        diagnostic_message("Cannot attach segment - already a connection on current side.");
392
   else {
393
                if (Lock_view_to_cursegp)
394
                {
395
                        auto &vcvertptr = Vertices.vcptr;
396
                        set_view_target_from_segment(vcvertptr, Cursegp);
397
                }
398
                vm_angvec_make(&Seg_orientation,0,0,0);
399
                Curside = WBACK;
400
                Update_flags |= UF_WORLD_CHANGED;
401
           autosave_mine(mine_filename);
402
                undo_status[Autosave_count] = "Attach Segment UNDONE.";
403
                mine_changed = 1;
404
                warn_if_concave_segment(Cursegp);
405
      }
406
        return 1;
407
}
408
 
409
 
410
#if ORTHO_VIEWS
411
int SyncLargeView()
412
{
413
        // Make large view be same as one of the orthogonal views.
414
        Large_view_index = (Large_view_index + 1) % 3;  // keep in 0,1,2 for top, front, right
415
        switch (Large_view_index) {
416
                case 0: LargeView.ev_matrix = TopView.ev_matrix; break;
417
                case 1: LargeView.ev_matrix = FrontView.ev_matrix; break;
418
                case 2: LargeView.ev_matrix = RightView.ev_matrix; break;
419
        }
420
        Update_flags |= UF_VIEWPOINT_MOVED;
421
        return 1;
422
}
423
#endif
424
 
425
int CreateDefaultNewSegment()
426
{
427
        // Create a default segment for New_segment.
428
        med_create_new_segment({DEFAULT_X_SIZE, DEFAULT_Y_SIZE, DEFAULT_Z_SIZE});
429
        mine_changed = 1;
430
 
431
        return 1;
432
}
433
 
434
int CreateDefaultNewSegmentandAttach()
435
{
436
        CreateDefaultNewSegment();
437
        AttachSegment();
438
 
439
        return 1;
440
}
441
 
442
int ExchangeMarkandCurseg()
443
{
444
        // If Markedsegp != Cursegp, and Markedsegp->segnum != -1, exchange Markedsegp and Cursegp
445
        if (Markedsegp)
446
                if (Markedsegp->segnum != segment_none) {
447
                        using std::swap;
448
                        swap(Markedsegp, Cursegp);
449
                        swap(Markedside, Curside);
450
                        med_create_new_segment_from_cursegp();
451
                        Update_flags |= UF_ED_STATE_CHANGED;
452
                        mine_changed = 1;
453
                }
454
        return 1;
455
}
456
 
457
int ClearSelectedList(void)
458
{
459
        Selected_segs.clear();
460
        Update_flags |= UF_WORLD_CHANGED;
461
 
462
        diagnostic_message("Selected list cleared.");
463
 
464
        return 1;
465
}
466
 
467
 
468
int ClearFoundList(void)
469
{
470
        Found_segs.clear();
471
        Update_flags |= UF_WORLD_CHANGED;
472
 
473
        diagnostic_message("Found list cleared.");
474
 
475
        return 1;
476
}
477
 
478
// ---------------------------------------------------------------------------------------------------
479
void set_view_target_from_segment(fvcvertptr &vcvertptr, const shared_segment &sp)
480
{
481
        if (Funky_chase_mode)
482
                {
483
                //set_chase_matrix(sp);
484
                }
485
        else {
486
                vms_vector tv{};
487
                range_for (const auto &v, sp.verts)
488
                        vm_vec_add2(tv, vcvertptr(v));
489
 
490
                vm_vec_scale(tv,F1_0/MAX_VERTICES_PER_SEGMENT);
491
                Ed_view_target = tv;
492
        }
493
        Update_flags |= UF_VIEWPOINT_MOVED;
494
 
495
}