]> icculus.org git repositories - taylor/freespace2.git/blob - src/nebedit/nebedit.cpp
nebedit cleanup; still needs working file dialogs
[taylor/freespace2.git] / src / nebedit / nebedit.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/nebedit/NebEdit.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Program to edit nebulas in 2d
16  *
17  * $Log$
18  * Revision 1.3  2002/06/09 04:41:23  relnev
19  * added copyright header
20  *
21  * Revision 1.2  2002/05/07 03:16:47  theoddone33
22  * The Great Newline Fix
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:10  root
25  * Initial import.
26  *
27  * 
28  * 7     7/15/99 3:07p Dave
29  * 32 bit detection support. Mouse coord commandline.
30  * 
31  * 6     5/19/99 4:07p Dave
32  * Moved versioning code into a nice isolated common place. Fixed up
33  * updating code on the pxo screen. Fixed several stub problems.
34  * 
35  * 5     1/08/99 2:06p Dave
36  * Fixed pfoview for software mode.
37  * 
38  * 4     12/18/98 1:14a Dave
39  * Rough 1024x768 support for Direct3D. Proper detection and usage through
40  * the launcher.
41  * 
42  * 3     11/13/98 2:32p Dave
43  * Improved commandline parsing for exe pathname.
44  * 
45  * 2     10/24/98 9:51p Dave
46  * 
47  * 1     10/24/98 9:39p Dave
48  * 
49  * 13    4/13/98 10:11a John
50  * Made timer functions thread safe.  Made timer_init be called in all
51  * projects.
52  * 
53  * 12    3/23/98 1:35p Sandeep
54  * 
55  * 11    3/05/98 11:15p Hoffoss
56  * Changed non-game key checking to use game_check_key() instead of
57  * game_poll().
58  * 
59  * 10    12/29/97 5:10p Allender
60  * fixed problems with speed not being reported properly in multiplayer
61  * games.  Made read_flying_controls take frametime as a parameter.  More
62  * ship/weapon select stuff
63  * 
64  * 9     12/04/97 3:47p John
65  * Made joystick move mouse cursor
66  * 
67  * 8     11/21/97 11:32a John
68  * Added nebulas.   Fixed some warpout bugs.
69  * 
70  * 7     11/19/97 10:15p Adam
71  * upped maxtris to 200
72  * 
73  * 6     11/19/97 4:28p Sandeep
74  * added poly/vert counter
75  * 
76  * 5     11/19/97 1:59p Sandeep
77  * Added multiple vertex editing mode
78  * 
79  * 4     11/16/97 2:29p John
80  * added versioning to nebulas; put nebula code into freespace.
81  * 
82  * 3     11/13/97 12:04p Sandeep
83  * Added face editing support, deletion support, and a saving and loading
84  * stuff.
85  * 
86  * 2     11/10/97 9:59p John
87  * some tweaking
88  * 
89  * 1     11/10/97 9:42p John
90  *
91  * $NoKeywords: $
92  */
93
94 #if 0
95 #include "wx/wxprec.h"
96
97 #ifndef WX_PRECOMP
98 #include "wx/wx.h"
99 #endif
100
101 #include "wx/filedlg.h"
102 #endif
103
104 #include <stdio.h>
105 #include <stdlib.h>
106 #include <string.h>
107 #include <ctype.h>
108
109 #include "pstypes.h"
110 #include "2d.h"
111 #include "3d.h"
112 #include "key.h"
113 #include "palman.h"
114 #include "bmpman.h"
115 #include "timer.h"
116 #include "floating.h"
117 #include "osapi.h"
118 #include "cfile.h"
119 #include "linklist.h"
120 #include "lighting.h"
121 #include "mouse.h"
122 #include "vecmat.h"
123 #include "physics.h"
124 #include "model.h"
125 #include "font.h"
126 #include "cmdline.h"
127
128
129 #define SCREEN_W        640     
130 #define SCREEN_H        480
131
132 vector ViewerPos;
133 matrix ViewerOrient;
134 matrix ModelOrient;
135 vector ModelPos;
136 physics_info ViewerPhysics;
137 float ViewerZoom = 1.0f;
138
139 int test_model = -1;
140 int Fred_running = 0;
141 int Pofview_running = 0;
142 float flFrametime = 0.0f;
143
144 int Font1 = -1;
145
146 color color_green;
147
148 vector Global_light_world = { 0.208758f, -0.688253f, -0.694782f };
149
150 // nebula stuff
151
152 #define NEB_W 6
153 #define NEB_H 6
154 #define MAX_TRIS 200
155 #define MAX_POINTS 300
156
157 int neb_w = 0, neb_h = 0;
158
159 int nebula_inited = 0;
160 int num_pts = 0;
161
162 int x[MAX_POINTS], y[MAX_POINTS], l[MAX_POINTS];
163 float scale_factor = 1.0f;
164
165 int num_tris = 0;
166 int tri[MAX_TRIS][3];
167
168 color nebula_color;
169
170 int Mouse_x, Mouse_y;
171 int Current_point;
172 bool Selected[MAX_POINTS];
173 bool Sel_mode = false;   // false = 1 point at a time, true = select multiple points
174 int Current_face;
175
176 int View_mode = 0;      // 0 = 2d editor, 1 = 3d viewer
177
178 int Vert_mode = 0;   // 0 = Move vertices/Add vertices, 2 = Move face/Add face
179
180 int Which_vert = 0;  // Current vertex of the faceadd
181
182 int Orig_pos_x;
183 int Orig_pos_y;
184 int End_pos_x;
185 int End_pos_y;
186 bool Draw_sel_box = false;
187
188 int Neb_created = 0;
189
190 int Nebedit_running = 1;
191
192 extern void project_2d_onto_sphere(vector *, float, float);
193
194 void create_default_neb()
195 {
196         int i,j;
197         neb_w = NEB_W;
198         neb_h = NEB_H;
199         num_pts = neb_w*neb_h;
200
201         for (j=0; j<neb_h; j++ )        {
202                 for (i=0; i<neb_w; i++ )        {
203                         x[i+j*neb_w] = ((i+1)*SCREEN_W)/(neb_w+2);
204                         y[i+j*neb_w] = ((j+3)*SCREEN_H)/(neb_h+6);
205                         if ( (j==0) || (j==neb_h-1))    {
206                                 l[i+j*neb_w] = 0;
207                         } else {
208                                 l[i+j*neb_w] = 31;
209                         }
210                 }
211         }
212
213         num_tris = 0;
214
215         for (j=0; j<neb_h-1; j++ )      {
216                 for (i=0; i<neb_w-1; i++ )      {
217                         tri[num_tris][0] = i+neb_w*j;
218                         tri[num_tris][1] = i+neb_w*j+1;
219                         tri[num_tris][2] = i+neb_w*(j+1)+1;
220                         num_tris++;
221
222                         tri[num_tris][0] = i+neb_w*j;
223                         tri[num_tris][1] = i+neb_w*(j+1)+1;
224                         tri[num_tris][2] = i+neb_w*(j+1);
225                         num_tris++;
226                 }
227         }
228
229         Neb_created = 1;
230 }
231
232 #define NEBULA_FILE_ID "NEBU"                   
233 #define NEBULA_MAJOR_VERSION 1          // Can be 1-?
234 #define NEBULA_MINOR_VERSION 0          // Can be 0-99
235
236 void save_nebula_sub(const char *filename)
237 {
238         FILE *fp;
239         float xf, yf;
240         int version;
241         int i;
242         int tmp;
243
244         fp = fopen(filename, "wb");
245
246         // ID of NEBU
247         fwrite( "NEBU", 4, 1, fp );
248         version = NEBULA_MAJOR_VERSION*100+NEBULA_MINOR_VERSION;
249         tmp = INTEL_INT(version);
250         fwrite( &tmp, sizeof(int), 1, fp );
251         tmp = INTEL_INT(num_pts);
252         fwrite( &tmp, sizeof(int), 1, fp );
253         tmp = INTEL_INT(num_tris);
254         fwrite( &tmp, sizeof(int), 1, fp );
255
256
257         for (i=0; i<num_pts; i++ )      {
258                 xf = INTEL_FLOAT(float(x[i])/640.0f);
259                 yf = INTEL_FLOAT(float(y[i])/480.0f);
260                 fwrite( &xf, sizeof(float), 1, fp );
261                 fwrite( &yf, sizeof(float), 1, fp );
262                 tmp = INTEL_INT(l[i]);
263                 fwrite( &tmp, sizeof(int), 1, fp );
264         }
265
266         for (i=0; i<num_tris; i++ )     {
267                 tmp = INTEL_INT(tri[i][0]);
268                 fwrite( &tmp, sizeof(int), 1, fp );
269                 tmp = INTEL_INT(tri[i][1]);
270                 fwrite( &tmp, sizeof(int), 1, fp );
271                 tmp = INTEL_INT(tri[i][2]);
272                 fwrite( &tmp, sizeof(int), 1, fp );
273         }
274
275         fclose(fp);
276 }
277
278 // returns 0 if failed
279 int load_nebula_sub(const char *filename)
280 {
281         FILE *fp;
282         char id[16];
283         int version, major, minor;
284
285         fp = fopen(filename, "rb");
286
287         if ( !fp )      {
288                 return 0;
289         }
290
291         // ID of NEBU
292         fread( id, 4, 1, fp );
293         if ( strncmp( id, NEBULA_FILE_ID, 4))   {
294                 mprintf(( "Not a valid nebula file.\n" ));
295                 return 0;
296         }
297
298         fread( &version, sizeof(int), 1, fp );
299         version = INTEL_INT(version);
300         major = version / 100;
301         minor = version % 100;
302
303         if ( (major != NEBULA_MAJOR_VERSION) && (minor != NEBULA_MINOR_VERSION) ) {
304                 mprintf(( "An out of date nebula file.\n" ));
305                 return 0;
306         }
307
308         fread( &num_pts, sizeof(int), 1, fp );
309         num_pts = INTEL_INT(num_pts);
310         SDL_assert( num_pts < MAX_POINTS );
311         fread( &num_tris, sizeof(int), 1, fp );
312         num_tris = INTEL_INT(num_tris);
313         SDL_assert( num_tris < MAX_TRIS );
314
315         for (int i=0; i<num_pts; i++ )  {
316                 float xf, yf;
317                 int li;
318
319                 fread( &xf, sizeof(float), 1, fp );
320                 fread( &yf, sizeof(float), 1, fp );
321                 fread( &li, sizeof(int), 1, fp );
322
323                 xf = INTEL_FLOAT(xf);
324                 yf = INTEL_FLOAT(yf);
325                 li = INTEL_INT(li);
326
327                 x[i] = (int)(xf*640.0f);
328                 y[i] = (int)(yf*480.0f);
329                 l[i] = li;
330         }
331
332         for (int i=0; i<num_tris; i++ ) {
333                 fread( &tri[i][0], sizeof(int), 1, fp );
334                 fread( &tri[i][1], sizeof(int), 1, fp );
335                 fread( &tri[i][2], sizeof(int), 1, fp );
336                 tri[i][0] = INTEL_INT(tri[i][0]);
337                 tri[i][1] = INTEL_INT(tri[i][1]);
338                 tri[i][2] = INTEL_INT(tri[i][2]);
339         }
340
341         fclose(fp);
342
343         return 1;
344 }
345
346 void nebedit_close()
347 {
348         save_nebula_sub( "autosaved.neb" );
349 }
350
351 void save_nebula()
352 {
353 #if 0
354         wxFileDialog saveFileDialog(NULL, _("Save Nebula File"), wxEmptyString,
355                                                                 wxEmptyString, _("Nebula Files (*.neb)|*.neb"),
356                                                                 wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
357
358         if (saveFileDialog.Show() == wxID_OK) {
359                 save_nebula_sub(saveFileDialog.GetPath().ToAscii());
360         }
361 #endif
362 }
363
364 void load_nebula()
365 {
366         int create_default = 1;
367 #if 0
368         wxFileDialog openFileDialog(NULL, _("Open Nebula File"), wxEmptyString,
369                                                                 wxEmptyString, _("Nebula Files (*.neb)|*.neb"),
370                                                                 wxFD_OPEN|wxFD_FILE_MUST_EXIST);
371
372         if (openFileDialog.Show() == wxID_OK) {
373                 create_default = !load_nebula_sub(openFileDialog.GetPath().ToAscii());
374         }
375 #endif
376         if ( create_default )   {
377                 create_default_neb();
378         }
379
380         Neb_created = 1;
381 }
382
383 void nebula_init()
384 {
385         if ( nebula_inited ) return;
386         memset(Selected, 0, sizeof(BOOL)*MAX_POINTS);
387         nebula_inited++;
388
389         create_default_neb();   
390         gr_init_alphacolor( &nebula_color, 0, 255, 0, 255, AC_TYPE_HUD );
391
392         return;
393 }
394
395 void draw_tri_2d( int i, int j, int k )
396 {
397         int index[3];
398
399         index[0] = i;
400         index[1] = j;
401         index[2] = k;
402
403         vertex va, vb, vc;
404         vertex * verts[3] = { &va, &vb, &vc };
405 //      gr_zbuffering = 0;
406         for (int v=0; v<3; v++ )        {
407                 verts[v]->sx = i2fl(x[index[v]]);   
408                 verts[v]->sy = i2fl(y[index[v]]);
409                 verts[v]->u = 0.0f;
410                 verts[v]->v = 0.0f;
411                 verts[v]->sw = 1.0f; 
412                 verts[v]->b = (ubyte)(i2fl(l[index[v]]*255)/31.0f);
413         }
414
415 //      gr_set_color( 0, 0, 0 );
416         gr_tmapper(3, verts, TMAP_FLAG_RAMP | TMAP_FLAG_GOURAUD | TMAP_FLAG_NEBULA );
417
418         if ( !key_pressed(SDLK_LSHIFT) )        {
419                 gr_set_color(100,100,100);
420                 gr_line( x[i], y[i], x[j], y[j] );
421                 gr_line( x[j], y[j], x[k], y[k] );
422                 gr_line( x[k], y[k], x[i], y[i] );
423         }
424 }
425
426 void nebula_draw_2d()
427 {
428         int i;
429         
430         for (i=0; i<num_tris; i++ )     {
431                 draw_tri_2d( tri[i][0], tri[i][1], tri[i][2] );
432         }               
433
434                 gr_set_color(100,0,0);
435                 for (i=0; i<num_pts; i++ )      {
436                         gr_circle( x[i], y[i], 4 );
437                 }
438                 if ((Sel_mode==1)) { // multiple selection
439                         if (Draw_sel_box) {
440                                 gr_set_color(200,0,200);
441                                 gr_line(Orig_pos_x, Orig_pos_y, Orig_pos_x, End_pos_y);
442                                 gr_line(Orig_pos_x, End_pos_y, End_pos_x, End_pos_y);
443                                 gr_line(End_pos_x, Orig_pos_y, End_pos_x, End_pos_y);
444                                 gr_line(End_pos_x, Orig_pos_y, Orig_pos_x, Orig_pos_y);
445                         } else {
446                                 gr_set_color(0,100,0);
447                                 for (int i=0;i<num_pts;i++)
448                                         if (Selected[i]) gr_circle( x[i], y[i], 5);
449                         }
450                 } else if ((Vert_mode==0)&&(Current_point>-1)) {
451                         gr_set_color(0,100,0);
452                         gr_circle( x[Current_point], y[Current_point], 5);
453                 } else if (Vert_mode == 1) {
454                         for (i=0;i<Which_vert;i++) {
455                                 gr_set_color(0,0,100);
456                                 gr_circle( x[tri[num_tris][i]], y[tri[num_tris][i]], 6);
457                         }
458                         gr_set_color(200,200,0);
459                         if (Current_face>-1) {
460                                 gr_line(x[tri[Current_face][0]], y[tri[Current_face][0]], 
461                                                 x[tri[Current_face][1]], y[tri[Current_face][1]]);
462                                 gr_line(x[tri[Current_face][1]], y[tri[Current_face][1]], 
463                                                 x[tri[Current_face][2]], y[tri[Current_face][2]]);
464                                 gr_line(x[tri[Current_face][2]], y[tri[Current_face][2]], 
465                                                 x[tri[Current_face][0]], y[tri[Current_face][0]]);
466                         }
467                 }
468 }
469
470
471 void draw_tri_3d( int i, int j, int k )
472 {
473         int index[3];
474
475         index[2] = k;
476         index[1] = j;
477         index[0] = i;
478
479         vertex va, vb, vc;
480         vertex * verts[3] = { &va, &vb, &vc };
481         //gr_zbuffering = 0;
482         for (int v=0; v<3; v++ )        {
483                 vector tmp;
484                 
485                 project_2d_onto_sphere( &tmp, 1.0f - i2fl(x[index[v]])/640.0f, i2fl(y[index[v]])/480.0f );
486         
487                 vm_vec_scale( &tmp, 10.0f );
488
489                 g3_rotate_faraway_vertex( verts[v], &tmp );
490                 //g3_rotate_vertex( verts[v], &tmp );
491                 g3_project_vertex( verts[v] );
492
493                 verts[v]->b = (ubyte)(i2fl(l[index[v]]*255)/31.0f);
494         }
495
496         //gr_zbuffering = 0;
497         //gr_set_color_fast( &nebula_color );
498         //gr_set_color( 0, 0, 0 );
499         g3_draw_poly(3, verts, TMAP_FLAG_RAMP | TMAP_FLAG_GOURAUD | TMAP_FLAG_NEBULA );
500 }
501
502 void nebula_draw_3d()
503 {
504         int i;
505         for (i=0; i<num_tris; i++ )     {
506                 draw_tri_3d( tri[i][0], tri[i][1], tri[i][2] );
507         }               
508 }
509
510 void render_frame()
511 {
512         gr_reset_clip();
513
514         gr_set_color(0,0,0);            // set color to black
515         gr_rect(0,0,SCREEN_W,SCREEN_H); // clear screen
516
517         light_reset();
518         light_add_directional( &Global_light_world, 0.1f, 1.0f, 1.0f, 1.0f );
519
520         g3_start_frame(1);
521
522         g3_set_view_matrix(&ViewerPos, &ViewerOrient,ViewerZoom);
523
524         if ( View_mode == 0 )   {
525                 nebula_draw_2d();
526
527                 gr_set_font(Font1);
528                 gr_set_color_fast( &color_green );
529                 gr_printf(10,10,"Nebula Editor. Mode :");
530                 if (Sel_mode ==1) {
531                                 gr_printf(180, 10, "Multiple Vertex Selection Editing");
532                 } else if (Vert_mode ==0 ) {
533                         gr_printf(180,10,"Vertex Editing");
534                         if(Current_point >= 0){
535                                 gr_printf(180, 20, "Current vertex intensity : %d\n", l[Current_point]);
536                         }
537                 } else if (Vert_mode ==1) {
538                         gr_printf(180,10,"Face Editing");
539                 }
540                 char blah[255];
541                 gr_printf(20,30,"# Points:");
542                 gr_printf(100,30, SDL_itoa(num_pts, blah, 10));
543                 gr_printf(220,30,"# Polys:");
544                 gr_printf(300,30, SDL_itoa(num_tris, blah, 10));
545         } else {
546                 nebula_draw_3d();
547                 model_render( test_model, &ModelOrient, &ModelPos );
548         }
549
550         g3_end_frame();
551
552         gr_flip();
553 }
554
555 int get_closest(int mx, int my)
556 {
557         int i, closest = -1, cval = 100000;
558
559         for (i=0; i<num_pts; i++ )      {
560                 int dist;
561                 int dx, dy;
562                 
563                 dx = x[i] - mx;
564                 dy = y[i] - my;
565                 
566                 dist = fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
567
568                 if ( dist < cval )      {
569                         cval = dist;
570                         closest = i;
571                 }
572         }
573
574         return closest;
575 }
576
577 int get_closest_face(int mx, int my)
578 {
579         int i, closest = -1, cval = 100000;
580
581         for (i=0; i<num_tris; i++ )     {
582                 int dist;
583                 int dx, dy;
584                 
585                 dx = x[tri[i][0]] - mx;
586                 dy = y[tri[i][0]] - my;
587
588                 dx += x[tri[i][1]] - mx;
589                 dy += y[tri[i][1]] - my;
590                 
591                 dx += x[tri[i][2]] - mx;
592                 dy += y[tri[i][2]] - my;
593
594                 dist = fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
595 /*
596                 dist += fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
597
598                 dx = x[tri[i][2]] - mx;
599                 dy = y[tri[i][2]] - my;
600                 dist += fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
601 */
602
603                 if ( dist < cval )      {
604                         cval = dist;
605                         closest = i;
606                 }
607         }
608
609         return closest;
610 }
611
612 void delete_face(int i)
613 {
614         for (int j=i;j<num_tris;j++) {
615                 memcpy(tri[j], tri[j+1], sizeof(int)*3);
616         }
617         num_tris--;
618 }
619
620 void delete_vert(int i)
621 {
622         int j;
623
624         for (j=0;j<num_tris;j++) {
625                 if ((tri[j][0]==i)||(tri[j][1]==i)||(tri[j][2]==i)) {
626                         delete_face(j);
627                         j=0;
628                 }
629         }
630         for (j=0;j<num_tris;j++) {
631                 if (tri[j][0]>i) tri[j][0]--;
632                 if (tri[j][1]>i) tri[j][1]--;
633                 if (tri[j][2]>i) tri[j][2]--;
634         }
635         for (j=i;j<num_pts;j++) {
636                 x[j] = x[j+1];
637                 y[j] = y[j+1];
638                 l[j] = l[j+1];
639         }
640         num_pts--;
641 }
642
643 int add_vert(int mx, int my)
644 {
645         SDL_assert(num_pts<300);
646         x[num_pts] = mx;
647         y[num_pts] = my;
648         l[num_pts] = 0;
649         num_pts++;
650         return num_pts-1;
651 }
652
653 void select_by_box(int x1, int y1, int x2, int y2)
654 {
655         if (x1>x2) {
656                 int temp = x1;
657                 x1 = x2;
658                 x2 = temp;
659         }
660         if (y1>y2) {
661                 int temp = y1;
662                 y1 = y2;
663                 y2 = temp;
664         }
665         for (int i=0;i<num_pts;i++) {
666                 if ((x[i]<=x2) && (x[i]>=x1) &&
667                          (y[i]<=y2) && (y[i]>=y1)) {
668                         Selected[i] = true;
669                 }
670         }
671 }
672
673 void sphericalize_nebula()
674 {
675         int idx1, idx2;
676         int px = SCREEN_W / (neb_w - 1);
677         int py = SCREEN_H / (neb_h - 1);
678
679         // flatten out the nebula so that it covers the entire sphere evenly
680         for(idx1=0; idx1<neb_w; idx1++){
681                 for(idx2=0; idx2<neb_h; idx2++){
682                         x[idx1+idx2*neb_w] = px * idx1;
683                         y[idx1+idx2*neb_w] = py * idx2;
684                 }
685         }
686 }
687
688 void controls_read_all(control_info * ci, float sim_time )
689 {
690         float kh;
691
692         {
693                 float temp = ci->heading;
694                 float temp1 = ci->pitch;
695                 memset( ci, 0, sizeof(control_info) );
696                 ci->heading = temp;
697                 ci->pitch = temp1;
698         }
699
700         // From keyboard...
701         kh = (key_down_timef(SDLK_KP_6) - key_down_timef(SDLK_KP_4))/8.0f;
702         if (kh == 0.0f)
703                 ci->heading = 0.0f;
704         else if (kh > 0.0f) {
705                 if (ci->heading < 0.0f)
706                         ci->heading = 0.0f;
707         } else // kh < 0
708                 if (ci->heading > 0.0f)
709                         ci->heading = 0.0f;
710         ci->heading += kh;
711
712         kh = (key_down_timef(SDLK_KP_8) - key_down_timef(SDLK_KP_2))/8.0f;
713         if (kh == 0.0f)
714                 ci->pitch = 0.0f;
715         else if (kh > 0.0f) {
716                 if (ci->pitch < 0.0f)
717                         ci->pitch = 0.0f;
718         } else // kh < 0
719                 if (ci->pitch > 0.0f)
720                         ci->pitch = 0.0f;
721         ci->pitch += kh;
722
723         ci->bank = (key_down_timef(SDLK_KP_7) - key_down_timef(SDLK_KP_9))*.75f;
724         ci->forward = key_down_timef(SDLK_a) - key_down_timef(SDLK_z);
725         ci->sideways = key_down_timef(SDLK_KP_3) - key_down_timef(SDLK_KP_1);
726         ci->vertical = key_down_timef(SDLK_KP_PLUS) - key_down_timef(SDLK_KP_ENTER);
727 }
728
729 int check_keys()
730 {
731         int k;
732
733         while( (k = key_inkey()) != 0 ) {
734 //mprintf(( "Key = %x\n", k ));
735                 if ( k == SDLK_ESCAPE ) {
736                         return 1;
737                 }
738
739                 switch( k )     {
740                 case SDLK_RETURN:
741                         Sel_mode = false;
742                         Vert_mode = !Vert_mode;
743                         Which_vert = 0;
744                         break;
745
746                 case SDLK_DELETE:
747                         if (Sel_mode) break;
748                         if (Vert_mode==1) delete_face(Current_face);
749                         else if (Vert_mode==0) {
750                                 delete_vert(Current_point);
751                         }
752                         break;
753
754                 case SDLK_MINUS:
755                         scale_factor -= 0.05f;
756                         mprintf(( "Scale = %.1f\n", scale_factor ));
757                         break;
758
759
760                 case SDLK_EQUALS:
761                         scale_factor += 0.05f;
762                         mprintf(( "Scale = %.1f\n", scale_factor ));
763                         break;
764
765                 case SDLK_INSERT:
766                         Sel_mode = !Sel_mode;
767                         break;
768
769                 case SDLK_SPACE:
770                         View_mode = !View_mode;
771                         break;
772
773                 case SDLK_COMMA:
774                         if (Sel_mode) {
775                                 int i;
776                                 for (i=0;i<num_pts;i++) if (Selected[i]) {
777                                         if ( l[i] > 0 ) {
778                                                 l[i]--;
779                                         }
780                                 }
781                         } else if (Vert_mode==0) {
782                                 if ( Current_point > -1 )       {
783                                         if ( l[Current_point] > 0 )     {
784                                                 l[Current_point]--;
785                                         }
786                                 }
787                         } else if (Vert_mode ==1) {
788                                 if ( l[tri[Current_face][0]] > 0 )      {
789                                                 l[tri[Current_face][0]]--;
790                                         }
791                                 if ( l[tri[Current_face][1]] > 0 )      {
792                                                 l[tri[Current_face][1]]--;
793                                         }
794                                 if ( l[tri[Current_face][2]] > 0 )      {
795                                                 l[tri[Current_face][2]]--;
796                                         }
797                         }
798                         break;
799
800                 case SDLK_PERIOD:
801                         if (Sel_mode) {
802                                 int i;
803                                 for (i=0;i<num_pts;i++) if (Selected[i]) {
804                                         if ( l[i] < 31 )        {
805                                                 l[i]++;
806                                         }
807                                 }
808                         } else if (Vert_mode==0) {
809                                 if ( Current_point > -1 )       {
810                                         if ( l[Current_point] < 31 )    {
811                                                 l[Current_point]++;
812                                         }
813                                 }
814                         } else if (Vert_mode ==1) {
815                                 if ( l[tri[Current_face][0]] <31 )      {
816                                                 l[tri[Current_face][0]]++;
817                                         }
818                                 if ( l[tri[Current_face][1]] <31)       {
819                                                 l[tri[Current_face][1]]++;
820                                         }
821                                 if ( l[tri[Current_face][2]] <31 )      {
822                                                 l[tri[Current_face][2]]++;
823                                         }
824                         }
825                         
826                         break;          
827
828                 case SDLK_F5:
829                         save_nebula();
830                         break;
831                 case SDLK_F7:
832                         load_nebula();
833                         break;
834
835                 case SDLK_BACKSPACE:
836                         sphericalize_nebula();
837                         break;
838                 }
839         }
840         return 0;
841 }
842
843 void os_close()
844 {
845         exit(1);
846 }
847
848 int newtri[3];
849
850 bool mdflag = false;
851
852 int main(int argc, char *argv[])
853 {
854         int i;
855         fix t1, t2;
856         control_info ci;
857         float speed = 20.0f;            // how fast viewer moves        
858
859         // setup the fred exe directory so CFILE can init properly
860         /*
861         char *c = GetCommandLine();
862         SDL_assert(c != NULL);
863         char *tok = strtok(c, " ");
864         SDL_assert(tok != NULL);        
865         */
866
867         Cmdline_window = 1; // always windowed
868
869         timer_init();
870         // cfile_init(tok);
871         cfile_init(argv[0]);
872         os_init( "NebEdit", "NebEdit" );        //SCREEN_W, SCREEN_H );
873         os_set_title("NebEdit");
874         gr_init(GR_640, GR_OPENGL, 16);
875         palette_load_table( "gamepalette1-01.pcx" );
876         key_init();
877         mouse_init();
878         SDL_ShowCursor(1);
879         Font1 = gr_init_font( "font01.vf" );
880         gr_init_alphacolor( &color_green, 0,255,0,255,AC_TYPE_HUD );
881
882         test_model = model_load( "fighter01.pof", 0, NULL );
883
884         physics_init( &ViewerPhysics );
885         ViewerPhysics.flags |= PF_ACCELERATES | PF_SLIDE_ENABLED;
886
887         ViewerPhysics.max_vel.xyz.x = 2.0f*speed;               //sideways
888         ViewerPhysics.max_vel.xyz.y = 2.0f*speed;               //up/down
889         ViewerPhysics.max_vel.xyz.z = 2.0f*speed;               //forward
890         ViewerPhysics.max_rear_vel = 2.0f*speed;        //backward -- controlled seperately
891         
892         memset( &ci, 0, sizeof(control_info) );
893
894         ModelOrient = vmd_identity_matrix;
895         ModelPos.xyz.x=0.0f; ModelPos.xyz.y = 0.0f; ModelPos.xyz.z = 0.0f;
896
897         ViewerOrient = vmd_identity_matrix;
898         ViewerPos.xyz.x=0.0f; ViewerPos.xyz.y = 0.0f; ViewerPos.xyz.z = -50.0f;
899
900         flFrametime = 0.033f;
901
902         t1 = timer_get_fixed_seconds();
903
904         nebula_init();
905
906         //bool some_selected = false;
907
908         while(1)        {
909                 os_poll();
910
911                 /*some_selected = false;
912                 if (Sel_mode) {
913                         for (i=0;i<num_pts;i++) {
914                                 if (Selected[i]) {
915                                         some_selected = true;
916                                         break;
917                                 }
918                         }
919                 }*/
920
921                 mouse_get_pos( &Mouse_x, &Mouse_y );
922
923                 if (Current_face==-1) {
924                         Current_face = get_closest_face(Mouse_x, Mouse_y);
925                 }
926                 
927                 if ( check_keys() ){
928                         break;
929                 }
930
931                 if ( Sel_mode==1 ) {
932                         // Special mouse handlers for multiple selmode
933                         if (mouse_down_count(LOWEST_MOUSE_BUTTON)) {
934                                 Orig_pos_x = Mouse_x;
935                                 Orig_pos_y = Mouse_y;
936                         }
937                         if (mouse_down(LOWEST_MOUSE_BUTTON)) {
938                                 for (i=0;i<num_pts;i++) {
939                                         if (Selected[i]) {
940                                                 x[i]+=Mouse_x - Orig_pos_x;
941                                                 y[i]+=Mouse_y - Orig_pos_y;
942                                         }
943                                 }
944                                 Orig_pos_x = Mouse_x;
945                                 Orig_pos_y = Mouse_y;
946                         }
947                         if (mouse_down_count(MOUSE_RIGHT_BUTTON)) {
948                                 Orig_pos_x = Mouse_x;
949                                 Orig_pos_y = Mouse_y;
950                                 for (i=0;i<num_pts;i++) {
951                                         Selected[i] = FALSE;
952                                 }
953                         }
954                         if (mouse_down(MOUSE_RIGHT_BUTTON)) {
955                                 Draw_sel_box = true;
956                                 End_pos_x = Mouse_x;
957                                 End_pos_y = Mouse_y;
958                         }
959                         if (mouse_up_count(MOUSE_RIGHT_BUTTON)) {
960                                 Draw_sel_box = false;
961                                 End_pos_x = Mouse_x;
962                                 End_pos_y = Mouse_y;
963                                 select_by_box(Orig_pos_x, Orig_pos_y, End_pos_x, End_pos_y);
964                         }
965
966                 } else {
967
968                         if ( mouse_down(LOWEST_MOUSE_BUTTON) )  {
969                                 if ( mdflag )   {
970                                         if (Vert_mode==0) {
971                                                 x[Current_point] = Mouse_x;
972                                                 y[Current_point] = Mouse_y;
973                                         } else if (Vert_mode==1) {
974                                                 x[tri[Current_face][0]] += Mouse_x - Orig_pos_x;
975                                                 y[tri[Current_face][0]] += Mouse_y - Orig_pos_y;
976                                                 x[tri[Current_face][1]] += Mouse_x - Orig_pos_x;
977                                                 y[tri[Current_face][1]] += Mouse_y - Orig_pos_y;
978                                                 x[tri[Current_face][2]] += Mouse_x - Orig_pos_x;
979                                                 y[tri[Current_face][2]] += Mouse_y - Orig_pos_y;
980                                                 Orig_pos_x = Mouse_x;
981                                                 Orig_pos_y = Mouse_y;
982                                         }
983                                 } else {
984                                         if (Vert_mode == 1) {
985                                                 Current_face = get_closest_face(Mouse_x, Mouse_y);
986                                                 Orig_pos_x = Mouse_x;
987                                                 Orig_pos_y = Mouse_y;
988                                         }
989                                         if (Vert_mode==0) {
990                                                 Current_point = get_closest(Mouse_x, Mouse_y);
991                                                 mouse_set_pos(x[Current_point], y[Current_point]);
992                                         }
993                                         mdflag = true;
994                                 }
995                         }
996                         if ( mouse_up_count(LOWEST_MOUSE_BUTTON)) {
997                                 //Current_point = -1;
998                                 //Current_face = -1;
999                                 mdflag = false;
1000                         }
1001
1002                         if ( mouse_up_count(MOUSE_RIGHT_BUTTON) ) {
1003                                 if (Vert_mode==0) {
1004                                         Current_point = add_vert(Mouse_x, Mouse_y);
1005                                 } else if (Vert_mode==1) {
1006                                         if ((num_tris<MAX_TRIS-1)) {
1007                                                 tri[num_tris][Which_vert] = get_closest(Mouse_x, Mouse_y);
1008                                                 Which_vert++;
1009                                                 if (Which_vert>2) {
1010                                                         Which_vert = 0;
1011                                                         num_tris++;
1012                                                 }
1013                                         }
1014                                 }
1015                         }
1016                 }
1017                 controls_read_all(&ci, flFrametime );
1018                 physics_read_flying_controls( &ViewerOrient, &ViewerPhysics, &ci, flFrametime );
1019                 physics_sim(&ViewerPos, &ViewerOrient, &ViewerPhysics, flFrametime );           
1020
1021                 render_frame();
1022
1023                 t2 = timer_get_fixed_seconds();
1024                 if ( t2 > t1 )  {
1025                         flFrametime = f2fl(t2 - t1);
1026                 }
1027
1028                 t1 = t2;
1029
1030                 SDL_Delay(10);
1031         }
1032
1033         nebedit_close();
1034
1035         return 0;
1036 }
1037
1038 // Stub functions and variables.
1039 // These do nothing but are needed to prevent link errors.
1040 void demo_set_playback_filter() {}
1041
1042 void freespace_menu_background()
1043 {
1044         gr_reset_clip();
1045         gr_clear();
1046 }
1047
1048 int game_check_key()
1049 {
1050         return key_inkey();
1051 }
1052
1053 int game_poll()
1054 {
1055         return key_inkey();
1056 }
1057
1058 vector Camera_pos;
1059 vector Dead_player_last_vel;
1060 // end stubs
1061