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