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