From a196e6d554f0c8f3687ea9707dec29c30a96f4f6 Mon Sep 17 00:00:00 2001 From: Bradley Bell Date: Thu, 25 Oct 2001 02:27:57 +0000 Subject: [PATCH] attempt at support for editor, makefile changes, etc --- Makefile.am | 6 +- configure.in | 8 +- main/Makefile.am | 10 +- main/editor/Makefile.am | 6 + main/editor/med.c | 1610 +++++++++++++++++++++++++++ main/editor/medwall.h | 109 ++ main/editor/segment.c | 2271 +++++++++++++++++++++++++++++++++++++++ main/editor/seguvs.h | 50 + sound/Makefile.am | 2 + video/Makefile.am | 2 + 10 files changed, 4068 insertions(+), 6 deletions(-) create mode 100644 main/editor/Makefile.am create mode 100644 main/editor/med.c create mode 100644 main/editor/medwall.h create mode 100644 main/editor/segment.c create mode 100644 main/editor/seguvs.h diff --git a/Makefile.am b/Makefile.am index fc7eeacf..2c61aeca 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,13 +21,17 @@ ARCH_LIBS = arch/linux/libarch_linux.a arch/sdl/libarch_sdl.a endif endif +if EDITOR +EDITOR_LIBS = main/editor/libeditor.a +endif + d2x_SOURCES = d2x_sdl_SOURCES = d2x_ogl_SOURCES = d2x_svga_SOURCES = d2x_ggi_SOURCES = -d2x_LDADD = ${LD_KLUDGE} main/libmain.a 3d/lib3d.a 2d/lib2d.a ${ARCH_LIBS} mem/libmem.a cfile/libcfile.a iff/libiff.a texmap/libtexmap.a misc/libmisc.a maths/libmaths.a video/libvideo.a sound/libsound.a input/libinput.a +d2x_LDADD = ${LD_KLUDGE} main/libmain.a ${EDITOR_LIBS} 3d/lib3d.a 2d/lib2d.a ${ARCH_LIBS} mem/libmem.a cfile/libcfile.a iff/libiff.a texmap/libtexmap.a misc/libmisc.a maths/libmaths.a video/libvideo.a sound/libsound.a if MINGW32 if USE_NETWORK diff --git a/configure.in b/configure.in index 5fedb04f..a30e89c1 100644 --- a/configure.in +++ b/configure.in @@ -43,6 +43,7 @@ AC_ARG_ENABLE(editor, [ --enable-editor Build editor? (not functional)],,) if test x$enable_editor = xyes; then AC_DEFINE(EDITOR) + D2X_MAIN_SUBDIRS=editor fi AM_CONDITIONAL(EDITOR, test x$enable_editor = xyes) @@ -88,8 +89,6 @@ else ) AC_SUBST(SDL_LIBS) - CFLAGS="$SDL_CFLAGS $CFLAGS" - TARGETS=d2x-sdl D2X_ARCH_SUBDIRS=sdl @@ -196,8 +195,12 @@ else fi AM_CONDITIONAL(USE_ASM, test x$enable_assembler != xno) +AM_PROG_AS + AC_SUBST(D2X_ARCH_SUBDIRS) +AC_SUBST(D2X_MAIN_SUBDIRS) + AC_SUBST(TARGETS) AC_SUBST(NASMFLAGS) @@ -218,6 +221,7 @@ arch/win32/Makefile cfile/Makefile iff/Makefile main/Makefile +main/editor/Makefile maths/Makefile mem/Makefile misc/Makefile diff --git a/main/Makefile.am b/main/Makefile.am index 44705fee..66254bbc 100644 --- a/main/Makefile.am +++ b/main/Makefile.am @@ -1,11 +1,15 @@ -EXTRA_SUBDIRS = editor old +SUBDIRS = @D2X_MAIN_SUBDIRS@ -noinst_LIBRARIES = libmain.a +DIST_SUBDIRS = editor + +EXTRA_SUBDIRS = old -CFLAGS += -fwritable-strings +noinst_LIBRARIES = libmain.a INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/arch/include +CFLAGS += -fwritable-strings ${SDL_CFLAGS} + if USE_NETWORK NETWORK_SRCS = ipx_drv.c kmatrix.c multi.c multibot.c network.c else diff --git a/main/editor/Makefile.am b/main/editor/Makefile.am new file mode 100644 index 00000000..935fa6ae --- /dev/null +++ b/main/editor/Makefile.am @@ -0,0 +1,6 @@ +noinst_LIBRARIES = libeditor.a +INCLUDES = -I$(top_srcdir)/includes -I$(top_srcdir)/arch/include -I$(top_srcdir)/main + +libeditor_a_SOURCES = med.c segment.c + +EXTRA_DIST = editor.h kdefs.h medwall.h seguvs.h texpage.h diff --git a/main/editor/med.c b/main/editor/med.c new file mode 100644 index 00000000..416b55c4 --- /dev/null +++ b/main/editor/med.c @@ -0,0 +1,1610 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/main/editor/med.c,v $ + * $Revision: 1.1 $ + * $Author: bradleyb $ + * $Date: 2001-10-25 02:27:17 $ + * + * Editor loop for Inferno + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:43 donut + * Import of d1x 1.37 source. + * + * Revision 2.3 1995/03/06 18:23:52 john + * Fixed bug with font screwing up. + * + * Revision 2.2 1995/03/06 16:34:55 john + * Fixed bug with previous. + * + * Revision 2.1 1995/03/06 15:20:57 john + * New screen mode method. + * + * Revision 2.0 1995/02/27 11:35:54 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.192 1994/11/30 12:33:55 mike + * set window clearing mode for editor. + * + * Revision 1.191 1994/11/27 23:17:02 matt + * Made changes for new mprintf calling convention + * + * Revision 1.190 1994/11/19 00:04:33 john + * Changed some shorts to ints. + * + * Revision 1.189 1994/11/17 14:47:57 mike + * validation functions moved from editor to game. + * + * Revision 1.188 1994/11/14 11:41:38 john + * Fixed bug with editor/game sequencing. + * + * Revision 1.187 1994/11/13 15:36:44 john + * Changed game sequencing with editor. + * + * Revision 1.186 1994/11/10 16:49:12 matt + * Don't sort seg list if no segs in list + * + * Revision 1.185 1994/11/08 09:28:39 mike + * reset ai paths on going to game. + * + * Revision 1.184 1994/10/30 14:13:05 mike + * rip out repair center stuff. + * + * Revision 1.183 1994/10/27 10:07:06 mike + * adapt to no inverse table. + * + * Revision 1.182 1994/10/20 12:48:03 matt + * Replaced old save files (MIN/SAV/HOT) with new LVL files + * + * Revision 1.181 1994/10/13 11:39:22 john + * Took out network stuff/. + * + * Revision 1.180 1994/10/07 22:21:38 mike + * Stop Delete-{whatever} from hanging you! + * + * Revision 1.179 1994/10/03 23:39:37 mike + * Adapt to newer, better, fuelcen_activate function. + * + * Revision 1.178 1994/09/30 00:38:05 mike + * Shorten diagnostic message erase -- was erasing outside canvas. + * + * Revision 1.177 1994/09/28 17:31:37 mike + * Add call to check_wall_validity(); + * + * Revision 1.176 1994/08/19 10:57:42 mike + * Fix status message erase bug. + * + * Revision 1.175 1994/08/18 10:48:12 john + * Cleaned up game sequencing. + * + * Revision 1.174 1994/08/16 18:11:04 yuan + * Maded C place you in the center of a segment. + * + * Revision 1.173 1994/08/10 19:55:05 john + * Changed font stuff. + * + * Revision 1.172 1994/08/09 16:06:06 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.171 1994/08/04 09:14:11 matt + * Fixed problem I said I fixed last time + * + * Revision 1.170 1994/08/04 00:27:57 matt + * When viewing a wall, update the objects segnum if moved out of the segment + * + * Revision 1.169 1994/08/02 14:18:12 mike + * Clean up dialog boxes. + * + * Revision 1.168 1994/07/29 15:34:35 mike + * Kill some mprintfs. + * + * Revision 1.167 1994/07/29 14:56:46 yuan + * Close centers window, when you go into game. + * + * Revision 1.166 1994/07/28 17:16:20 john + * MAde editor use Network stuff. + * + * Revision 1.165 1994/07/28 16:59:10 mike + * objects containing objects. + * + * Revision 1.164 1994/07/22 12:37:07 matt + * Cleaned up editor/game interactions some more. + * + * Revision 1.163 1994/07/21 19:35:11 yuan + * Fixed #include problem + * + * Revision 1.162 1994/07/21 18:02:09 matt + * Don't re-init player stats when going from editor -> game + * + * Revision 1.161 1994/07/21 12:47:53 mike + * Add tilde key functionality for object movement. + * + * Revision 1.160 1994/07/18 10:44:55 mike + * One-click access to keypads. + * + * Revision 1.159 1994/07/01 18:05:54 john + * *** empty log message *** + * + * Revision 1.158 1994/07/01 17:57:06 john + * First version of not-working hostage system + * + * + * Revision 1.157 1994/07/01 11:32:29 john + * *** empty log message *** + * + * Revision 1.156 1994/06/24 17:04:36 john + * *** empty log message *** + * + * Revision 1.155 1994/06/23 15:53:47 matt + * Finished hacking in 3d rendering in big window + * + * Revision 1.154 1994/06/21 16:17:54 yuan + * Init stats when you go to game from editor + * + * Revision 1.153 1994/06/21 12:57:14 yuan + * Remove center from segment function added to menu. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +//#define DEMO 1 + +#define DIAGNOSTIC_MESSAGE_MAX 90 +#define EDITOR_STATUS_MESSAGE_DURATION 4 // Shows for 3+..4 seconds + +#include +#include +#include +#include +#include + +#ifdef __MSDOS__ +#include +#endif + + +//#define INCLUDE_XLISP + +#include "inferno.h" +#include "segment.h" +#include "gr.h" +#include "ui.h" +#include "editor.h" +//#include "gamemine.h" +#include "gamesave.h" +#include "gameseg.h" + +#include "key.h" +#include "mono.h" +#include "error.h" +#include "kfuncs.h" +#include "macro.h" + +#ifdef INCLUDE_XLISP +#include "medlisp.h" +#endif +#include "u_mem.h" +#include "render.h" +#include "game.h" +#include "slew.h" +#include "kdefs.h" +#include "func.h" +#include "textures.h" +#include "screens.h" +#include "texmap.h" +#include "object.h" +#include "effects.h" +#include "wall.h" +#include "info.h" +#include "ai.h" + +#include "texpage.h" // Textue selection paging stuff +#include "objpage.h" // Object selection paging stuff + +#include "medmisc.h" +#include "meddraw.h" +#include "medsel.h" +#include "medrobot.h" +#include "medwall.h" +#include "eswitch.h" +#include "ehostage.h" +#include "centers.h" + +#include "fuelcen.h" +#include "gameseq.h" +#include "newmenu.h" + +//#define _MARK_ON 1 +//#include //should come after inferno.h to get mark setting //Not included here. + +#define COMPRESS_INTERVAL 5 // seconds + +//char *undo_status[128]; + +int initializing; + +//these are instances of canvases, pointed to by variables below +grs_canvas _canv_editor_game; //the game on the editor screen + +//these are pointers to our canvases +grs_canvas *Canv_editor; //the editor screen +grs_canvas *Canv_editor_game=&_canv_editor_game; //the game on the editor screen + +grs_canvas *canv_offscreen; //for off-screen rendering +grs_canvas *Pad_text_canvas; // Keypad text + +grs_font *editor_font=NULL; + +//where the editor is looking +vms_vector Ed_view_target={0,0,0}; + +int gamestate_not_restored = 0; + +UI_WINDOW * EditorWindow; + +int Large_view_index = -1; + +UI_GADGET_USERBOX * GameViewBox; +UI_GADGET_USERBOX * LargeViewBox; +UI_GADGET_USERBOX * GroupViewBox; + +#if ORTHO_VIEWS +UI_GADGET_USERBOX * TopViewBox; +UI_GADGET_USERBOX * FrontViewBox; +UI_GADGET_USERBOX * RightViewBox; +#endif + +UI_GADGET_ICON * ViewIcon; +UI_GADGET_ICON * AllIcon; +UI_GADGET_ICON * AxesIcon; +UI_GADGET_ICON * ChaseIcon; +UI_GADGET_ICON * OutlineIcon; +UI_GADGET_ICON * LockIcon; +//-NOLIGHTICON- UI_GADGET_ICON * LightIcon; + +UI_EVENT * DemoBuffer = NULL; + +//grs_canvas * BigCanvas[2]; +//int CurrentBigCanvas = 0; +//int BigCanvasFirstTime = 1; + +int Found_seg_index=0; // Index in Found_segs corresponding to Cursegp + + +void print_status_bar( char message[DIAGNOSTIC_MESSAGE_MAX] ) { + int w,h,aw; + + gr_set_current_canvas( NULL ); + gr_set_curfont(editor_font); + gr_set_fontcolor( CBLACK, CGREY ); + gr_get_string_size( message, &w, &h, &aw ); + gr_string( 4, 583, message ); + gr_set_fontcolor( CBLACK, CWHITE ); + gr_setcolor( CGREY ); + gr_rect( 4+w, 583, 799, 599 ); +} + +void print_diagnostic( char message[DIAGNOSTIC_MESSAGE_MAX] ) { + int w,h,aw; + + gr_set_current_canvas( NULL ); + gr_set_curfont(editor_font); + gr_set_fontcolor( CBLACK, CGREY ); + gr_get_string_size( message, &w, &h, &aw ); + gr_string( 4, 583, message ); + gr_set_fontcolor( CBLACK, CWHITE ); + gr_setcolor( CGREY ); + gr_rect( 4+w, 583, 799, 599 ); +} + +static char status_line[DIAGNOSTIC_MESSAGE_MAX]; + +struct tm Editor_status_last_time; + +void editor_status( const char *format, ... ) +{ + va_list ap; + + va_start(ap, format); + vsprintf(status_line, format, ap); + va_end(ap); + + print_status_bar(status_line); + + Editor_status_last_time = Editor_time_of_day; + +} + +// int tm_sec; /* seconds after the minute -- [0,61] */ +// int tm_min; /* minutes after the hour -- [0,59] */ +// int tm_hour; /* hours after midnight -- [0,23] */ +// int tm_mday; /* day of the month -- [1,31] */ +// int tm_mon; /* months since January -- [0,11] */ +// int tm_year; /* years since 1900 */ +// int tm_wday; /* days since Sunday -- [0,6] */ +// int tm_yday; /* days since January 1 -- [0,365]*/ +// int tm_isdst; /* Daylight Savings Time flag */ + +void clear_editor_status(void) +{ + int cur_time = Editor_time_of_day.tm_hour * 3600 + Editor_time_of_day.tm_min*60 + Editor_time_of_day.tm_sec; + int erase_time = Editor_status_last_time.tm_hour * 3600 + Editor_status_last_time.tm_min*60 + Editor_status_last_time.tm_sec + EDITOR_STATUS_MESSAGE_DURATION; + + if (cur_time > erase_time) { + int i; + char message[DIAGNOSTIC_MESSAGE_MAX]; + + for (i=0; ipos; +//@@ Player_init.orient = Player->orient; +//@@ Player_init.segnum = Player->segnum; + +// -- must always save gamesave.sav because the restore-objects code relies on it +// -- that code could be made smarter and use the original file, if appropriate. +// if (mine_changed) + if (gamestate_not_restored == 0) { + gamestate_not_restored = 1; + save_level("GAMESAVE.LVL"); + editor_status("Gamestate saved.\n"); + mprintf((0, "Gamestate saved.\n")); + } + + ai_reset_all_paths(); + + start_time(); + + ModeFlag = mode; + return 1; +} + +int GotoGameScreen() +{ + return GotoGameCommon(3); +} + +int GotoGame() +{ + return GotoGameCommon(2); +} + + +void ReadLispMacro( FILE * file, char * buffer ) +{ +// char c; +// int size=0; +// int pcount = 0; +// char text[100]; +// int i=0; + + fscanf( file, " { %s } ", buffer ); + +/* + while (1) + { + c = text[i++]; + if (pcount > 0 ) + buffer[size++] = c; + if ( c == '(' ) pcount++; + if ( c == ')' ) break; + } + buffer[size++] = 0; +*/ + + return; +} + +static int (*KeyFunction[2048])(); + +void medkey_init() +{ + FILE * keyfile; + char keypress[100]; + int key; + int i; //, size; + int np; + char * LispCommand; + + MALLOC( LispCommand, char, DIAGNOSTIC_MESSAGE_MAX ); + + for (i=0; i<2048; i++ ) + KeyFunction[i] = NULL; + + keyfile = fopen( "GLOBAL.KEY", "rt" ); + if (keyfile) + { + while (fscanf( keyfile, " %s %s ", keypress, LispCommand ) != EOF ) + { + //ReadLispMacro( keyfile, LispCommand ); + + if ( (key=DecodeKeyText( keypress ))!= -1 ) + { + Assert( key < 2048); + KeyFunction[key] = func_get( LispCommand, &np ); + } else { + Error( "Bad key %s in GLOBAL.KEY!", keypress ); + } + } + fclose(keyfile); + } + free( LispCommand ); +} + +void init_editor() +{ + minit(); + + ui_init(); + + init_med_functions(); // Must be called before medlisp_init + + ui_pad_read( 0, "segmove.pad" ); + ui_pad_read( 1, "segsize.pad" ); + ui_pad_read( 2, "curve.pad" ); + ui_pad_read( 3, "texture.pad" ); + ui_pad_read( 4, "object.pad" ); + ui_pad_read( 5, "objmov.pad" ); + ui_pad_read( 6, "group.pad" ); + ui_pad_read( 7, "lighting.pad" ); + ui_pad_read( 8, "test.pad" ); + + medkey_init(); + + editor_font = gr_init_font( "pc8x16.fnt" ); + + menubar_init( "MED.MNU" ); + + canv_offscreen = gr_create_canvas(LVIEW_W,LVIEW_H); + + Draw_all_segments = 1; // Say draw all segments, not just connected ones + + init_autosave(); + +// atexit(close_editor); + + Clear_window = 1; // do full window clear. +} + +int ShowAbout() +{ + MessageBox( -2, -2, 1, "INFERNO Mine Editor\n\n" \ + "Copyright (c) 1993 Parallax Software Corp.", + "OK"); + return 0; +} + +void move_player_2_segment(segment *seg,int side); + +int SetPlayerFromCurseg() +{ + move_player_2_segment(Cursegp,Curside); + Update_flags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; + return 1; +} + +int fuelcen_create_from_curseg() +{ + Cursegp->special = SEGMENT_IS_FUELCEN; + fuelcen_activate( Cursegp, Cursegp->special); + return 1; +} + +int repaircen_create_from_curseg() +{ + Int3(); // -- no longer supported! +// Cursegp->special = SEGMENT_IS_REPAIRCEN; +// fuelcen_activate( Cursegp, Cursegp->special); + return 1; +} + +int controlcen_create_from_curseg() +{ + Cursegp->special = SEGMENT_IS_CONTROLCEN; + fuelcen_activate( Cursegp, Cursegp->special); + return 1; +} + +int robotmaker_create_from_curseg() +{ + Cursegp->special = SEGMENT_IS_ROBOTMAKER; + fuelcen_activate( Cursegp, Cursegp->special); + return 1; +} + +int fuelcen_reset_all() { + fuelcen_reset(); + return 1; +} + +int fuelcen_delete_from_curseg() { + fuelcen_delete( Cursegp ); + return 1; +} + + +//@@//this routine places the viewer in the center of the side opposite to curside, +//@@//with the view toward the center of curside +//@@int SetPlayerFromCursegMinusOne() +//@@{ +//@@ vms_vector vp; +//@@ +//@@// int newseg,newside; +//@@// get_previous_segment(SEG_PTR_2_NUM(Cursegp),Curside,&newseg,&newside); +//@@// move_player_2_segment(&Segments[newseg],newside); +//@@ +//@@ med_compute_center_point_on_side(&Player->obj_position,Cursegp,Side_opposite[Curside]); +//@@ med_compute_center_point_on_side(&vp,Cursegp,Curside); +//@@ vm_vec_sub2(&vp,&Player->position); +//@@ vm_vector_2_matrix(&Player->orient,&vp,NULL,NULL); +//@@ +//@@ Player->seg = SEG_PTR_2_NUM(Cursegp); +//@@ +//@@ Update_flags |= UF_GAME_VIEW_CHANGED; +//@@ return 1; +//@@} + +//this constant determines how much of the window will be occupied by the +//viewed side when SetPlayerFromCursegMinusOne() is called. It actually +//determine how from from the center of the window the farthest point will be +#define SIDE_VIEW_FRAC (f1_0*8/10) //80% + + +void move_player_2_segment_and_rotate(segment *seg,int side) +{ + vms_vector vp; + vms_vector upvec; + static int edgenum=0; + + compute_segment_center(&ConsoleObject->pos,seg); + compute_center_point_on_side(&vp,seg,side); + vm_vec_sub2(&vp,&ConsoleObject->pos); + + vm_vec_sub(&upvec, &Vertices[Cursegp->verts[Side_to_verts[Curside][edgenum%4]]], &Vertices[Cursegp->verts[Side_to_verts[Curside][(edgenum+3)%4]]]); + edgenum++; + + vm_vector_2_matrix(&ConsoleObject->orient,&vp,&upvec,NULL); +// vm_vector_2_matrix(&ConsoleObject->orient,&vp,NULL,NULL); + + obj_relink( ConsoleObject-Objects, SEG_PTR_2_NUM(seg) ); + +} + +int SetPlayerFromCursegAndRotate() +{ + move_player_2_segment_and_rotate(Cursegp,Curside); + Update_flags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; + return 1; +} + + +//sets the player facing curseg/curside, normal to face0 of curside, and +//far enough away to see all of curside +int SetPlayerFromCursegMinusOne() +{ + vms_vector view_vec,view_vec2,side_center; + vms_vector corner_v[4]; + vms_vector upvec; + g3s_point corner_p[4]; + int i; + fix max,view_dist=f1_0*10; + static int edgenum=0; + int newseg; + + view_vec = Cursegp->sides[Curside].normals[0]; + vm_vec_negate(&view_vec); + + compute_center_point_on_side(&side_center,Cursegp,Curside); + vm_vec_copy_scale(&view_vec2,&view_vec,view_dist); + vm_vec_sub(&ConsoleObject->pos,&side_center,&view_vec2); + + vm_vec_sub(&upvec, &Vertices[Cursegp->verts[Side_to_verts[Curside][edgenum%4]]], &Vertices[Cursegp->verts[Side_to_verts[Curside][(edgenum+3)%4]]]); + edgenum++; + + vm_vector_2_matrix(&ConsoleObject->orient,&view_vec,&upvec,NULL); + + gr_set_current_canvas(Canv_editor_game); + g3_start_frame(); + g3_set_view_matrix(&ConsoleObject->pos,&ConsoleObject->orient,Render_zoom); + + for (i=max=0;i<4;i++) { + corner_v[i] = Vertices[Cursegp->verts[Side_to_verts[Curside][i]]]; + g3_rotate_point(&corner_p[i],&corner_v[i]); + if (labs(corner_p[i].p3_x) > max) max = labs(corner_p[i].p3_x); + if (labs(corner_p[i].p3_y) > max) max = labs(corner_p[i].p3_y); + } + + view_dist = fixmul(view_dist,fixdiv(fixdiv(max,SIDE_VIEW_FRAC),corner_p[0].p3_z)); + vm_vec_copy_scale(&view_vec2,&view_vec,view_dist); + vm_vec_sub(&ConsoleObject->pos,&side_center,&view_vec2); + + //obj_relink(ConsoleObject-Objects, SEG_PTR_2_NUM(Cursegp) ); + //update_object_seg(ConsoleObject); //might have backed right out of curseg + + newseg = find_point_seg(&ConsoleObject->pos,SEG_PTR_2_NUM(Cursegp) ); + if (newseg != -1) + obj_relink(ConsoleObject-Objects,newseg); + + Update_flags |= UF_ED_STATE_CHANGED | UF_GAME_VIEW_CHANGED; + return 1; +} + +int ToggleLighting(void) +{ + char outstr[80] = "[shift-L] "; + int chindex; + + Lighting_on++; + if (Lighting_on >= 2) + Lighting_on = 0; + + Update_flags |= UF_GAME_VIEW_CHANGED; + + if (last_keypress == KEY_L + KEY_SHIFTED) + chindex = 0; + else + chindex = 10; + + switch (Lighting_on) { + case 0: + strcpy(&outstr[chindex],"Lighting off."); + break; + case 1: + strcpy(&outstr[chindex],"Static lighting."); + break; + case 2: + strcpy(&outstr[chindex],"Ship lighting."); + break; + case 3: + strcpy(&outstr[chindex],"Ship and static lighting."); + break; + } + + diagnostic_message(outstr); + + return Lighting_on; +} + +void find_concave_segs(); + +int FindConcaveSegs() +{ + find_concave_segs(); + + Update_flags |= UF_ED_STATE_CHANGED; //list may have changed + + return 1; +} + +int DosShell() +{ + int ok, w, h; + grs_bitmap * save_bitmap; + + // Save the current graphics state. + + w = grd_curscreen->sc_canvas.cv_bitmap.bm_w; + h = grd_curscreen->sc_canvas.cv_bitmap.bm_h; + + save_bitmap = gr_create_bitmap( w, h ); + gr_bm_ubitblt(w, h, 0, 0, 0, 0, &(grd_curscreen->sc_canvas.cv_bitmap), save_bitmap ); + + gr_set_mode( SM_ORIGINAL ); + + printf( "\n\nType EXIT to return to Inferno" ); + fflush(stdout); + + key_close(); +#ifndef __LINUX__ + ok = spawnl(P_WAIT,getenv("COMSPEC"), NULL ); +#else + system(""); +#endif + key_init(); + + gr_set_mode(grd_curscreen->sc_mode); + gr_bm_ubitblt(w, h, 0, 0, 0, 0, save_bitmap, &(grd_curscreen->sc_canvas.cv_bitmap)); + gr_free_bitmap( save_bitmap ); + //gr_pal_setblock( 0, 256, grd_curscreen->pal ); + //gr_use_palette_table(); + + return 1; + +} + +int ToggleOutlineMode() +{ int mode; + + mode=toggle_outline_mode(); + + if (mode) + { + if (last_keypress != KEY_O) + diagnostic_message("[O] Outline Mode ON."); + else + diagnostic_message("Outline Mode ON."); + } + else + { + if (last_keypress != KEY_O) + diagnostic_message("[O] Outline Mode OFF."); + else + diagnostic_message("Outline Mode OFF."); + } + + Update_flags |= UF_GAME_VIEW_CHANGED; + return mode; +} + +//@@int do_reset_orient() +//@@{ +//@@ slew_reset_orient(SlewObj); +//@@ +//@@ Update_flags |= UF_GAME_VIEW_CHANGED; +//@@ +//@@ * (ubyte *) 0x417 &= ~0x20; +//@@ +//@@ return 1; +//@@} + +int GameZoomOut() +{ + Render_zoom = fixmul(Render_zoom,68985); + Update_flags |= UF_GAME_VIEW_CHANGED; + return 1; +} + +int GameZoomIn() +{ + Render_zoom = fixmul(Render_zoom,62259); + Update_flags |= UF_GAME_VIEW_CHANGED; + return 1; +} + + +int med_keypad_goto_0() { ui_pad_goto(0); return 0; } +int med_keypad_goto_1() { ui_pad_goto(1); return 0; } +int med_keypad_goto_2() { ui_pad_goto(2); return 0; } +int med_keypad_goto_3() { ui_pad_goto(3); return 0; } +int med_keypad_goto_4() { ui_pad_goto(4); return 0; } +int med_keypad_goto_5() { ui_pad_goto(5); return 0; } +int med_keypad_goto_6() { ui_pad_goto(6); return 0; } +int med_keypad_goto_7() { ui_pad_goto(7); return 0; } +int med_keypad_goto_8() { ui_pad_goto(8); return 0; } + +#define PAD_WIDTH 30 +#define PAD_WIDTH1 (PAD_WIDTH + 7) + +int editor_screen_open = 0; + +//setup the editors windows, canvases, gadgets, etc. +//called whenever the editor screen is selected +void init_editor_screen() +{ +// grs_bitmap * bmp; + + if (editor_screen_open) return; + + grd_curscreen->sc_canvas.cv_font = editor_font; + + //create canvas for game on the editor screen + initializing = 1; + gr_set_current_canvas(Canv_editor); + Canv_editor->cv_font = editor_font; + gr_init_sub_canvas(Canv_editor_game,Canv_editor,GAMEVIEW_X,GAMEVIEW_Y,GAMEVIEW_W,GAMEVIEW_H); + + //Editor renders into full (320x200) game screen + + init_info = 1; + + //do other editor screen setup + + // Since the palette might have changed, find some good colors... + CBLACK = gr_find_closest_color( 1, 1, 1 ); + CGREY = gr_find_closest_color( 28, 28, 28 ); + CWHITE = gr_find_closest_color( 38, 38, 38 ); + CBRIGHT = gr_find_closest_color( 60, 60, 60 ); + CRED = gr_find_closest_color( 63, 0, 0 ); + + gr_set_curfont(editor_font); + gr_set_fontcolor( CBLACK, CWHITE ); + + EditorWindow = ui_open_window( 0 , 0, ED_SCREEN_W, ED_SCREEN_H, WIN_FILLED ); + + LargeViewBox = ui_add_gadget_userbox( EditorWindow,LVIEW_X,LVIEW_Y,LVIEW_W,LVIEW_H); +#if ORTHO_VIEWS + TopViewBox = ui_add_gadget_userbox( EditorWindow,TVIEW_X,TVIEW_Y,TVIEW_W,TVIEW_H); + FrontViewBox = ui_add_gadget_userbox( EditorWindow,FVIEW_X,FVIEW_Y,FVIEW_W,FVIEW_H); + RightViewBox = ui_add_gadget_userbox( EditorWindow,RVIEW_X,RVIEW_Y,RVIEW_W,RVIEW_H); +#endif + ui_gadget_calc_keys(EditorWindow); //make tab work for all windows + + GameViewBox = ui_add_gadget_userbox( EditorWindow, GAMEVIEW_X, GAMEVIEW_Y, GAMEVIEW_W, GAMEVIEW_H ); +// GroupViewBox = ui_add_gadget_userbox( EditorWindow,GVIEW_X,GVIEW_Y,GVIEW_W,GVIEW_H); + +// GameViewBox->when_tab = GameViewBox->when_btab = (UI_GADGET *) LargeViewBox; +// LargeViewBox->when_tab = LargeViewBox->when_btab = (UI_GADGET *) GameViewBox; + +// ui_gadget_calc_keys(EditorWindow); //make tab work for all windows + + ViewIcon = ui_add_gadget_icon( EditorWindow, "Lock\nview", 455,25+530, 40, 22, KEY_V+KEY_CTRLED, ToggleLockViewToCursegp ); + AllIcon = ui_add_gadget_icon( EditorWindow, "Draw\nall", 500,25+530, 40, 22, KEY_A+KEY_CTRLED, ToggleDrawAllSegments ); + AxesIcon = ui_add_gadget_icon( EditorWindow, "Coord\naxes",545,25+530, 40, 22, KEY_D+KEY_CTRLED, ToggleCoordAxes ); +//-NOLIGHTICON- LightIcon = ui_add_gadget_icon( EditorWindow, "Light\ning", 590,25+530, 40, 22, KEY_L+KEY_SHIFTED,ToggleLighting ); + ChaseIcon = ui_add_gadget_icon( EditorWindow, "Chase\nmode",635,25+530, 40, 22, -1, ToggleChaseMode ); + OutlineIcon = ui_add_gadget_icon( EditorWindow, "Out\nline", 680,25+530, 40, 22, KEY_O, ToggleOutlineMode ); + LockIcon = ui_add_gadget_icon( EditorWindow, "Lock\nstep", 725,25+530, 40, 22, KEY_L, ToggleLockstep ); + + meddraw_init_views(LargeViewBox->canvas); + + //ui_add_gadget_button( EditorWindow, 460, 510, 50, 25, "Quit", ExitEditor ); + //ui_add_gadget_button( EditorWindow, 520, 510, 50, 25, "Lisp", CallLisp ); + //ui_add_gadget_button( EditorWindow, 580, 510, 50, 25, "Mine", MineMenu ); + //ui_add_gadget_button( EditorWindow, 640, 510, 50, 25, "Help", DoHelp ); + //ui_add_gadget_button( EditorWindow, 460, 540, 50, 25, "Macro", MacroMenu ); + //ui_add_gadget_button( EditorWindow, 520, 540, 50, 25, "About", ShowAbout ); + //ui_add_gadget_button( EditorWindow, 640, 540, 50, 25, "Shell", DosShell ); + + ui_pad_activate( EditorWindow, PAD_X, PAD_Y ); + Pad_text_canvas = gr_create_sub_canvas(Canv_editor, PAD_X + 250, PAD_Y + 8, 180, 160); + ui_add_gadget_button( EditorWindow, PAD_X+6, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "<<", med_keypad_goto_prev ); + ui_add_gadget_button( EditorWindow, PAD_X+PAD_WIDTH1+6, PAD_Y+(30*5)+22, PAD_WIDTH, 20, ">>", med_keypad_goto_next ); + + { int i; + i = 0; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "SR", med_keypad_goto_0 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "SS", med_keypad_goto_1 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "CF", med_keypad_goto_2 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "TM", med_keypad_goto_3 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "OP", med_keypad_goto_4 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "OR", med_keypad_goto_5 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "GE", med_keypad_goto_6 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "LI", med_keypad_goto_7 ); + i++; ui_add_gadget_button( EditorWindow, PAD_X+16+(i+2)*PAD_WIDTH1, PAD_Y+(30*5)+22, PAD_WIDTH, 20, "TT", med_keypad_goto_8 ); + } + + gr_set_curfont(editor_font); + menubar_show(); + + // INIT TEXTURE STUFF + texpage_init( EditorWindow ); + objpage_init( EditorWindow ); + + EditorWindow->keyboard_focus_gadget = (UI_GADGET *)LargeViewBox; + + canv_offscreen->cv_font = grd_curscreen->sc_canvas.cv_font; +// BigCanvas[0]->cv_font = grd_curscreen->sc_canvas.cv_font; +// BigCanvas[1]->cv_font = grd_curscreen->sc_canvas.cv_font; +// BigCanvasFirstTime = 1; + + // Draw status box + gr_set_current_canvas( NULL ); + gr_setcolor( CGREY ); + gr_rect(STATUS_X,STATUS_Y,STATUS_X+STATUS_W-1,STATUS_Y+STATUS_H-1); //0, 582, 799, 599 ); + + // Draw icon box + // gr_set_current_canvas( NULL ); + // gr_setcolor( CBRIGHT ); + // gr_rect( 528, 2, 798, 22); + // gr_setcolor( CGREY); + // gr_rect( 530, 2, 799, 20); + + Update_flags = UF_ALL; + initializing = 0; + editor_screen_open = 1; +} + +//shutdown ui on the editor screen +void close_editor_screen() +{ + if (!editor_screen_open) return; + + editor_screen_open = 0; + ui_pad_deactivate(); + gr_free_sub_canvas(Pad_text_canvas); + + ui_close_window(EditorWindow); + + close_all_windows(); + + // CLOSE TEXTURE STUFF + texpage_close(); + objpage_close(); + + menubar_hide(); + +} + +void med_show_warning(char *s) +{ + grs_canvas *save_canv=grd_curcanv; + + //gr_pal_fade_in(grd_curscreen->pal); //in case palette is blacked + + MessageBox(-2,-2,1,s,"OK"); + + gr_set_current_canvas(save_canv); + +} + +// Returns 1 if OK to trash current mine. +int SafetyCheck() +{ + int x; + + if (mine_changed) { + stop_time(); + x = nm_messagebox( "Warning!", 2, "Cancel", "OK", "You are about to lose work." ); + if (x<1) { + start_time(); + return 0; + } + start_time(); + } + return 1; +} + +//called at the end of the program +void close_editor() { + + close_autosave(); + + menubar_close(); + + gr_close_font(editor_font); + + gr_free_canvas(canv_offscreen); canv_offscreen = NULL; + + return; + +} + +//variables for find segments process + +// --------------------------------------------------------------------------------------------------- +// Subtract all elements in Found_segs from selected list. +void subtract_found_segments_from_selected_list(void) +{ + int s,f; + + for (f=0; fpos; + Save_position.orient = ConsoleObject->orient; + Save_position.segnum = ConsoleObject->segnum; + + load_level("GAMESAVE.LVL"); + + // Restore current position + if (Save_position.segnum <= Highest_segment_index) { + ConsoleObject->pos = Save_position.pos; + ConsoleObject->orient = Save_position.orient; + obj_relink(ConsoleObject-Objects,Save_position.segnum); + } + + gamestate_not_restored = 0; + Update_flags |= UF_WORLD_CHANGED; + } + else + gamestate_not_restored = 1; + } +} + +int RestoreGameState() { + load_level("GAMESAVE.LVL"); + gamestate_not_restored = 0; + + mprintf((0, "Gamestate restored.\n")); + editor_status("Gamestate restored.\n"); + + Update_flags |= UF_WORLD_CHANGED; + return 0; +} + +extern void check_wall_validity(void); + +// --------------------------------------------------------------------------------------------------- +//this function is the editor. called when editor mode selected. runs until +//game mode or exit selected +void editor(void) +{ + int w,h; + grs_bitmap * savedbitmap; + editor_view *new_cv; + static int padnum=0; + vms_matrix MouseRotMat,tempm; + //@@short camera_objnum; //a camera for viewing + + init_editor(); + + InitCurve(); + + restore_effect_bitmap_icons(); + + if (!set_screen_mode(SCREEN_EDITOR)) { + set_screen_mode(SCREEN_GAME); + Function_mode=FMODE_GAME; //force back into game + return; + } + + gr_set_current_canvas( NULL ); + gr_set_curfont(editor_font); + + //Editor renders into full (320x200) game screen + + set_warn_func(med_show_warning); + + keyd_repeat = 1; // Allow repeat in editor + +// _MARK_("start of editor");//Nuked to compile -KRB + + ui_mouse_hide(); + + ui_reset_idle_seconds(); + +//@@ //create a camera for viewing in the editor. copy position from ConsoleObject +//@@ camera_objnum = obj_create(OBJ_CAMERA,0,ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0); +//@@ Viewer = &Objects[camera_objnum]; +//@@ slew_init(Viewer); //camera is slewing + + Viewer = ConsoleObject; + slew_init(ConsoleObject); + + Update_flags = UF_ALL; + + medlisp_update_screen(); + + //set the wire-frame window to be the current view + current_view = &LargeView; + + if (faded_in==0) + { + faded_in = 1; + //gr_pal_fade_in( grd_curscreen->pal ); + } + + w = GameViewBox->canvas->cv_bitmap.bm_w; + h = GameViewBox->canvas->cv_bitmap.bm_h; + + savedbitmap = gr_create_bitmap(w, h ); + + gr_bm_ubitblt( w, h, 0, 0, 0, 0, &GameViewBox->canvas->cv_bitmap, savedbitmap ); + + gr_set_current_canvas( GameViewBox->canvas ); + gr_set_curfont(editor_font); + //gr_setcolor( CBLACK ); + //gr_deaccent_canvas(); + //gr_grey_canvas(); + + ui_mouse_show(); + + gr_set_curfont(editor_font); + ui_pad_goto(padnum); + + gamestate_restore_check(); + + while (Function_mode == FMODE_EDITOR) { + + gr_set_curfont(editor_font); + info_display_all(EditorWindow); + + ModeFlag = 0; + + // Update the windows + + // Only update if there is no key waiting and we're not in + // fast play mode. + if (!key_peekkey()) //-- && (MacroStatus != UI_STATUS_FASTPLAY)) + medlisp_update_screen(); + + //do editor stuff + gr_set_curfont(editor_font); + ui_mega_process(); + last_keypress &= ~KEY_DEBUGGED; // mask off delete key bit which has no function in editor. + ui_window_do_gadgets(EditorWindow); + do_robot_window(); + do_object_window(); + do_wall_window(); + do_trigger_window(); + do_hostage_window(); + do_centers_window(); + check_wall_validity(); + Assert(Num_walls>=0); + + if (Gameview_lockstep) { + static segment *old_cursegp=NULL; + static int old_curside=-1; + + if (old_cursegp!=Cursegp || old_curside!=Curside) { + SetPlayerFromCursegMinusOne(); + old_cursegp = Cursegp; + old_curside = Curside; + } + } + +// mprintf((0, "%d ", ui_get_idle_seconds() )); + + if ( ui_get_idle_seconds() > COMPRESS_INTERVAL ) + { + med_compress_mine(); + ui_reset_idle_seconds(); + } + +// Commented out because it occupies about 25% of time in twirling the mine. +// Removes some Asserts.... +// med_check_all_vertices(); + clear_editor_status(); // if enough time elapsed, clear editor status message + TimedAutosave(mine_filename); + set_editor_time_of_day(); + gr_set_current_canvas( GameViewBox->canvas ); + + // Remove keys used for slew + switch(last_keypress) + { + case KEY_PAD9: + case KEY_PAD7: + case KEY_PADPLUS: + case KEY_PADMINUS: + case KEY_PAD8: + case KEY_PAD2: + case KEY_LBRACKET: + case KEY_RBRACKET: + case KEY_PAD1: + case KEY_PAD3: + case KEY_PAD6: + case KEY_PAD4: + last_keypress = 0; + } + if ((last_keypress&0xff)==KEY_LSHIFT) last_keypress=0; + if ((last_keypress&0xff)==KEY_RSHIFT) last_keypress=0; + if ((last_keypress&0xff)==KEY_LCTRL) last_keypress=0; + if ((last_keypress&0xff)==KEY_RCTRL) last_keypress=0; +// if ((last_keypress&0xff)==KEY_LALT) last_keypress=0; +// if ((last_keypress&0xff)==KEY_RALT) last_keypress=0; + + gr_set_curfont(editor_font); + menubar_do( last_keypress ); + + //=================== DO FUNCTIONS ==================== + + if ( KeyFunction[ last_keypress ] != NULL ) { + KeyFunction[last_keypress](); + last_keypress = 0; + } + switch (last_keypress) + { + case 0: + case KEY_Z: + case KEY_G: + case KEY_LALT: + case KEY_RALT: + case KEY_LCTRL: + case KEY_RCTRL: + case KEY_LSHIFT: + case KEY_RSHIFT: + case KEY_LAPOSTRO: + break; + case KEY_SHIFTED + KEY_L: + ToggleLighting(); + break; + case KEY_F1: + render_3d_in_big_window = !render_3d_in_big_window; + Update_flags |= UF_ALL; + break; + default: + { + char kdesc[100]; + GetKeyDescription( kdesc, last_keypress ); + editor_status("Error: %s isn't bound to anything.", kdesc ); + } + } + + //================================================================ + + if (ModeFlag==1) + { + close_editor_screen(); + Function_mode=FMODE_EXIT; + gr_free_bitmap( savedbitmap ); + break; + } + + if (ModeFlag==2) //-- && MacroStatus==UI_STATUS_NORMAL ) + { + ui_mouse_hide(); + Function_mode = FMODE_GAME; + gr_bm_ubitblt( w, h, 0, 0, 0, 0, savedbitmap, &GameViewBox->canvas->cv_bitmap); + gr_free_bitmap( savedbitmap ); + break; + } + + if (ModeFlag==3) //-- && MacroStatus==UI_STATUS_NORMAL ) + { +// med_compress_mine(); //will be called anyways before game. + close_editor_screen(); + Function_mode=FMODE_GAME; //force back into game + set_screen_mode(SCREEN_GAME); //put up game screen + gr_free_bitmap( savedbitmap ); + break; + } + +// if (CurWindow->keyboard_focus_gadget == (UI_GADGET *)GameViewBox) current_view=NULL; +// if (CurWindow->keyboard_focus_gadget == (UI_GADGET *)GroupViewBox) current_view=NULL; + + new_cv = current_view ; + +#if ORTHO_VIEWS + if (CurWindow->keyboard_focus_gadget == (UI_GADGET *)LargeViewBox) new_cv=&LargeView; + if (CurWindow->keyboard_focus_gadget == (UI_GADGET *)TopViewBox) new_cv=&TopView; + if (CurWindow->keyboard_focus_gadget == (UI_GADGET *)FrontViewBox) new_cv=&FrontView; + if (CurWindow->keyboard_focus_gadget == (UI_GADGET *)RightViewBox) new_cv=&RightView; +#endif + if (new_cv != current_view ) { + current_view->ev_changed = 1; + new_cv->ev_changed = 1; + current_view = new_cv; + } + + calc_frame_time(); + if (slew_frame(0)) { //do movement and check keys + Update_flags |= UF_GAME_VIEW_CHANGED; + if (Gameview_lockstep) { + Cursegp = &Segments[ConsoleObject->segnum]; + med_create_new_segment_from_cursegp(); + Update_flags |= UF_ED_STATE_CHANGED; + } + } + + // DO TEXTURE STUFF + texpage_do(); + objpage_do(); + + + // Process selection of Cursegp using mouse. + if (LargeViewBox->mouse_onme && LargeViewBox->b1_clicked && !render_3d_in_big_window) + { + int xcrd,ycrd; + xcrd = LargeViewBox->b1_drag_x1; + ycrd = LargeViewBox->b1_drag_y1; + + find_segments(xcrd,ycrd,LargeViewBox->canvas,&LargeView,Cursegp,Big_depth); // Sets globals N_found_segs, Found_segs + + // If shift is down, then add segment to found list + if (keyd_pressed[ KEY_LSHIFT ] || keyd_pressed[ KEY_RSHIFT ]) + subtract_found_segments_from_selected_list(); + else + add_found_segments_to_selected_list(); + + Found_seg_index = 0; + + if (N_found_segs > 0) { + sort_seg_list(N_found_segs,Found_segs,&ConsoleObject->pos); + Cursegp = &Segments[Found_segs[0]]; + med_create_new_segment_from_cursegp(); + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + } + + Update_flags |= UF_ED_STATE_CHANGED | UF_VIEWPOINT_MOVED; + } + + if (GameViewBox->mouse_onme && GameViewBox->b1_dragging) { + int x, y; + x = GameViewBox->b1_drag_x2; + y = GameViewBox->b1_drag_y2; + + ui_mouse_hide(); + gr_set_current_canvas( GameViewBox->canvas ); + gr_setcolor( 15 ); + gr_rect( x-1, y-1, x+1, y+1 ); + ui_mouse_show(); + + } + + // Set current segment and side by clicking on a polygon in game window. + // If ctrl pressed, also assign current texture map to that side. + //if (GameViewBox->mouse_onme && (GameViewBox->b1_done_dragging || GameViewBox->b1_clicked)) { + if ((GameViewBox->mouse_onme && GameViewBox->b1_clicked && !render_3d_in_big_window) || + (LargeViewBox->mouse_onme && LargeViewBox->b1_clicked && render_3d_in_big_window)) { + + int xcrd,ycrd; + int seg,side,face,poly,tmap; + + if (render_3d_in_big_window) { + xcrd = LargeViewBox->b1_drag_x1; + ycrd = LargeViewBox->b1_drag_y1; + } + else { + xcrd = GameViewBox->b1_drag_x1; + ycrd = GameViewBox->b1_drag_y1; + } + + //Int3(); + + if (find_seg_side_face(xcrd,ycrd,&seg,&side,&face,&poly)) { + + + if (seg<0) { //found an object + + Cur_object_index = -seg-1; + editor_status("Object %d selected.",Cur_object_index); + + Update_flags |= UF_ED_STATE_CHANGED; + } + else { + + // See if either shift key is down and, if so, assign texture map + if (keyd_pressed[KEY_LSHIFT] || keyd_pressed[KEY_RSHIFT]) { + Cursegp = &Segments[seg]; + Curside = side; + AssignTexture(); + med_create_new_segment_from_cursegp(); + editor_status("Texture assigned"); + } else if (keyd_pressed[KEY_G]) { + tmap = Segments[seg].sides[side].tmap_num; + texpage_grab_current(tmap); + editor_status( "Texture grabbed." ); + } else if (keyd_pressed[ KEY_LAPOSTRO] ) { + ui_mouse_hide(); + move_object_to_mouse_click(); + } else { + Cursegp = &Segments[seg]; + Curside = side; + med_create_new_segment_from_cursegp(); + editor_status("Curseg and curside selected"); + } + } + + Update_flags |= UF_ED_STATE_CHANGED; + } + else + editor_status("Click on non-texture ingored"); + + } + + // Allow specification of LargeView using mouse + if (keyd_pressed[ KEY_LCTRL ] || keyd_pressed[ KEY_RCTRL ]) { + ui_mouse_hide(); + if ( (Mouse.dx!=0) && (Mouse.dy!=0) ) { + GetMouseRotation( Mouse.dx, Mouse.dy, &MouseRotMat ); + vm_matrix_x_matrix(&tempm,&LargeView.ev_matrix,&MouseRotMat); + LargeView.ev_matrix = tempm; + LargeView.ev_changed = 1; + Large_view_index = -1; // say not one of the orthogonal views + } + } else { + ui_mouse_show(); + } + + if ( keyd_pressed[ KEY_Z ] ) { + ui_mouse_hide(); + if ( Mouse.dy!=0 ) { + current_view->ev_dist += Mouse.dy*10000; + current_view->ev_changed = 1; + } + } else { + ui_mouse_show(); + } + + } + +// _MARK_("end of editor");//Nuked to compile -KRB + + clear_warn_func(med_show_warning); + + //kill our camera object + + Viewer = ConsoleObject; //reset viewer + //@@obj_delete(camera_objnum); + + padnum = ui_pad_get_current(); + + close_editor(); + ui_close(); + + +} + +void test_fade(void) +{ + int i,c; + + for (c=0; c<256; c++) { + printf("%4i: {%3i %3i %3i} ",c,gr_palette[3*c],gr_palette[3*c+1],gr_palette[3*c+2]); + for (i=0; i<16; i++) { + int col = gr_fade_table[256*i+c]; + + printf("[%3i %3i %3i] ",gr_palette[3*col],gr_palette[3*col+1],gr_palette[3*col+2]); + } + if ( (c%16) == 15) + printf("\n"); + printf("\n"); + } +} + +void dump_stuff(void) +{ + int i,j,prev_color; + + printf("Palette:\n"); + + for (i=0; i<256; i++) + printf("%3i: %2i %2i %2i\n",i,gr_palette[3*i],gr_palette[3*i+1],gr_palette[3*i+2]); + + for (i=0; i<16; i++) { + printf("\nFade table #%i\n",i); + for (j=0; j<256; j++) { + int c = gr_fade_table[i*256 + j]; + printf("[%3i %2i %2i %2i] ",c, gr_palette[3*c], gr_palette[3*c+1], gr_palette[3*c+2]); + if ((j % 8) == 7) + printf("\n"); + } + } + + printf("Colors indexed by intensity:\n"); + printf(". = change from previous, * = no change\n"); + for (j=0; j<256; j++) { + printf("%3i: ",j); + prev_color = -1; + for (i=0; i<16; i++) { + int c = gr_fade_table[i*256 + j]; + if (c == prev_color) + printf("*"); + else + printf("."); + prev_color = c; + } + printf(" "); + for (i=0; i<16; i++) { + int c = gr_fade_table[i*256 + j]; + printf("[%3i %2i %2i %2i] ", c, gr_palette[3*c], gr_palette[3*c+1], gr_palette[3*c+2]); + } + printf("\n"); + } + +} + + +int MarkStart(void) +{ + char mystr[30]; + sprintf(mystr,"mark %i start",Mark_count); +// _MARK_(mystr);//Nuked to compile -KRB + + return 1; +} + +int MarkEnd(void) +{ + char mystr[30]; + sprintf(mystr,"mark %i end",Mark_count); + Mark_count++; +// _MARK_(mystr);//Nuked to compile -KRB + + return 1; +} + diff --git a/main/editor/medwall.h b/main/editor/medwall.h new file mode 100644 index 00000000..4364192e --- /dev/null +++ b/main/editor/medwall.h @@ -0,0 +1,109 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/main/editor/medwall.h,v $ + * $Revision: 1.1 $ + * $Author: bradleyb $ + * $Date: 2001-10-25 02:27:17 $ + * + * Created from version 1.6 of main\wall.h + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:40 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:10 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.9 1994/09/28 17:31:51 mike + * Prototype copy_group_walls(). + * + * Revision 1.8 1994/08/05 21:18:16 matt + * Allow two doors to be linked together + * + * Revision 1.7 1994/06/20 22:30:10 yuan + * Fixed crazy runaway trigger bug that Adam found + * + * Revision 1.6 1994/05/30 20:22:58 yuan + * New triggers. + * + * Revision 1.5 1994/05/25 18:08:37 yuan + * Revamping walls and triggers interface. + * Wall interface complete, but triggers are still in progress. + * + * Revision 1.4 1994/05/18 18:22:04 yuan + * Fixed delete segment and walls bug. + * + * Revision 1.3 1994/03/17 18:08:41 yuan + * New wall stuff... Cut out switches.... + * + * Revision 1.2 1994/03/15 16:34:10 yuan + * Fixed bm loader (might have some changes in walls and switches) + * + * Revision 1.1 1994/02/10 17:52:01 matt + * Initial revision + * + * + * + */ + +#ifndef _MEDWALL_H +#define _MEDWALL_H + +#include "wall.h" +#include "inferno.h" +#include "segment.h" + +extern int wall_add_removable(); + +// Restores all the walls to original status +extern int wall_restore_all(); + +// Reset a wall. +extern void wall_reset(segment *seg, short side); + +// Adds a removable wall (medwall.c) +extern int wall_add_removable(); + +// Adds a door (medwall.c) +extern int wall_add_door(); + +// Adds an illusory wall (medwall.c) +extern int wall_add_illusion(); + +// Removes a removable wall (medwall.c) +extern int wall_remove_blastable(); + +// Adds a wall. (visually) +extern int wall_add_to_curside(); +extern int wall_add_to_markedside(byte type); + +// Removes a wall. (visually) +extern int wall_remove(); + +// Removes a specific side. +int wall_remove_side(segment *seg, short side); + +extern int bind_wall_to_control_center(); + +extern void close_wall_window(); + +extern void do_wall_window(); + +extern int wall_link_doors(); +extern int wall_unlink_door(); +extern void copy_group_walls(int old_group, int new_group); + +#endif + diff --git a/main/editor/segment.c b/main/editor/segment.c new file mode 100644 index 00000000..d8b47954 --- /dev/null +++ b/main/editor/segment.c @@ -0,0 +1,2271 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ + +/* + * $Source: /cvs/cvsroot/d2x/main/editor/segment.c,v $ + * $Revision: 1.1 $ + * $Author: bradleyb $ + * $Date: 2001-10-25 02:27:17 $ + * + * Interrogation functions for segment data structure. + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 1999/09/02 13:37:06 sekmu + * remove warning in editor compile + * + * Revision 1.1.1.1 1999/06/14 22:04:21 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:21 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.191 1995/02/22 15:28:30 allender + * remove anonymous unions from object structure + * + * Revision 1.190 1995/02/02 02:59:40 yuan + * Working on exterminating bogus matcen_nums... (harmless though) + * + * Revision 1.189 1995/02/01 16:29:51 yuan + * Stabilizing triggers and matcens. + * + * Revision 1.188 1995/02/01 11:31:47 yuan + * Trigger bug fixed. + * + * Revision 1.187 1994/11/27 23:17:24 matt + * Made changes for new mprintf calling convention + * + * Revision 1.186 1994/11/17 14:48:12 mike + * validation functions moved from editor to game. + * + * Revision 1.185 1994/10/30 14:13:17 mike + * rip out local segment stuff. + * + * Revision 1.184 1994/10/27 10:04:24 matt + * When triangulating, don't use WID() to see if connected, look at children + * + * Revision 1.183 1994/10/26 13:40:23 mike + * debug code for matt. + * + * Revision 1.182 1994/10/24 16:34:00 mike + * Force render after mine compress to prevent bugs in segment selection via clicking in 3d window. + * + * Revision 1.181 1994/10/20 18:16:15 mike + * Initialize ControlCenterTriggers.num_links in create_new_mine. + * + * Revision 1.180 1994/10/18 16:29:14 mike + * Write function to automatically fix bogus segnums in segment array. + * + * Revision 1.179 1994/10/08 17:10:41 matt + * Correctly set current_level_num when loading/creating mine in editor + * + * Revision 1.178 1994/09/25 14:17:51 mike + * Initialize (to 0) Num_robot_centers and Num_open_doors at mine creation. + * + * Revision 1.177 1994/09/20 14:36:06 mike + * Write function to find overlapping segments. + * + * Revision 1.176 1994/08/25 21:55:57 mike + * IS_CHILD stuff. + * + * Revision 1.175 1994/08/23 15:28:03 mike + * Fix peculiarity in med_combine_duplicate_vertices. + * + * Revision 1.174 1994/08/09 16:06:17 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.173 1994/08/05 21:18:10 matt + * Allow two doors to be linked together + * + * Revision 1.172 1994/08/04 19:13:16 matt + * Changed a bunch of vecmat calls to use multiple-function routines, and to + * allow the use of C macros for some functions + * + * Revision 1.171 1994/07/22 12:37:00 matt + * Cleaned up editor/game interactions some more. + * + * Revision 1.170 1994/07/22 11:20:08 mike + * Set Lsegments validity. + * + * Revision 1.169 1994/07/21 19:02:49 mike + * lsegment stuff. + * + * Revision 1.168 1994/07/21 13:27:17 matt + * Ripped out remants of old demo system, and added demo + * disables object movement and game options from menu. + * + * Revision 1.167 1994/07/19 20:15:48 matt + * Name for each level now saved in the .SAV file & stored in Current_level_name + * + * Revision 1.166 1994/07/06 12:42:45 john + * Made generic messages for hostages. + * + * Revision 1.165 1994/06/24 17:04:29 john + * *** empty log message *** + * + * Revision 1.164 1994/06/15 15:42:40 mike + * Initialize static_light field in new segments. + * + * Revision 1.163 1994/06/13 17:49:19 mike + * Fix bug in med_validate_side which was toasting lighting for removable walls. + * + * Revision 1.162 1994/06/13 10:52:20 mike + * Fix bug in triangulation of sides between connected segments. + * Was assigning SIDE_IS_02 regardless of how triangulated, was + * causing physics bugs. + * + * Revision 1.161 1994/06/08 18:14:16 mike + * Fix triangulation of sides in hallways (ie, where there is no wall), + * so they get triangulated the same way, so find_new_seg doesn't get + * stuck in an infinite recursion. + * + * Revision 1.160 1994/06/08 11:44:31 mike + * Fix bug in normals not being opposite on opposite sides of a segment. + * Problem occurred due to difference in handling of remainder in signed divide. + * + * Revision 1.159 1994/05/31 19:00:15 yuan + * Fixed gamestate restore. + * + * Revision 1.158 1994/05/30 20:22:36 yuan + * New triggers. + * + * Revision 1.157 1994/05/26 19:32:51 mike + * Add bfs_parse. + * + * Revision 1.156 1994/05/23 14:56:46 mike + * make current segment be add segment., + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "mono.h" +#include "key.h" +#include "gr.h" + +#include "inferno.h" +#include "segment.h" +// #include "segment2.h" +#include "editor.h" +#include "error.h" +#include "object.h" + +#include "gameseg.h" +#include "render.h" +#include "game.h" + +#include "wall.h" +#include "switch.h" +#include "fuelcen.h" +#include "cntrlcen.h" +#include "seguvs.h" +#include "gameseq.h" + +#include "medwall.h" +#include "hostage.h" + +int Do_duplicate_vertex_check = 0; // Gets set to 1 in med_create_duplicate_vertex, means to check for duplicate vertices in compress_mine + +#define BOTTOM_STUFF 0 + +// Remap all vertices in polygons in a segment through translation table xlate_verts. +#if BOTTOM_STUFF +void remap_vertices(segment *segp, int *xlate_verts) +{ + int sidenum, facenum, polynum, v; + + for (sidenum=0; sidenumsides[sidenum].num_faces; facenum++) + for (polynum=0; polynumsides[sidenum].faces[facenum].num_polys; polynum++) { + poly *pp = &segp->sides[sidenum].faces[facenum].polys[polynum]; + for (v=0; vnum_vertices; v++) + pp->verts[v] = xlate_verts[pp->verts[v]]; + } +} + +// Copy everything from sourceside to destside except sourceside->faces[xx].polys[xx].verts +void copy_side_except_vertex_ids(side *destside, side *sourceside) +{ + int facenum, polynum, v; + + destside->num_faces = sourceside->num_faces; + destside->tri_edge = sourceside->tri_edge; + destside->wall_num = sourceside->wall_num; + + for (facenum=0; facenumnum_faces; facenum++) { + face *destface = &destside->faces[facenum]; + face *sourceface = &sourceside->faces[facenum]; + + destface->num_polys = sourceface->num_polys; + destface->normal = sourceface->normal; + + for (polynum=0; polynumnum_polys; polynum++) { + poly *destpoly = &destface->polys[polynum]; + poly *sourcepoly = &sourceface->polys[polynum]; + + destpoly->num_vertices = sourcepoly->num_vertices; + destpoly->face_type = sourcepoly->face_type; + destpoly->tmap_num = sourcepoly->tmap_num; + destpoly->tmap_num2 = sourcepoly->tmap_num2; + + for (v=0; vnum_vertices; v++) + destpoly->uvls[v] = sourcepoly->uvls[v]; + } + + } +} + +// [side] [index] [cur:next] +// To remap the vertices on a side after a forward rotation +byte xlate_previous[6][4][2] = { +{ {7, 3}, {3, 2}, {2, 6}, {6, 7} }, // remapping left to left +{ {5, 4}, {4, 0}, {7, 3}, {6, 7} }, // remapping back to top +{ {5, 4}, {1, 5}, {0, 1}, {4, 0} }, // remapping right to right +{ {0, 1}, {1, 5}, {2, 6}, {3, 2} }, // remapping front to bottom +{ {1, 5}, {5, 4}, {6, 7}, {2, 6} }, // remapping bottom to back +{ {4, 0}, {0, 1}, {3, 2}, {7, 3} }, // remapping top to front +}; + +void remap_vertices_previous(segment *segp, int sidenum) +{ + int v, w, facenum, polynum; + + for (facenum=0; facenumsides[sidenum].num_faces; facenum++) { + for (polynum=0; polynumsides[sidenum].faces[facenum].num_polys; polynum++) { + poly *pp = &segp->sides[sidenum].faces[facenum].polys[polynum]; + + for (v=0; vnum_vertices; v++) { + for (w=0; w<4; w++) { + if (pp->verts[v] == xlate_previous[sidenum][w][0]) { + pp->verts[v] = xlate_previous[sidenum][w][1]; + break; + } + } + Assert(w<4); // If w == 4, then didn't find current vertex in list, which means xlate_previous table is bogus + } + } + } +} + +byte xlate_previous_right[6][4][2] = { +{ {5, 6}, {6, 7}, {2, 3}, {1, 2} }, // bottom to left +{ {6, 7}, {7, 4}, {3, 0}, {2, 3} }, // left to top +{ {7, 4}, {4, 5}, {0, 1}, {3, 0} }, // top to right +{ {4, 5}, {5, 6}, {1, 2}, {0, 1} }, // right to bottom +{ {6, 7}, {5, 6}, {4, 5}, {7, 4} }, // back to back +{ {3, 2}, {0, 3}, {1, 0}, {2, 1} }, // front to front +}; + +void remap_vertices_previous_right(segment *segp, int sidenum) +{ + int v, w, facenum, polynum; + + for (facenum=0; facenumsides[sidenum].num_faces; facenum++) { + for (polynum=0; polynumsides[sidenum].faces[facenum].num_polys; polynum++) { + poly *pp = &segp->sides[sidenum].faces[facenum].polys[polynum]; + + for (v=0; vnum_vertices; v++) { + for (w=0; w<4; w++) { + if (pp->verts[v] == xlate_previous_right[sidenum][w][0]) { + pp->verts[v] = xlate_previous_right[sidenum][w][1]; + break; + } + } + Assert(w<4); // If w == 4, then didn't find current vertex in list, which means xlate_previous table is bogus + } + } + } +} + + +// ----------------------------------------------------------------------------------- +// Takes top to front +void med_rotate_segment_forward(segment *segp) +{ + segment seg_copy; + int i; + + seg_copy = *segp; + + seg_copy.verts[0] = segp->verts[4]; + seg_copy.verts[1] = segp->verts[0]; + seg_copy.verts[2] = segp->verts[3]; + seg_copy.verts[3] = segp->verts[7]; + seg_copy.verts[4] = segp->verts[5]; + seg_copy.verts[5] = segp->verts[1]; + seg_copy.verts[6] = segp->verts[2]; + seg_copy.verts[7] = segp->verts[6]; + + seg_copy.children[WFRONT] = segp->children[WTOP]; + seg_copy.children[WTOP] = segp->children[WBACK]; + seg_copy.children[WBACK] = segp->children[WBOTTOM]; + seg_copy.children[WBOTTOM] = segp->children[WFRONT]; + + seg_copy.sides[WFRONT] = segp->sides[WTOP]; + seg_copy.sides[WTOP] = segp->sides[WBACK]; + seg_copy.sides[WBACK] = segp->sides[WBOTTOM]; + seg_copy.sides[WBOTTOM] = segp->sides[WFRONT]; + + for (i=0; i<6; i++) + remap_vertices_previous(&seg_copy, i); + + *segp = seg_copy; +} + +// ----------------------------------------------------------------------------------- +// Takes top to right +void med_rotate_segment_right(segment *segp) +{ + segment seg_copy; + int i; + + seg_copy = *segp; + + seg_copy.verts[4] = segp->verts[7]; + seg_copy.verts[5] = segp->verts[4]; + seg_copy.verts[1] = segp->verts[0]; + seg_copy.verts[0] = segp->verts[3]; + seg_copy.verts[3] = segp->verts[2]; + seg_copy.verts[2] = segp->verts[1]; + seg_copy.verts[6] = segp->verts[5]; + seg_copy.verts[7] = segp->verts[6]; + + seg_copy.children[WRIGHT] = segp->children[WTOP]; + seg_copy.children[WBOTTOM] = segp->children[WRIGHT]; + seg_copy.children[WLEFT] = segp->children[WBOTTOM]; + seg_copy.children[WTOP] = segp->children[WLEFT]; + + seg_copy.sides[WRIGHT] = segp->sides[WTOP]; + seg_copy.sides[WBOTTOM] = segp->sides[WRIGHT]; + seg_copy.sides[WLEFT] = segp->sides[WBOTTOM]; + seg_copy.sides[WTOP] = segp->sides[WLEFT]; + + for (i=0; i<6; i++) + remap_vertices_previous_right(&seg_copy, i); + + *segp = seg_copy; +} + +void make_curside_bottom_side(void) +{ + switch (Curside) { + case WRIGHT: med_rotate_segment_right(Cursegp); break; + case WTOP: med_rotate_segment_right(Cursegp); med_rotate_segment_right(Cursegp); break; + case WLEFT: med_rotate_segment_right(Cursegp); med_rotate_segment_right(Cursegp); med_rotate_segment_right(Cursegp); break; + case WBOTTOM: break; + case WFRONT: med_rotate_segment_forward(Cursegp); break; + case WBACK: med_rotate_segment_forward(Cursegp); med_rotate_segment_forward(Cursegp); med_rotate_segment_forward(Cursegp); break; + } + Update_flags = UF_WORLD_CHANGED; +} +#endif + +int ToggleBottom(void) +{ + Render_only_bottom = !Render_only_bottom; + Update_flags = UF_WORLD_CHANGED; + return 0; +} + +// --------------------------------------------------------------------------------------------- +// ---------- Segment interrogation functions ---------- +// ---------------------------------------------------------------------------- +// Return a pointer to the list of vertex indices for the current segment in vp and +// the number of vertices in *nv. +void med_get_vertex_list(segment *s,int *nv,short **vp) +{ + *vp = s->verts; + *nv = MAX_VERTICES_PER_SEGMENT; +} + +// ------------------------------------------------------------------------------- +// Return number of times vertex vi appears in all segments. +// This function can be used to determine whether a vertex is used exactly once in +// all segments, in which case it can be freely moved because it is not connected +// to any other segment. +int med_vertex_count(int vi) +{ + int s,v; + segment *sp; + int count; + + count = 0; + + for (s=0; ssegnum != -1) + for (v=0; vverts[v] == vi) + count++; + } + + return count; +} + +// ------------------------------------------------------------------------------- +int is_free_vertex(int vi) +{ + return med_vertex_count(vi) == 1; +} + + +// ------------------------------------------------------------------------------- +// Move a free vertex in the segment by adding the vector *vofs to its coordinates. +// Error handling: +// If the point is not free then: +// If the point is not valid (probably valid = in 0..7) then: +// If adding *vofs will cause a degenerate segment then: +// Note, pi is the point index relative to the segment, not an absolute point index. +// For example, 3 is always the front upper left vertex. +void med_move_vertex(segment *sp, int pi, vms_vector *vofs) +{ + int abspi; + + Assert((pi >= 0) && (pi <= 7)); // check valid range of point indices. + + abspi = sp->verts[pi]; + + // Make sure vertex abspi is free. If it is free, it appears exactly once in Vertices + Assert(med_vertex_count(abspi) == 1); + + Assert(abspi <= MAX_SEGMENT_VERTICES); // Make sure vertex id is not bogus. + + vm_vec_add(&Vertices[abspi],&Vertices[abspi],vofs); + + // Here you need to validate the geometry of the segment, which will be quite tricky. + // You need to make sure: + // The segment is not concave. + // None of the sides are concave. + validate_segment(sp); + +} + +// ------------------------------------------------------------------------------- +// Move a free wall in the segment by adding the vector *vofs to its coordinates. +// Wall indices: 0/1/2/3/4/5 = left/top/right/bottom/back/front +void med_move_wall(segment *sp,int wi, vms_vector *vofs) +{ + char *vp; + int i; + + Assert( (wi >= 0) && (wi <= 5) ); + + vp = Side_to_verts[wi]; + for (i=0; i<4; i++) { + med_move_vertex(sp,*vp,vofs); + vp++; + } + + validate_segment(sp); +} + +// ------------------------------------------------------------------------------- +// Return true if one fixed point number is very close to another, else return false. +int fnear(fix f1, fix f2) +{ + return (abs(f1 - f2) <= FIX_EPSILON); +} + +// ------------------------------------------------------------------------------- +int vnear(vms_vector *vp1, vms_vector *vp2) +{ + return fnear(vp1->x, vp2->x) && fnear(vp1->y, vp2->y) && fnear(vp1->z, vp2->z); +} + +// ------------------------------------------------------------------------------- +// Add the vertex *vp to the global list of vertices, return its index. +// Search until a matching vertex is found (has nearly the same coordinates) or until Num_vertices +// vertices have been looked at without a match. If no match, add a new vertex. +int med_add_vertex(vms_vector *vp) +{ + int v,free_index; + int count; // number of used vertices found, for loops exits when count == Num_vertices + +// set_vertex_counts(); + + Assert(Num_vertices < MAX_SEGMENT_VERTICES); + + count = 0; + free_index = -1; + for (v=0; (v < MAX_SEGMENT_VERTICES) && (count < Num_vertices); v++) + if (Vertex_active[v]) { + count++; + if (vnear(vp,&Vertices[v])) { + // mprintf((0,"[%4i] ",v)); + return v; + } + } else if (free_index == -1) + free_index = v; // we want free_index to be the first free slot to add a vertex + + if (free_index == -1) + free_index = Num_vertices; + + while (Vertex_active[free_index] && (free_index < MAX_VERTICES)) + free_index++; + + Assert(free_index < MAX_VERTICES); + + Vertices[free_index] = *vp; + Vertex_active[free_index] = 1; + + Num_vertices++; + + if (free_index > Highest_vertex_index) + Highest_vertex_index = free_index; + + return free_index; +} + +// ------------------------------------------------------------------------------------------ +// Returns the index of a free segment. +// Scans the Segments array. +int get_free_segment_number(void) +{ + int segnum; + + for (segnum=0; segnum Highest_segment_index) + Highest_segment_index = segnum; + return segnum; + } + + Assert(0); + + return 0; +} + +// ------------------------------------------------------------------------------- +// Create a new segment, duplicating exactly, including vertex ids and children, the passed segment. +int med_create_duplicate_segment(segment *sp) +{ + int segnum; + + segnum = get_free_segment_number(); + + Segments[segnum] = *sp; + + return segnum; +} + +// ------------------------------------------------------------------------------- +// Add the vertex *vp to the global list of vertices, return its index. +// This is the same as med_add_vertex, except that it does not search for the presence of the vertex. +int med_create_duplicate_vertex(vms_vector *vp) +{ + int free_index; + + Assert(Num_vertices < MAX_SEGMENT_VERTICES); + + Do_duplicate_vertex_check = 1; + + free_index = Num_vertices; + + while (Vertex_active[free_index] && (free_index < MAX_VERTICES)) + free_index++; + + Assert(free_index < MAX_VERTICES); + + Vertices[free_index] = *vp; + Vertex_active[free_index] = 1; + + Num_vertices++; + + if (free_index > Highest_vertex_index) + Highest_vertex_index = free_index; + + return free_index; +} + + +// ------------------------------------------------------------------------------- +// Set the vertex *vp at index vnum in the global list of vertices, return its index (just for compatibility). +int med_set_vertex(int vnum,vms_vector *vp) +{ + Assert(vnum < MAX_VERTICES); + + Vertices[vnum] = *vp; + + // Just in case this vertex wasn't active, mark it as active. + if (!Vertex_active[vnum]) { + Vertex_active[vnum] = 1; + Num_vertices++; + if ((vnum > Highest_vertex_index) && (vnum < NEW_SEGMENT_VERTICES)) { + mprintf((0,"Warning -- setting a previously unset vertex, index = %i.\n",vnum)); + Highest_vertex_index = vnum; + } + } + + return vnum; +} + + + +// ---- +// A side is determined to be degenerate if the cross products of 3 consecutive points does not point outward. +int check_for_degenerate_side(segment *sp, int sidenum) +{ + char *vp = Side_to_verts[sidenum]; + vms_vector vec1, vec2, cross, vec_to_center; + vms_vector segc, sidec; + fix dot; + int degeneracy_flag = 0; + + compute_segment_center(&segc, sp); + compute_center_point_on_side(&sidec, sp, sidenum); + vm_vec_sub(&vec_to_center, &segc, &sidec); + + //vm_vec_sub(&vec1, &Vertices[sp->verts[vp[1]]], &Vertices[sp->verts[vp[0]]]); + //vm_vec_sub(&vec2, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]); + //vm_vec_normalize(&vec1); + //vm_vec_normalize(&vec2); + vm_vec_normalized_dir(&vec1, &Vertices[sp->verts[(int) vp[1]]], &Vertices[sp->verts[(int) vp[0]]]); + vm_vec_normalized_dir(&vec2, &Vertices[sp->verts[(int) vp[2]]], &Vertices[sp->verts[(int) vp[1]]]); + vm_vec_cross(&cross, &vec1, &vec2); + + dot = vm_vec_dot(&vec_to_center, &cross); + if (dot <= 0) + degeneracy_flag |= 1; + + //vm_vec_sub(&vec1, &Vertices[sp->verts[vp[2]]], &Vertices[sp->verts[vp[1]]]); + //vm_vec_sub(&vec2, &Vertices[sp->verts[vp[3]]], &Vertices[sp->verts[vp[2]]]); + //vm_vec_normalize(&vec1); + //vm_vec_normalize(&vec2); + vm_vec_normalized_dir(&vec1, &Vertices[sp->verts[(int) vp[2]]], &Vertices[sp->verts[(int) vp[1]]]); + vm_vec_normalized_dir(&vec2, &Vertices[sp->verts[(int) vp[3]]], &Vertices[sp->verts[(int) vp[2]]]); + vm_vec_cross(&cross, &vec1, &vec2); + + dot = vm_vec_dot(&vec_to_center, &cross); + if (dot <= 0) + degeneracy_flag |= 1; + + return degeneracy_flag; + +} + +// ------------------------------------------------------------------------------- +void create_removable_wall(segment *sp, int sidenum, int tmap_num) +{ + create_walls_on_side(sp, sidenum); + + sp->sides[sidenum].tmap_num = tmap_num; + + assign_default_uvs_to_side(sp, sidenum); + assign_light_to_side(sp, sidenum); +} + +// ---- +// See if a segment has gotten turned inside out, or something. +// If so, set global Degenerate_segment_found and return 1, else return 0. +int check_for_degenerate_segment(segment *sp) +{ + vms_vector fvec, rvec, uvec, cross; + fix dot; + int i, degeneracy_flag = 0; // degeneracy flag for current segment + + extract_forward_vector_from_segment(sp, &fvec); + extract_right_vector_from_segment(sp, &rvec); + extract_up_vector_from_segment(sp, &uvec); + + vm_vec_normalize(&fvec); + vm_vec_normalize(&rvec); + vm_vec_normalize(&uvec); + + vm_vec_cross(&cross, &fvec, &rvec); + dot = vm_vec_dot(&cross, &uvec); + + if (dot > 0) + degeneracy_flag = 0; + else { + mprintf((0, "segment #%i is degenerate due to cross product check.\n", sp-Segments)); + degeneracy_flag = 1; + } + + // Now, see if degenerate because of any side. + for (i=0; izrow = tmat.zrow; + + // Now, compute the second vector. + // From page 172 of Strang, we use the equation: + // b' = b - [transpose(q1) * b] * q1 + // where: b = the second row of tmat + // q1 = the first row of rmat + // b' = the second row of rmat + + // Compute: transpose(q1) * b + dot = vm_vec_dotprod(&rmat->zrow,&tmat.yrow); + + // Compute: b - dot * q1 + rmat->yrow.x = tmat.yrow.x - fixmul(dot,rmat->zrow.x); + rmat->yrow.y = tmat.yrow.y - fixmul(dot,rmat->zrow.y); + rmat->yrow.z = tmat.yrow.z - fixmul(dot,rmat->zrow.z); + + // Now, compute the third vector. + // From page 173 of Strang, we use the equation: + // c' = c - (q1*c)*q1 - (q2*c)*q2 + // where: c = the third row of tmat + // q1 = the first row of rmat + // q2 = the second row of rmat + // c' = the third row of rmat + + // Compute: q1*c + dot = vm_vec_dotprod(&rmat->zrow,&tmat.xrow); + + tvec1.x = fixmul(dot,rmat->zrow.x); + tvec1.y = fixmul(dot,rmat->zrow.y); + tvec1.z = fixmul(dot,rmat->zrow.z); + + // Compute: q2*c + dot = vm_vec_dotprod(&rmat->yrow,&tmat.xrow); + + tvec2.x = fixmul(dot,rmat->yrow.x); + tvec2.y = fixmul(dot,rmat->yrow.y); + tvec2.z = fixmul(dot,rmat->yrow.z); + + vm_vec_sub(&rmat->xrow,vm_vec_sub(&rmat->xrow,&tmat.xrow,&tvec1),&tvec2); +} + +#endif + +// ------------------------------------------------------------------------------------------ +// Given a segment, extract the rotation matrix which defines it. +// Do this by extracting the forward, right, up vectors and then making them orthogonal. +// In the process of making the vectors orthogonal, favor them in the order forward, up, right. +// This means that the forward vector will remain unchanged. +void med_extract_matrix_from_segment(segment *sp,vms_matrix *rotmat) +{ + vms_vector forwardvec,upvec; + + extract_forward_vector_from_segment(sp,&forwardvec); + extract_up_vector_from_segment(sp,&upvec); + + if (((forwardvec.x == 0) && (forwardvec.y == 0) && (forwardvec.z == 0)) || ((upvec.x == 0) && (upvec.y == 0) && (upvec.z == 0))) { + mprintf((0, "Trapped null vector in med_extract_matrix_from_segment, returning identity matrix.\n")); + *rotmat = vmd_identity_matrix; + return; + } + + + vm_vector_2_matrix(rotmat,&forwardvec,&upvec,NULL); + +#if 0 + vms_matrix rm; + + extract_forward_vector_from_segment(sp,&rm.zrow); + extract_right_vector_from_segment(sp,&rm.xrow); + extract_up_vector_from_segment(sp,&rm.yrow); + + vm_vec_normalize(&rm.xrow); + vm_vec_normalize(&rm.yrow); + vm_vec_normalize(&rm.zrow); + + make_orthogonal(rotmat,&rm); + + vm_vec_normalize(&rotmat->xrow); + vm_vec_normalize(&rotmat->yrow); + vm_vec_normalize(&rotmat->zrow); + +// *rotmat = rm; // include this line (and remove the call to make_orthogonal) if you don't want the matrix orthogonalized +#endif + +} + +// ------------------------------------------------------------------------------------------ +// Given a rotation matrix *rotmat which describes the orientation of a segment +// and a side destside, return the rotation matrix which describes the orientation for the side. +void set_matrix_based_on_side(vms_matrix *rotmat,int destside) +{ + vms_angvec rotvec,*tmpvec; + vms_matrix r1,rtemp; + + switch (destside) { + case WLEFT: + tmpvec=vm_angvec_make(&rotvec,0,0,-16384); + vm_angles_2_matrix(&r1,&rotvec); + vm_matrix_x_matrix(&rtemp,rotmat,&r1); + *rotmat = rtemp; + break; + + case WTOP: + tmpvec=vm_angvec_make(&rotvec,-16384,0,0); + vm_angles_2_matrix(&r1,&rotvec); + vm_matrix_x_matrix(&rtemp,rotmat,&r1); + *rotmat = rtemp; + break; + + case WRIGHT: + tmpvec=vm_angvec_make(&rotvec,0,0,16384); + vm_angles_2_matrix(&r1,&rotvec); + vm_matrix_x_matrix(&rtemp,rotmat,&r1); + *rotmat = rtemp; + break; + + case WBOTTOM: + tmpvec=vm_angvec_make(&rotvec,+16384,-32768,0); // bank was -32768, but I think that was an erroneous compensation + vm_angles_2_matrix(&r1,&rotvec); + vm_matrix_x_matrix(&rtemp,rotmat,&r1); + *rotmat = rtemp; + break; + + case WFRONT: + tmpvec=vm_angvec_make(&rotvec,0,0,-32768); + vm_angles_2_matrix(&r1,&rotvec); + vm_matrix_x_matrix(&rtemp,rotmat,&r1); + *rotmat = rtemp; + break; + + case WBACK: + break; + } + +} + +// ------------------------------------------------------------------------------------- +void change_vertex_occurrences(int dest, int src) +{ + int g,s,v; + + // Fix vertices in groups + for (g=0;ghole) && (!Vertex_active[vert]); vert--) + ; + + if (vert > hole) { + + // Ok, hole is the index of a hole, vert is the index of a vertex which follows it. + // Copy vert into hole, update pointers to it. + Vertices[hole] = Vertices[vert]; + + change_vertex_occurrences(hole, vert); + + vert--; + } + } + + Highest_vertex_index = Num_vertices-1; +} + +// -------------------------------------------------------------------------------------------------- +void compress_segments(void) +{ + int hole,seg; + + if (Highest_segment_index == Num_segments - 1) + return; + + seg = Highest_segment_index; + + for (hole=0; hole < seg; hole++) + if (Segments[hole].segnum == -1) { + // found an unused segment which is a hole if a used segment follows (not necessarily immediately) it. + for ( ; (seg>hole) && (Segments[seg].segnum == -1); seg--) + ; + + if (seg > hole) { + int f,g,l,s,t,w; + segment *sp; + int objnum; + + // Ok, hole is the index of a hole, seg is the index of a segment which follows it. + // Copy seg into hole, update pointers to it, update Cursegp, Markedsegp if necessary. + Segments[hole] = Segments[seg]; + Segments[seg].segnum = -1; + + if (Cursegp == &Segments[seg]) + Cursegp = &Segments[hole]; + + if (Markedsegp == &Segments[seg]) + Markedsegp = &Segments[hole]; + + // Fix segments in groups + for (g=0;gchildren[s])) { + segment *csegp; + csegp = &Segments[sp->children[s]]; + + // Find out on what side the segment connection to the former seg is on in *csegp. + for (t=0; tchildren[t] == seg) { + csegp->children[t] = hole; // It used to be connected to seg, so make it connected to hole + } + } // end for t + } // end if + } // end for s + + //Update object segment pointers + for (objnum = sp->objects; objnum != -1; objnum = Objects[objnum].next) { + Assert(Objects[objnum].segnum == seg); + Objects[objnum].segnum = hole; + } + + seg--; + + } // end if (seg > hole) + } // end if + + Highest_segment_index = Num_segments-1; + med_create_new_segment_from_cursegp(); + +} + + +// ------------------------------------------------------------------------------- +// Combine duplicate vertices. +// If two vertices have the same coordinates, within some small tolerance, then assign +// the same vertex number to the two vertices, freeing up one of the vertices. +void med_combine_duplicate_vertices(byte *vlp) +{ + int v,w; + + for (v=0; vsides[s].tmap_num = sseg->sides[s].tmap_num; + dseg->sides[s].tmap_num2 = 0; + } +} + +// ------------------------------------------------------------------------------------------ +// Attach a segment with a rotated orientation. +// Return value: +// 0 = successful attach +// 1 = No room in Segments[]. +// 2 = No room in Vertices[]. +// 3 = newside != WFRONT -- for now, the new segment must be attached at its (own) front side +// 4 = already a face attached on destseg:destside +int med_attach_segment_rotated(segment *destseg, segment *newseg, int destside, int newside,vms_matrix *attmat) +{ + char *dvp; + segment *nsp; + segment2 *nsp2; + int side,v; + vms_matrix rotmat,rotmat1,rotmat2,rotmat3,rotmat4; + vms_vector vr,vc,tvs[4],xlate_vec; + int segnum; + vms_vector forvec,upvec; + + // Return if already a face attached on this side. + if (IS_CHILD(destseg->children[destside])) + return 4; + + segnum = get_free_segment_number(); + + forvec = attmat->fvec; + upvec = attmat->uvec; + + // We are pretty confident we can add the segment. + nsp = &Segments[segnum]; + nsp2 = &Segment2s[segnum]; + + nsp->segnum = segnum; + nsp->objects = -1; + nsp2->matcen_num = -1; + + // Copy group value. + nsp->group = destseg->group; + + // Add segment to proper group list. + if (nsp->group > -1) + add_segment_to_group(nsp-Segments, nsp->group); + + // Copy the texture map ids. + copy_tmap_ids(nsp,newseg); + + // clear all connections + for (side=0; sidechildren[side] = -1; + nsp->sides[side].wall_num = -1; + } + + // Form the connection + destseg->children[destside] = segnum; +// destseg->sides[destside].render_flag = 0; + nsp->children[newside] = destseg-Segments; + + // Copy vertex indices of the four vertices forming the joint + dvp = Side_to_verts[destside]; + + // Set the vertex indices for the four vertices forming the front of the new side + for (v=0; v<4; v++) + nsp->verts[v] = destseg->verts[(int) dvp[v]]; + + // The other 4 vertices must be created. + // Their coordinates are determined by the 4 welded vertices and the vector from front + // to back of the original *newseg. + + // Do lots of hideous matrix stuff, about 3/4 of which could probably be simplified out. + med_extract_matrix_from_segment(destseg,&rotmat); // get orientation matrix for destseg (orthogonal rotation matrix) + set_matrix_based_on_side(&rotmat,destside); + vm_vector_2_matrix(&rotmat1,&forvec,&upvec,NULL); + vm_matrix_x_matrix(&rotmat4,&rotmat,&rotmat1); // this is the desired orientation of the new segment + med_extract_matrix_from_segment(newseg,&rotmat3); // this is the current orientation of the new segment + vm_transpose_matrix(&rotmat3); // get the inverse of the current orientation matrix + vm_matrix_x_matrix(&rotmat2,&rotmat4,&rotmat3); // now rotmat2 takes the current segment to the desired orientation + + // Warning -- look at this line! + vm_transpose_matrix(&rotmat2); // added 12:33 pm, 10/01/93 + + // Compute and rotate the center point of the attaching face. + compute_center_point_on_side(&vc,newseg,newside); + vm_vec_rotate(&vr,&vc,&rotmat2); + + // Now rotate the free vertices in the segment + for (v=0; v<4; v++) + vm_vec_rotate(&tvs[v],&Vertices[newseg->verts[v+4]],&rotmat2); + + // Now translate the new segment so that the center point of the attaching faces are the same. + compute_center_point_on_side(&vc,destseg,destside); + vm_vec_sub(&xlate_vec,&vc,&vr); + + // Create and add the 4 new vertices. + for (v=0; v<4; v++) { + vm_vec_add2(&tvs[v],&xlate_vec); + nsp->verts[v+4] = med_add_vertex(&tvs[v]); + } + + set_vertex_counts(); + + // Now all the vertices are in place. Create the faces. + validate_segment(nsp); + + // Say to not render at the joint. +// destseg->sides[destside].render_flag = 0; +// nsp->sides[newside].render_flag = 0; + + Cursegp = nsp; + + return 0; +} + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// ------------------------------------------------------------------------------------------ +void scale_free_vertices(segment *sp,vms_vector *vp,fix scale_factor,int min_side,int max_side) +{ + int i; + char *verts; + + verts = Side_to_verts[min_side]; + + for (i=0; i<4; i++) + if (is_free_vertex(sp->verts[(int) verts[i]])) { + Vertices[sp->verts[(int) verts[i]]].x = fixmul(vp->x,scale_factor)/2; + Vertices[sp->verts[(int) verts[i]]].y = fixmul(vp->y,scale_factor)/2; + Vertices[sp->verts[(int) verts[i]]].z = fixmul(vp->z,scale_factor)/2; + } + + verts = Side_to_verts[max_side]; + + for (i=0; i<4; i++) + if (is_free_vertex(sp->verts[(int) verts[i]])) { + Vertices[sp->verts[(int) verts[i]]].x = fixmul(vp->x,scale_factor)/2; + Vertices[sp->verts[(int) verts[i]]].y = fixmul(vp->y,scale_factor)/2; + Vertices[sp->verts[(int) verts[i]]].z = fixmul(vp->z,scale_factor)/2; + } +} + + +// ------------------------------------------------------------------------------------------ +// Attach side newside of newseg to side destside of destseg. +// Copies *newseg into global array Segments, increments Num_segments. +// Forms a weld between the two segments by making the new segment fit to the old segment. +// Updates number of faces per side if necessitated by new vertex coordinates. +// Updates Cursegp. +// Return value: +// 0 = successful attach +// 1 = No room in Segments[]. +// 2 = No room in Vertices[]. +// 3 = newside != WFRONT -- for now, the new segment must be attached at its (own) front side +// 4 = already a face attached on side newside +int med_attach_segment(segment *destseg, segment *newseg, int destside, int newside) +{ + int rval; + segment *ocursegp = Cursegp; + + vms_angvec tang = {0,0,0}; + vms_matrix rotmat; + + vm_angles_2_matrix(&rotmat,&tang); + rval = med_attach_segment_rotated(destseg,newseg,destside,newside,&rotmat); + med_propagate_tmaps_to_segments(ocursegp,Cursegp,0); + med_propagate_tmaps_to_back_side(Cursegp, Side_opposite[newside],0); + copy_uvs_seg_to_seg(&New_segment,Cursegp); + + return rval; +} + +// ------------------------------------------------------------------------------- +// Delete a vertex, sort of. +// Decrement the vertex count. If the count goes to 0, then the vertex is free (has been deleted). +void delete_vertex(short v) +{ + Assert(v < MAX_VERTICES); // abort if vertex is not in array Vertices + Assert(Vertex_active[v] >= 1); // abort if trying to delete a non-existent vertex + + Vertex_active[v]--; +} + +// ------------------------------------------------------------------------------- +// Update Num_vertices. +// This routine should be called by anyone who calls delete_vertex. It could be called in delete_vertex, +// but then it would be called much more often than necessary, and it is a slow routine. +void update_num_vertices(void) +{ + int v; + + // Now count the number of vertices. + Num_vertices = 0; + for (v=0; v<=Highest_vertex_index; v++) + if (Vertex_active[v]) + Num_vertices++; +} + +// ------------------------------------------------------------------------------- +// Set Vertex_active to number of occurrences of each vertex. +// Set Num_vertices. +void set_vertex_counts(void) +{ + int s,v; + + Num_vertices = 0; + + for (v=0; v<=Highest_vertex_index; v++) + Vertex_active[v] = 0; + + // Count number of occurrences of each vertex. + for (s=0; s<=Highest_segment_index; s++) + if (Segments[s].segnum != -1) + for (v=0; vverts[v]); + + update_num_vertices(); +} + +extern void validate_segment_side(segment *sp, int sidenum); + +// ------------------------------------------------------------------------------- +// Delete segment *sp in Segments array. +// Return value: +// 0 successfully deleted. +// 1 unable to delete. +int med_delete_segment(segment *sp) +{ + int s,side,segnum; + int objnum; + + segnum = sp-Segments; + + // Cannot delete segment if only segment. + if (Num_segments == 1) + return 1; + + // Don't try to delete if segment doesn't exist. + if (sp->segnum == -1) { + mprintf((0,"Hey -- you tried to delete a non-existent segment (segnum == -1)\n")); + return 1; + } + + // Delete its refueling center if it has one + fuelcen_delete(sp); + + delete_vertices_in_segment(sp); + + Num_segments--; + + // If deleted segment has walls on any side, wipe out the wall. + for (side=0; side < MAX_SIDES_PER_SEGMENT; side++) + if (sp->sides[side].wall_num != -1) + wall_remove_side(sp, side); + + // Find out what this segment was connected to and break those connections at the other end. + for (side=0; side < MAX_SIDES_PER_SEGMENT; side++) + if (IS_CHILD(sp->children[side])) { + segment *csp; // the connecting segment + int s; + + csp = &Segments[sp->children[side]]; + for (s=0; schildren[s] == segnum) { + csp->children[s] = -1; // this is the side of connection, break it + validate_segment_side(csp,s); // we have converted a connection to a side so validate the segment + med_propagate_tmaps_to_back_side(csp,s,0); + } + Cursegp = csp; + med_create_new_segment_from_cursegp(); + copy_uvs_seg_to_seg(&New_segment,Cursegp); + } + + sp->segnum = -1; // Mark segment as inactive. + + // If deleted segment = marked segment, then say there is no marked segment + if (sp == Markedsegp) + Markedsegp = 0; + + // If deleted segment = a Group segment ptr, then wipe it out. + for (s=0;sgroup > -1) + delete_segment_from_group(sp-Segments, sp->group); + + // If we deleted something which was not connected to anything, must now select a new current segment. + if (Cursegp == sp) + for (s=0; sobjects != -1) { +// if (objnum == Objects[objnum].next) { +// mprintf((0, "Warning -- object #%i points to itself. Setting next to -1.\n", objnum)); +// Objects[objnum].next = -1; +// } + for (objnum=sp->objects;objnum!=-1;objnum=Objects[objnum].next) { + + //if an object is in the seg, delete it + //if the object is the player, move to new curseg + + if (objnum == (ConsoleObject-Objects)) { + compute_segment_center(&ConsoleObject->pos,Cursegp); + obj_relink(objnum,Cursegp-Segments); + } else + obj_delete(objnum); + } + } + + // Make sure everything deleted ok... + Assert( sp->objects==-1 ); + + // If we are leaving many holes in Segments or Vertices, then compress mine, because it is inefficient to be that way +// if ((Highest_segment_index > Num_segments+4) || (Highest_vertex_index > Num_vertices+4*8)) +// med_compress_mine(); + + return 0; +} + +// ------------------------------------------------------------------------------------------ +// Copy texture maps from sseg to dseg +void copy_tmaps_to_segment(segment *dseg, segment *sseg) +{ + int s; + + for (s=0; ssides[s].type = sseg->sides[s].type; + dseg->sides[s].tmap_num = sseg->sides[s].tmap_num; + dseg->sides[s].tmap_num2 = sseg->sides[s].tmap_num2; + } + +} + +// ------------------------------------------------------------------------------------------ +// Rotate the segment *seg by the pitch, bank, heading defined by *rot, destructively +// modifying its four free vertices in the global array Vertices. +// It is illegal to rotate a segment which has connectivity != 1. +// Pitch, bank, heading are about the point which is the average of the four points +// forming the side of connection. +// Return value: +// 0 = successful rotation +// 1 = Connectivity makes rotation illegal (connected to 0 or 2+ segments) +// 2 = Rotation causes degeneracy, such as self-intersecting segment. +// 3 = Unable to rotate because not connected to exactly 1 segment. +int med_rotate_segment(segment *seg, vms_matrix *rotmat) +{ + segment *destseg; + int newside=0,destside,s; + int count; + int back_side,side_tmaps[MAX_SIDES_PER_SEGMENT]; + + // Find side of attachment + count = 0; + for (s=0; schildren[s])) { + count++; + newside = s; + } + + // Return if passed in segment is connected to other than 1 segment. + if (count != 1) + return 3; + + destseg = &Segments[seg->children[newside]]; + + destside = 0; + while ((destseg->children[destside] != seg-Segments) && (destside < MAX_SIDES_PER_SEGMENT)) + destside++; + + // Before deleting the segment, copy its texture maps to New_segment + copy_tmaps_to_segment(&New_segment,seg); + + if (med_delete_segment(seg)) + mprintf((0,"Error in rotation: Unable to delete segment %i\n",seg-Segments)); + + if (Curside == WFRONT) + Curside = WBACK; + + med_attach_segment_rotated(destseg,&New_segment,destside,AttachSide,rotmat); + + // Save tmap_num on each side to restore after call to med_propagate_tmaps_to_segments and _back_side + // which will change the tmap nums. + for (s=0; ssides[s].tmap_num; + + back_side = Side_opposite[find_connect_side(destseg, seg)]; + + med_propagate_tmaps_to_segments(destseg, seg,0); + med_propagate_tmaps_to_back_side(seg, back_side,0); + + for (s=0; ssides[s].tmap_num = side_tmaps[s]; + + return 0; +} + +// ---------------------------------------------------------------------------------------- +int med_rotate_segment_ang(segment *seg, vms_angvec *ang) +{ + vms_matrix rotmat; + + return med_rotate_segment(seg,vm_angles_2_matrix(&rotmat,ang)); +} + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// ---------------------------------------------------------------------------- +// Compute the sum of the distances between the four pairs of points. +// The connections are: +// firstv1 : 0 (firstv1+1)%4 : 1 (firstv1+2)%4 : 2 (firstv1+3)%4 : 3 +fix seg_seg_vertex_distsum(segment *seg1, int side1, segment *seg2, int side2, int firstv1) +{ + fix distsum; + int secondv; + + distsum = 0; + for (secondv=0; secondv<4; secondv++) { + int firstv; + + firstv = (4-secondv + (3 - firstv1)) % 4; + distsum += vm_vec_dist(&Vertices[seg1->verts[Side_to_verts[side1][firstv]]],&Vertices[seg2->verts[Side_to_verts[side2][secondv]]]); + } + + return distsum; + +} + +// ---------------------------------------------------------------------------- +// Determine how to connect two segments together with the least amount of twisting. +// Returns vertex index in 0..3 on first segment. Assumed ordering of vertices +// on second segment is 0,1,2,3. +// So, if return value is 2, connect 2:0 3:1 0:2 1:3. +// Theory: +// We select an ordering of vertices for connection. For the first pair of vertices to be connected, +// compute the vector. For the three remaining pairs of vertices, compute the vectors from one vertex +// to the other. Compute the dot products of these vectors with the original vector. Add them up. +// The close we are to 3, the better fit we have. Reason: The largest value for the dot product is +// 1.0, and this occurs for a parallel set of vectors. +int get_index_of_best_fit(segment *seg1, int side1, segment *seg2, int side2) +{ + int firstv; + fix min_distance; + int best_index=0; + + min_distance = F1_0*30000; + + for (firstv=0; firstv<4; firstv++) { + fix t; + t = seg_seg_vertex_distsum(seg1, side1, seg2, side2, firstv); + if (t <= min_distance) { + min_distance = t; + best_index = firstv; + } + } + + return best_index; + +} + + +#define MAX_VALIDATIONS 50 + +// ---------------------------------------------------------------------------- +// Remap uv coordinates in all sides in segment *sp which have a vertex in vp[4]. +// vp contains absolute vertex indices. +void remap_side_uvs(segment *sp,int *vp) +{ + int s,i,v; + + for (s=0; schildren[side1]) || IS_CHILD(seg2->children[side2])) + return 2; + + // Make sure there is no wall there + if ((seg1->sides[side1].wall_num != -1) || (seg2->sides[side2].wall_num != -1)) + return 2; + + // We can form the joint. Find the best orientation of vertices. + bfi = get_index_of_best_fit(seg1, side1, seg2, side2); + + vp1 = Side_to_verts[side1]; + vp2 = Side_to_verts[side2]; + + // Make a copy of the list of vertices in seg2 which will be deleted and set the + // associated vertex number, so that all occurrences of the vertices can be replaced. + for (v=0; v<4; v++) + lost_vertices[v] = seg2->verts[(int) vp2[v]]; + + // Now, for each vertex in lost_vertices, determine which vertex it maps to. + for (v=0; v<4; v++) + remap_vertices[3 - ((v + bfi) % 4)] = seg1->verts[(int) vp1[v]]; + + // Now, in all segments, replace all occurrences of vertices in lost_vertices with remap_vertices + + // Put the one segment we know are being modified into the validation list. + // Note: seg1 does not require a full validation, only a validation of the affected side. Its vertices do not move. + nv = 1; + validation_list[0] = seg2 - Segments; + + for (v=0; v<4; v++) + for (s=0; s<=Highest_segment_index; s++) + if (Segments[s].segnum != -1) + for (sv=0; svchildren[side1] = seg2 - Segments; + seg2->children[side2] = seg1 - Segments; + + // validate all segments + validate_segment_side(seg1,side1); + for (s=0; ssides[side1].render_flag = 0; +// seg2->sides[side2].render_flag = 0; + +//--// debug -- check all segments, make sure if a children[s] == -1, then side[s].num_faces != 0 +//--{ +//--int seg,side; +//--for (seg=0; segchildren[side] != -1) +// then it is not legal to form the brider. +// Return: +// 0 bridge segment formed +// 1 unable to form bridge because one (or both) of the sides is not open. +// Note that no new vertices are created by this process. +int med_form_bridge_segment(segment *seg1, int side1, segment *seg2, int side2) +{ + segment *bs; + char *sv; + int v,bfi,i; + + if (IS_CHILD(seg1->children[side1]) || IS_CHILD(seg2->children[side2])) + return 1; + + bs = &Segments[get_free_segment_number()]; +// mprintf((0,"Forming bridge segment %i from %i to %i\n",bs-Segments,seg1-Segments,seg2-Segments)); + + bs->segnum = bs-Segments; + bs->objects = -1; + + // Copy vertices from seg2 into last 4 vertices of bridge segment. + sv = Side_to_verts[side2]; + for (v=0; v<4; v++) + bs->verts[(3-v)+4] = seg2->verts[(int) sv[v]]; + + // Copy vertices from seg1 into first 4 vertices of bridge segment. + bfi = get_index_of_best_fit(seg1, side1, seg2, side2); + + sv = Side_to_verts[side1]; + for (v=0; v<4; v++) + bs->verts[(v + bfi) % 4] = seg1->verts[(int) sv[v]]; + + // Form connections to children, first initialize all to unconnected. + for (i=0; ichildren[i] = -1; + bs->sides[i].wall_num = -1; + } + + // Now form connections between segments. + + bs->children[AttachSide] = seg1 - Segments; + bs->children[(int) Side_opposite[AttachSide]] = seg2 - Segments; + + seg1->children[side1] = bs-Segments; //seg2 - Segments; + seg2->children[side2] = bs-Segments; //seg1 - Segments; + + // Validate bridge segment, and if degenerate, clean up mess. + Degenerate_segment_found = 0; + + validate_segment(bs); + + if (Degenerate_segment_found) { + seg1->children[side1] = -1; + seg2->children[side2] = -1; + bs->children[AttachSide] = -1; + bs->children[(int) Side_opposite[AttachSide]] = -1; + if (med_delete_segment(bs)) { + mprintf((0, "Oops, tried to delete bridge segment (because it's degenerate), but couldn't.\n")); + Int3(); + } + editor_status("Bridge segment would be degenerate, not created.\n"); + return 1; + } else { + validate_segment(seg1); // used to only validate side, but segment does more error checking: ,side1); + validate_segment(seg2); // ,side2); + med_propagate_tmaps_to_segments(seg1,bs,0); + + editor_status("Bridge segment formed."); + warn_if_concave_segment(bs); + return 0; + } +} + +// ------------------------------------------------------------------------------- +// Create a segment given center, dimensions, rotation matrix. +// Note that the created segment will always have planar sides and rectangular cross sections. +// It will be created with walls on all sides, ie not connected to anything. +void med_create_segment(segment *sp,fix cx, fix cy, fix cz, fix length, fix width, fix height, vms_matrix *mp) +{ + int i,f; + vms_vector v0,v1,cv; + segment2 *sp2; + + Num_segments++; + + sp->segnum = 1; // What to put here? I don't know. + sp2 = &Segment2s[sp->segnum]; + + // Form connections to children, of which it has none. + for (i=0; ichildren[i] = -1; +// sp->sides[i].render_flag = 0; + sp->sides[i].wall_num = -1; + } + + sp->group = -1; + sp2->matcen_num = -1; + + // Create relative-to-center vertices, which are the rotated points on the box defined by length, width, height + sp->verts[0] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,+height/2,-length/2),mp)); + sp->verts[1] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,-height/2,-length/2),mp)); + sp->verts[2] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,-height/2,-length/2),mp)); + sp->verts[3] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,+height/2,-length/2),mp)); + sp->verts[4] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,+height/2,+length/2),mp)); + sp->verts[5] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,+width/2,-height/2,+length/2),mp)); + sp->verts[6] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,-height/2,+length/2),mp)); + sp->verts[7] = med_add_vertex(vm_vec_rotate(&v1,vm_vec_make(&v0,-width/2,+height/2,+length/2),mp)); + + // Now create the vector which is the center of the segment and add that to all vertices. + while (!vm_vec_make(&cv,cx,cy,cz)); + + // Now, add the center to all vertices, placing the segment in 3 space. + for (i=0; iverts[i]],&Vertices[sp->verts[i]],&cv); + + // Set scale vector. +// sp->scale.x = width; +// sp->scale.y = height; +// sp->scale.z = length; + + // Add faces to all sides. + for (f=0; fobjects = -1; //no objects in this segment + + // Assume nothing special about this segment + sp2->special = 0; + sp2->value = 0; + sp2->static_light = 0; + sp2->matcen_num = -1; + + copy_tmaps_to_segment(sp, &New_segment); + + assign_default_uvs_to_segment(sp); +} + +// ---------------------------------------------------------------------------------------------- +// Create New_segment using a specified scale factor. +void med_create_new_segment(vms_vector *scale) +{ + int s,t; + vms_vector v0; + segment *sp = &New_segment; + segment2 *sp2; + + fix length,width,height; + + length = scale->z; + width = scale->x; + height = scale->y; + + sp->segnum = 1; // What to put here? I don't know. + sp2 = &Segment2s[sp->segnum]; + + // Create relative-to-center vertices, which are the points on the box defined by length, width, height + t = Num_vertices; + sp->verts[0] = med_set_vertex(NEW_SEGMENT_VERTICES+0,vm_vec_make(&v0,+width/2,+height/2,-length/2)); + sp->verts[1] = med_set_vertex(NEW_SEGMENT_VERTICES+1,vm_vec_make(&v0,+width/2,-height/2,-length/2)); + sp->verts[2] = med_set_vertex(NEW_SEGMENT_VERTICES+2,vm_vec_make(&v0,-width/2,-height/2,-length/2)); + sp->verts[3] = med_set_vertex(NEW_SEGMENT_VERTICES+3,vm_vec_make(&v0,-width/2,+height/2,-length/2)); + sp->verts[4] = med_set_vertex(NEW_SEGMENT_VERTICES+4,vm_vec_make(&v0,+width/2,+height/2,+length/2)); + sp->verts[5] = med_set_vertex(NEW_SEGMENT_VERTICES+5,vm_vec_make(&v0,+width/2,-height/2,+length/2)); + sp->verts[6] = med_set_vertex(NEW_SEGMENT_VERTICES+6,vm_vec_make(&v0,-width/2,-height/2,+length/2)); + sp->verts[7] = med_set_vertex(NEW_SEGMENT_VERTICES+7,vm_vec_make(&v0,-width/2,+height/2,+length/2)); + Num_vertices = t; + +// sp->scale = *scale; + + // Form connections to children, of which it has none, init faces and tmaps. + for (s=0; schildren[s] = -1; +// sp->sides[s].render_flag = 0; + sp->sides[s].wall_num = -1; + create_walls_on_side(sp,s); + sp->sides[s].tmap_num = s; // assign some stupid old tmap to this side. + sp->sides[s].tmap_num2 = 0; + } + + Seg_orientation.p = 0; Seg_orientation.b = 0; Seg_orientation.h = 0; + + sp->objects = -1; //no objects in this segment + + assign_default_uvs_to_segment(sp); + + // Assume nothing special about this segment + sp2->special = 0; + sp2->value = 0; + sp2->static_light = 0; + sp2->matcen_num = -1; +} + +// ------------------------------------------------------------------------------- +void med_create_new_segment_from_cursegp(void) +{ + vms_vector scalevec; + vms_vector uvec, rvec, fvec; + + med_extract_up_vector_from_segment_side(Cursegp, Curside, &uvec); + med_extract_right_vector_from_segment_side(Cursegp, Curside, &rvec); + extract_forward_vector_from_segment(Cursegp, &fvec); + + scalevec.x = vm_vec_mag(&rvec); + scalevec.y = vm_vec_mag(&uvec); + scalevec.z = vm_vec_mag(&fvec); + + med_create_new_segment(&scalevec); +} + +// ------------------------------------------------------------------------------- +// Initialize all vertices to inactive status. +void init_all_vertices(void) +{ + int v; + int s; + + for (v=0; vverts[v]; + + // Now copy the whole struct. + *dsp = *ssp; + + // Now restore the vertex indices. + for (v=0; vverts[v] = verts_copy[v]; + + // Now destructively modify the vertex values for all vertex indices. + for (v=0; vverts[v]] = Vertices[ssp->verts[v]]; +} + +// ----------------------------------------------------------------------------- +// Create coordinate axes in orientation of specified segment, stores vertices at *vp. +void create_coordinate_axes_from_segment(segment *sp,short *vertnums) +{ + vms_matrix rotmat; + vms_vector t; + + med_extract_matrix_from_segment(sp,&rotmat); + + compute_segment_center(&Vertices[vertnums[0]],sp); + + t = rotmat.rvec; + vm_vec_scale(&t,i2f(32)); + vm_vec_add(&Vertices[vertnums[1]],&Vertices[vertnums[0]],&t); + + t = rotmat.uvec; + vm_vec_scale(&t,i2f(32)); + vm_vec_add(&Vertices[vertnums[2]],&Vertices[vertnums[0]],&t); + + t = rotmat.fvec; + vm_vec_scale(&t,i2f(32)); + vm_vec_add(&Vertices[vertnums[3]],&Vertices[vertnums[0]],&t); +} + +// ----------------------------------------------------------------------------- +// Determine if a segment is concave. Returns true if concave +int check_seg_concavity(segment *s) +{ + int sn,vn; + vms_vector n0,n1; + + for (sn=0;snverts[Side_to_verts[sn][vn%4]]], + &Vertices[s->verts[Side_to_verts[sn][(vn+1)%4]]], + &Vertices[s->verts[Side_to_verts[sn][(vn+2)%4]]]); + + //vm_vec_normalize(&n1); + + if (vn>0) if (vm_vec_dotprod(&n0,&n1) < f0_5) return 1; + + n0 = n1; + } + + return 0; +} + + +// ----------------------------------------------------------------------------- +// Find all concave segments and add to list +void find_concave_segs() +{ + int i; + segment *s; + + N_warning_segs = 0; + + for (s=Segments,i=Highest_segment_index;i>=0;s++,i--) + if (s->segnum != -1) + if (check_seg_concavity(s)) Warning_segs[N_warning_segs++]=SEG_PTR_2_NUM(s); + + +} + + +// ----------------------------------------------------------------------------- +void warn_if_concave_segments(void) +{ + char temp[1]; + + find_concave_segs(); + + if (N_warning_segs) { + editor_status("*** WARNING *** %d concave segments in mine! *** WARNING ***",N_warning_segs); + sprintf( temp, "%d", N_warning_segs ); + } +} + +// ----------------------------------------------------------------------------- +// Check segment s, if concave, warn +void warn_if_concave_segment(segment *s) +{ + char temp[1]; + int result; + + result = check_seg_concavity(s); + + if (result) { + Warning_segs[N_warning_segs++] = s-Segments; + + if (N_warning_segs) { + editor_status("*** WARNING *** New segment is concave! *** WARNING ***"); + sprintf( temp, "%d", N_warning_segs ); + } + //else + // editor_status(""); + } //else + //editor_status(""); +} + + +// ------------------------------------------------------------------------------- +// Find segment adjacent to sp:side. +// Adjacent means a segment which shares all four vertices. +// Return true if segment found and fill in segment in adj_sp and side in adj_side. +// Return false if unable to find, in which case adj_sp and adj_side are undefined. +int med_find_adjacent_segment_side(segment *sp, int side, segment **adj_sp, int *adj_side) +{ + int seg,s,v,vv; + int abs_verts[4]; + + // Stuff abs_verts[4] array with absolute vertex indices + for (v=0; v<4; v++) + abs_verts[v] = sp->verts[Side_to_verts[side][v]]; + + // Scan all segments, looking for a segment which contains the four abs_verts + for (seg=0; seg<=Highest_segment_index; seg++) { + if (seg != sp-Segments) { + for (v=0; v<4; v++) { // do for each vertex in abs_verts + for (vv=0; vvchildren[side])) + return 0; + + compute_center_point_on_side(&vsc, sp, side); + + closest_seg_dist = JOINT_THRESHOLD; + + // Scan all segments, looking for a segment which contains the four abs_verts + for (seg=0; seg<=Highest_segment_index; seg++) + if (seg != sp-Segments) + for (s=0;ssegnum != -1) + for (v=0; vverts[v] <= Highest_vertex_index); + + } + +} + +// ----------------------------------------------------------------------------------------------------- +void check_for_overlapping_segment(int segnum) +{ + int i, v; + segmasks masks; + vms_vector segcenter; + + compute_segment_center(&segcenter, &Segments[segnum]); + + for (i=0;i<=Highest_segment_index; i++) { + if (i != segnum) { + masks = get_seg_masks(&segcenter, i, 0); + if (masks.centermask == 0) { + mprintf((0, "Segment %i center is contained in segment %i\n", segnum, i)); + continue; + } + + for (v=0; v<8; v++) { + vms_vector pdel, presult; + + vm_vec_sub(&pdel, &Vertices[Segments[segnum].verts[v]], &segcenter); + vm_vec_scale_add(&presult, &segcenter, &pdel, (F1_0*15)/16); + masks = get_seg_masks(&presult, i, 0); + if (masks.centermask == 0) { + mprintf((0, "Segment %i near vertex %i is contained in segment %i\n", segnum, v, i)); + break; + } + } + } + } + +} + +// ----------------------------------------------------------------------------------------------------- +// Check for overlapping segments. +void check_for_overlapping_segments(void) +{ + int i; + + med_compress_mine(); + + for (i=0; i<=Highest_segment_index; i++) { + mprintf((0, "+")); + check_for_overlapping_segment(i); + } + + mprintf((0, "\nDone!\n")); +} + diff --git a/main/editor/seguvs.h b/main/editor/seguvs.h new file mode 100644 index 00000000..76c67755 --- /dev/null +++ b/main/editor/seguvs.h @@ -0,0 +1,50 @@ +/* +THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX +SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO +END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A +ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS +IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS +SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE +FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE +CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS +AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. +COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. +*/ +/* + * $Source: /cvs/cvsroot/d2x/main/editor/seguvs.h,v $ + * $Revision: 1.1 $ + * $Author: bradleyb $ + * $Date: 2001-10-25 02:27:17 $ + * + * Header for seguvs.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:40 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:58 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.3 1994/08/03 10:32:28 mike + * Add stretch_uvs_from_curedge. + * + * Revision 1.2 1994/05/14 18:00:58 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.1 1994/05/14 17:27:26 matt + * Initial revision + * + * + */ + + + +#ifndef _SEGUVS_H +#define _SEGUVS_H + +extern void assign_light_to_side(segment *sp, int sidenum); +extern void assign_default_lighting_all(void); +extern void stretch_uvs_from_curedge(segment *segp, int side); + +#endif diff --git a/sound/Makefile.am b/sound/Makefile.am index 6f86f575..c5a84ac4 100644 --- a/sound/Makefile.am +++ b/sound/Makefile.am @@ -1,5 +1,7 @@ INCLUDES = -I $(top_srcdir) -I$(top_srcdir)/includes -I$(top_srcdir)/main +CFLAGS += ${SDL_CFLAGS} + noinst_LIBRARIES = libsound.a if ENV_DJGPP diff --git a/video/Makefile.am b/video/Makefile.am index 8889686a..251a1a42 100644 --- a/video/Makefile.am +++ b/video/Makefile.am @@ -2,6 +2,8 @@ noinst_LIBRARIES = libvideo.a INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/includes -I$(top_srcdir)/main -I$(top_srcdir)/arch/include +CFLAGS += ${SDL_CFLAGS} + if ENV_DJGPP libvideo_a_SOURCES = dos_gr.c else -- 2.39.2