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