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-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18
*/
19
 
20
/*
21
 *
22
 * Header for editor functions, data strcutures, etc.
23
 *
24
 */
25
 
26
#pragma once
27
 
28
#include "dxxsconf.h"
29
#include "dsx-ns.h"
30
#include "vecmat.h"
31
#include "ui.h"
32
#include "fmtcheck.h"
33
 
34
#ifdef __cplusplus
35
#include "fwd-window.h"
36
#include "fwd-segment.h"
37
#include "objnum.h"
38
 
39
/*
40
 * Constants
41
 *
42
 */
43
 
44
#define ORTHO_VIEWS 0                   // set to 1 to enable 3 orthogonal views
45
#define ED_SCREEN_W     800             //width of editor screen
46
#define ED_SCREEN_H     600             //height of editor screen
47
 
48
#define MENUBAR_H               16
49
 
50
#define GAMEVIEW_X      1               //where the 320x200 game window goes
51
#define GAMEVIEW_Y      1+MENUBAR_H
52
#define GAMEVIEW_W      320
53
#define GAMEVIEW_H      200
54
 
55
#define STATUS_X        0
56
#define STATUS_H        18
57
#define STATUS_Y        (ED_SCREEN_H-STATUS_H)
58
#define STATUS_W        ED_SCREEN_W
59
 
60
#define LVIEW_X 1                       //large view
61
#define LVIEW_Y (GAMEVIEW_Y+GAMEVIEW_H+2)
62
#define LVIEW_W 447
63
#define LVIEW_H (STATUS_Y-LVIEW_Y-2)
64
 
65
#define TMAPBOX_X       (LVIEW_X+LVIEW_W+4)     //location of first one
66
#define TMAPBOX_Y       (LVIEW_Y+2)
67
#define TMAPBOX_W       64
68
#define TMAPBOX_H       64
69
 
70
#define TMAPCURBOX_X (TMAPBOX_X + 4*(TMAPBOX_W + 3))
71
#define TMAPCURBOX_Y (TMAPBOX_Y + TMAPBOX_H)
72
 
73
#define OBJCURBOX_X (TMAPCURBOX_X)
74
#define OBJCURBOX_Y (TMAPCURBOX_Y + 3*(TMAPBOX_H + 2) -40)
75
 
76
#define PAD_X (GAMEVIEW_X + GAMEVIEW_W + 16)
77
#define PAD_Y (GAMEVIEW_Y + 4)
78
 
79
#define SMALLVIEW_W     173             //width of small view windows
80
#define SMALLVIEW_H     148             //height of small view windows
81
 
82
#define TVIEW_X (LVIEW_X+LVIEW_W+2)             //top view
83
#define TVIEW_Y LVIEW_Y
84
#define TVIEW_W SMALLVIEW_W
85
#define TVIEW_H SMALLVIEW_H
86
 
87
#define FVIEW_X TVIEW_X                                         //front view
88
#define FVIEW_Y (TVIEW_Y+SMALLVIEW_H+2)
89
#define FVIEW_W SMALLVIEW_W
90
#define FVIEW_H SMALLVIEW_H
91
 
92
#define RVIEW_X (TVIEW_X+SMALLVIEW_W+2) //right view
93
#define RVIEW_Y FVIEW_Y 
94
#define RVIEW_W SMALLVIEW_W
95
#define RVIEW_H SMALLVIEW_H
96
 
97
#define GVIEW_X RVIEW_X                                         //group view
98
#define GVIEW_Y TVIEW_Y 
99
#define GVIEW_W SMALLVIEW_W
100
#define GVIEW_H SMALLVIEW_H
101
 
102
//there were color constants here, but I moved them to meddraw.c - Matt
103
 
104
#define SEGMOVE_PAD_ID          0
105
#define SEGSIZE_PAD_ID          1
106
#define CURVE_PAD_ID            2       
107
#define TEXTURE_PAD_ID          3
108
#define OBJECT_PAD_ID           4
109
#define OBJMOV_PAD_ID           5
110
#define GROUP_PAD_ID            6
111
#define LIGHTING_PAD_ID 7
112
#define TEST_PAD_ID                     8
113
#define MAX_PAD_ID                      8
114
 
115
/*
116
 * Strucures
117
 *
118
 */
119
 
120
#define VF_ANGLES 0
121
#define VF_MATRIX 1
122
 
123
// Default size of a segment
124
#define DEFAULT_X_SIZE          F1_0*20
125
#define DEFAULT_Y_SIZE          F1_0*20
126
#define DEFAULT_Z_SIZE          F1_0*20
127
 
128
//      Scale factor from 3d units (integer portion) to uv coordinates (integer portion)
129
#define VMAG    (F1_0 / (DEFAULT_X_SIZE/F1_0))
130
#define UMAG    VMAG            // unused
131
 
132
//      Number of segments which can be found (size of Found_segs[])
133
 
134
#define MAX_GROUPS                      10
135
#define ROT_GROUP                       MAX_GROUPS
136
 
137
//      Modes for segment sizing
138
#define SEGSIZEMODE_FREE                1
139
#define SEGSIZEMODE_ALL                 2
140
#define SEGSIZEMODE_CURSIDE     3
141
#define SEGSIZEMODE_EDGE                4
142
#define SEGSIZEMODE_VERTEX              5
143
 
144
#define SEGSIZEMODE_MIN                 SEGSIZEMODE_FREE
145
#define SEGSIZEMODE_MAX                 SEGSIZEMODE_VERTEX
146
 
147
//defines a view for an editor window
148
struct editor_view
149
{
150
        short ev_num;                           //each view has it's own number
151
        short ev_changed;                       //set to true if view changed
152
        grs_canvas *ev_canv;            //points to this window's canvas
153
        fix ev_dist;                            //the distance from the view point
154
        vms_matrix ev_matrix;   //the view matrix
155
        fix ev_zoom;                            //zoom for this window
156
};
157
 
158
enum class editor_gamestate : uint8_t
159
{
160
        none,           // editing a level, not a gamestate
161
        unsaved,        // just pressed delete-e from a game
162
        saved           // saved state. Do we want to restore it when launching editor from menu? Ask user.
163
};
164
 
165
/*
166
 * Global variables
167
 *
168
 */
169
 
170
extern std::array<editor_view *, ORTHO_VIEWS ? 4 : 1> Views;
171
extern int Large_view_index;
172
extern std::unique_ptr<UI_GADGET_USERBOX> LargeViewBox, GameViewBox, GroupViewBox;
173
extern int Found_seg_index;                             // Index in Found_segs corresponding to Cursegp
174
extern editor_gamestate gamestate;
175
extern grs_font_ptr editor_font;
176
 
177
extern  vms_vector Ed_view_target;              // what editor is looking at
178
 
179
extern  class window *Pad_info;         // Keypad text
180
 
181
extern  int             Show_axes_flag;         // 0 = don't show, !0 = do show coordinate axes in *Cursegp orientation
182
 
183
namespace dcx {
184
extern   int            Autosave_count;         // Current counter for which autosave mine we are "on"
185
extern  int             Autosave_flag;                  // Whether or not Autosave is on.
186
extern  struct tm Editor_time_of_day;
187
}
188
 
189
extern  int             SegSizeMode;                    // Mode = 0/1 = not/is legal to move bound vertices, 
190
 
191
#ifdef dsx
192
namespace dsx {
193
void init_editor(void);
194
 
195
}
196
#endif
197
#ifdef dsx
198
namespace dsx {
199
 
200
//      Initialize all vertices to inactive status.
201
extern void init_all_vertices(void);
202
 
203
}
204
#endif
205
 
206
//      Returns true if vertex vi is contained in exactly one segment, else returns false.
207
extern int is_free_vertex(int vi);
208
 
209
//      Set existing vertex vnum to value *vp.
210
int med_set_vertex(unsigned vnum, const vertex &vp);
211
 
212
void med_combine_duplicate_vertices(std::array<uint8_t, MAX_VERTICES> &);
213
 
214
#ifdef dsx
215
namespace dsx {
216
// Attach side newside of newseg to side destside of destseg.
217
// Copies *newseg into global array Segments, increments Num_segments.
218
// Forms a weld between the two segments by making the new segment fit to the old segment.
219
// Updates number of faces per side if necessitated by new vertex coordinates.
220
// Return value:
221
//  0 = successful attach
222
//  1 = No room in Segments[].
223
//  2 = No room in Vertices[].
224
int med_attach_segment(vmsegptridx_t destseg, vmsegptr_t newseg, int destside, int newside);
225
 
226
// Delete a segment.
227
// Deletes a segment from the global array Segments.
228
// Updates Cursegp to be the segment to which the deleted segment was connected.  If there is
229
//      more than one connected segment, the new Cursegp will be the segment with the highest index
230
//      of connection in the deleted segment (highest index = front)
231
// Return value:
232
//  0 = successful deletion
233
//  1 = unable to delete
234
int med_delete_segment(vmsegptridx_t sp);
235
 
236
// Rotate the segment *seg by the pitch, bank, heading defined by *rot, destructively
237
// modifying its four free vertices in the global array Vertices.
238
// It is illegal to rotate a segment which has MAX_SIDES_PER_SEGMENT != 1.
239
// Pitch, bank, heading are about the point which is the average of the four points
240
// forming the side of connection.
241
// Return value:
242
//  0 = successful rotation
243
//  1 = MAX_SIDES_PER_SEGMENT makes rotation illegal (connected to 0 or 2+ segments)
244
//  2 = Rotation causes degeneracy, such as self-intersecting segment.
245
int med_rotate_segment(vmsegptridx_t seg, const vms_matrix &rotmat);
246
 
247
//    Create a wall which can be removed.
248
//    Creates wall at sp->sides[side], making it part of segment sp
249
//    Removable walls must be placed between two connected segments.  You should add the removable
250
//    wall on both sides.  In fact, you really must.
251
void create_removable_wall(fvcvertptr &vcvertptr, vmsegptridx_t sp, unsigned side, unsigned tmap_num);
252
}
253
#endif
254
 
255
// Saves mine contained in Segments[] and Vertices[].
256
// Num_segments = number of segments in mine.
257
// Num_vertices = number of vertices in mine.
258
// Cursegp = current segment.
259
// Saves Num_segments, and index of current segment (which is Cursegp - Segments), which will be converted to a pointer
260
// and written to Cursegp in med_load_mine.
261
// Returns:
262
//  0 = successfully saved.
263
//  1 = unable to save.
264
extern  int med_save_mine(const char *name);
265
 
266
// Updates the screen... (I put the prototype here for curves.c)
267
extern   int medlisp_update_screen();
268
 
269
// Returns 0 if no error, 1 if error, whatever that might be.
270
// Sets globals:
271
//    Num_segments
272
//    Num_vertices
273
//    Cursegp = pointer to only segment.
274
#ifdef dsx
275
namespace dsx {
276
extern  int create_new_mine(void);
277
 
278
}
279
#endif
280
#ifdef dsx
281
namespace dsx {
282
//      Create a segment given center, dimensions, rotation matrix.
283
//      Note that the created segment will always have planar sides and rectangular cross sections.
284
//      It will be created with walls on all sides, ie not connected to anything.
285
void med_create_segment(vmsegptridx_t sp,fix cx, fix cy, fix cz, fix length, fix width, fix height, const vms_matrix &mp);
286
 
287
//      Create New_segment with sizes found in *scale.
288
void med_create_new_segment(const vms_vector &scale);
289
 
290
//      Create New_segment with sizes found in Cursegp.
291
extern void med_create_new_segment_from_cursegp(void);
292
 
293
//      Create a new segment and use it to form a bridge between two existing segments.
294
//      Specify two segment:side pairs.  If either segment:side is not open (ie, segment->children[side] != -1)
295
//      then it is not legal to form the brider.
296
//      Return:
297
//              0       bridge segment formed
298
//              1       unable to form bridge because one (or both) of the sides is not open.
299
//      Note that no new vertices are created by this process.
300
int med_form_bridge_segment(vmsegptridx_t seg1, int side1, vmsegptridx_t seg2, int side2);
301
}
302
#endif
303
 
304
//      Compress mine at Segments and Vertices by squeezing out all holes.
305
//      If no holes (ie, an unused segment followed by a used segment), then no action.
306
//      If Cursegp or Markedsegp is a segment which gets moved to fill in a hole, then
307
//      they are properly updated.
308
extern  void med_compress_mine(void);
309
 
310
void update_matrix_based_on_side(vms_matrix &rotmat,int destside);
311
 
312
// Curves stuff.
313
 
314
#define ACCURACY 0.1*F1_0
315
 
316
struct vms_equation
317
{
318
    union {
319
            struct {fix x3, x2, x1, x0, y3, y2, y1, y0, z3, z2, z1, z0;} n;
320
                std::array<std::array<fix, 4>, 3> xyz;
321
    };
322
};
323
 
324
// Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t^3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4
325
 
326
extern vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t);
327
 
328
fix curve_dist(vms_equation *coeffs, int degree, fix t0, const vms_vector &p0, fix dist);
329
 
330
extern void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t);
331
 
332
// Curve generation routine.
333
// Returns 1 if curve is generated.
334
// Returns 0 if no curve.
335
extern int generate_curve( fix r1scale, fix r4scale );
336
 
337
// Deletes existing curve generated in generate_curve().
338
extern void delete_curve();
339
 
340
#ifdef dsx
341
namespace dsx {
342
void med_extract_matrix_from_segment(const shared_segment &sp, vms_matrix &rotmat);
343
 
344
//      Assign default u,v coordinates to all sides of a segment.
345
//      This routine should only be used for segments which are not connected to anything else,
346
//      ie the segment created at mine creation.
347
void assign_default_uvs_to_segment(vmsegptridx_t segp);
348
void assign_default_uvs_to_side(vmsegptridx_t segp, unsigned side);
349
 
350
//      Assign u,v coordinates to con_seg, con_common_side from base_seg, base_common_side
351
//      They are connected at the edge defined by the vertices abs_id1, abs_id2.
352
void med_assign_uvs_to_side(vmsegptridx_t con_seg, unsigned con_common_side, vmsegptr_t base_seg, unsigned base_common_side, unsigned abs_id1, unsigned abs_id2);
353
 
354
//      Create coordinate axes in orientation of specified segment, stores vertices at *vp.
355
void create_coordinate_axes_from_segment(vmsegptr_t sp, std::array<unsigned, 16> &vertnums);
356
 
357
//      Set Vertex_active to number of occurrences of each vertex.
358
//      Set Num_vertices.
359
extern  void set_vertex_counts(void);
360
 
361
//      Modify seg2 to share side2 with seg1:side1.  This forms a connection between
362
//      two segments without creating a new segment.  It modifies seg2 by sharing
363
//      vertices from seg1.  seg1 is not modified.  Four vertices from seg2 are
364
//      deleted.
365
//      If the four vertices forming side2 in seg2 are not free, the joint is not formed.
366
//      Return code:
367
//              0                       joint formed
368
//              1                       unable to form joint because one or more vertices of side2 is not free
369
//              2                       unable to form joint because side1 is already used
370
int med_form_joint(vmsegptridx_t seg1, int side1, vmsegptridx_t seg2, int side2);
371
}
372
 
373
// The current texture... use by saying something=bm_lock_bitmap(CurrentTexture)
374
extern int CurrentTexture;
375
 
376
namespace dsx {
377
void med_propagate_tmaps_to_segments(vmsegptridx_t base_seg,vmsegptridx_t con_seg, int uv_only_flag);
378
void med_propagate_tmaps_to_back_side(vmsegptridx_t base_seg, int back_side, int uv_only_flag);
379
 
380
//      Find segment adjacent to sp:side.
381
//      Adjacent means a segment which shares all four vertices.
382
//      Return true if segment found and fill in segment in adj_sp and side in adj_side.
383
//      Return false if unable to find, in which case adj_sp and adj_side are undefined.
384
int med_find_adjacent_segment_side(vmsegptridx_t sp, int side, imsegptridx_t &adj_sp, int *adj_side);
385
 
386
// Finds the closest segment and side to sp:side.
387
int med_find_closest_threshold_segment_side(vmsegptridx_t sp, int side, imsegptridx_t &adj_sp, int *adj_side, fix threshold);
388
 
389
// Select previous segment.
390
//      If there is a connection on the side opposite to the current side, then choose that segment.
391
// If there is no connecting segment on the opposite face, try any segment.
392
 
393
// Select next segment.
394
//      If there is a connection on the current side, then choose that segment.
395
// If there is no connecting segment on the current side, try any segment.
396
 
397
//      Copy texture maps in newseg to nsp.
398
void copy_uvs_seg_to_seg(unique_segment &destseg, const unique_segment &srcseg);
399
 
400
//      Return true if segment is concave.
401
 
402
//      Return N_found_segs = number of concave segments in mine.
403
//      Segment ids stored at Found_segs
404
extern void find_concave_segs(void);
405
 
406
//      High level call.  Check for concave segments, print warning message (using editor_status)
407
//      if any concave segments.
408
//      Calls find_concave_segs, therefore N_found_segs gets set, and Found_segs filled in.
409
extern void warn_if_concave_segments(void);
410
 
411
//      Warn if segment s is concave.
412
void warn_if_concave_segment(vmsegptridx_t s);
413
}
414
 
415
//      Add a vertex to the vertex list.
416
int med_add_vertex(const vertex &vp);
417
 
418
//      Add a vertex to the vertex list which may be identical to another vertex (in terms of coordinates).
419
//      Don't scan list, looking for presence of a vertex with same coords, add this one.
420
int med_create_duplicate_vertex(const vertex &vp);
421
 
422
namespace dsx {
423
//      Create a new segment, duplicating exactly, including vertex ids and children, the passed segment.
424
segnum_t med_create_duplicate_segment(segment_array &, const segment &sp);
425
 
426
//      Returns the index of a free segment.
427
//      Scans the Segments array.
428
segnum_t get_free_segment_number(segment_array &);
429
}
430
#endif
431
 
432
//      Diagnostic message.
433
#define diagnostic_message editor_status
434
#define diagnostic_message_fmt editor_status_fmt
435
 
436
//      Editor status message.
437
extern void editor_status_fmt(const char *format, ... ) __attribute_format_printf(1, 2);
438
#define editor_status_fmt(F,...)        dxx_call_printf_checked(editor_status_fmt,editor_status,(),(F),##__VA_ARGS__)
439
 
440
// Variables in editor.c that the k*.c files need
441
 
442
#define UF_NONE             0x000       //nothing has changed
443
#define UF_WORLD_CHANGED    0x001       //something added or deleted
444
#define UF_VIEWPOINT_MOVED  0x002       //what we're watching has moved
445
 
446
#define UF_GAME_VIEW_CHANGED 0x004              //the game window changed    
447
#define UF_ED_STATE_CHANGED  0x008              //something like curside,curseg changed
448
 
449
#define UF_ALL                                  0xffffffff  //all flags
450
 
451
extern uint        Update_flags;
452
extern int         Funky_chase_mode;
453
extern vms_angvec  Seg_orientation;
454
extern int         mine_changed;
455
extern int         ModeFlag;
456
extern editor_view *current_view;
457
 
458
//the view for the different windows
459
extern editor_view LargeView;
460
extern editor_view TopView;
461
extern editor_view FrontView;
462
extern editor_view RightView;
463
 
464
extern int SafetyCheck();
465
#ifdef dsx
466
namespace dsx {
467
int save_mine_data_compiled(PHYSFS_File *SaveFile);
468
 
469
}
470
#endif
471
void editor_status( const char *text);
472
 
473
extern int MacroNumEvents;
474
extern int MacroStatus;
475
 
476
//extern        int     Highest_segment_index;                  // Highest index in Segments, an efficiency hack
477
extern  int     Lock_view_to_cursegp;                   // !0 means whenever cursegp changes, view it
478
 
479
//      eglobal.c
480
extern  int     Num_tilings;                                            // number of tilings/wall
481
extern  int     Degenerate_segment_found;
482
 
483
namespace dcx {
484
 
485
// Initializes autosave system.
486
// Sets global Autosave_count to 0.
487
extern void init_autosave(void);
488
 
489
// Closes autosave system.
490
// Deletes all autosaved files.
491
extern void close_autosave(void);
492
 
493
// Saves current mine to name.miX where name = suffix of mine name and X = Autosave_count.
494
// For example, if name = "cookie.min", and Autosave_count = 3, then writes "cookie.mi3".
495
// Increments Autosave_count, wrapping from 9 to 0.
496
// (If there is no current mine name, assume "temp.min")
497
// Call med_save_mine to save the mine.
498
extern void autosave_mine(const char *name);
499
 
500
// Timed autosave
501
extern void TimedAutosave(const char *name);
502
extern void set_editor_time_of_day();
503
 
504
// Undo function
505
extern int undo(void);
506
extern std::array<const char *, 10> undo_status;
507
}
508
 
509
extern char mine_filename[PATH_MAX];
510
 
511
//      group.c
512
int RotateSegmentNew(vms_angvec *pbh);
513
int rotate_segment_new(const vms_angvec &pbh);
514
 
515
// The current object type and id declared in eglobal.c
516
extern short Cur_object_type;
517
extern short Cur_object_id;
518
 
519
//      From med.c
520
extern int DisplayCurrentRobotType(void);
521
extern objnum_t                 Cur_object_index;
522
 
523
extern int render_3d_in_big_window;
524
extern void move_object_to_mouse_click(void);
525
 
526
//these are instances of canvases, pointed to by variables below
527
extern grs_canvas _canv_editor_game;            //the game on the editor screen
528
 
529
//these are pointers to our canvases
530
extern grs_canvas *Canv_editor;                 //the editor screen
531
extern grs_canvas *const Canv_editor_game; //the game on the editor screen
532
 
533
extern UI_DIALOG * EditorWindow;
534
 
535
void med_point_2_vec(grs_canvas *canv,vms_vector &v,short sx,short sy);
536
 
537
//shutdown ui on the editor screen
538
void close_editor_screen(void);
539
 
540
#ifdef dsx
541
namespace dsx {
542
//    From eobject.c
543
int place_object(vmsegptridx_t segp, const vms_vector &object_pos, short object_type, short object_id);
544
 
545
// from ksegsize.c
546
void med_extract_up_vector_from_segment_side(vmsegptr_t sp, int sidenum, vms_vector &vp);
547
void med_extract_right_vector_from_segment_side(vmsegptr_t sp, int sidenum, vms_vector &vp);
548
}
549
#endif
550
 
551
//      In medmisc.c
552
extern void draw_world_from_game(void);
553
 
554
//      In medrobot.c
555
extern void close_all_windows(void);
556
 
557
//      In seguvs.c
558
 
559
//      Amount to stretch a texture map by.
560
//      The two different ones are for the two dimensions of a texture map.
561
extern fix Stretch_scale_x, Stretch_scale_y;
562
 
563
#endif