From db514a5dedc56169135b7c87f5e9ba87e435a971 Mon Sep 17 00:00:00 2001 From: Bradley Bell Date: Sun, 19 Dec 2004 13:54:27 +0000 Subject: [PATCH] imported missing editor files from d1x --- ChangeLog | 22 + main/editor/Makefile.am | 16 +- main/editor/autosave.c | 329 ++++++ main/editor/centers.c | 259 +++++ main/editor/centers.h | 55 + main/editor/curves.c | 513 ++++++++++ main/editor/eglobal.c | 221 ++++ main/editor/ehostage.c | 565 +++++++++++ main/editor/ehostage.h | 48 + main/editor/elight.c | 404 ++++++++ main/editor/eobject.c | 1138 +++++++++++++++++++++ main/editor/eobject.h | 64 ++ main/editor/eswitch.c | 635 ++++++++++++ main/editor/eswitch.h | 69 ++ main/editor/fixseg.c | 244 +++++ main/editor/func.c | 128 +++ main/editor/group.c | 2106 +++++++++++++++++++++++++++++++++++++++ main/editor/info.c | 492 +++++++++ main/editor/info.h | 47 + main/editor/kbuild.c | 284 ++++++ main/editor/kcurve.c | 204 ++++ main/editor/kfuncs.c | 498 +++++++++ main/editor/kfuncs.h | 45 + main/editor/kgame.c | 239 +++++ main/editor/kgroup.c | 13 + main/editor/khelp.c | 177 ++++ main/editor/kmine.c | 462 +++++++++ main/editor/ksegmove.c | 116 +++ main/editor/ksegsel.c | 255 +++++ main/editor/ksegsize.c | 493 +++++++++ main/editor/ktmap.c | 285 ++++++ main/editor/kview.c | 125 +++ main/editor/macro.c | 226 +++++ main/editor/macro.h | 45 + main/editor/meddraw.c | 1069 ++++++++++++++++++++ main/editor/meddraw.h | 55 + main/editor/medlisp.h | 18 + main/editor/medmisc.c | 693 +++++++++++++ main/editor/medmisc.h | 62 ++ main/editor/medrobot.c | 938 +++++++++++++++++ main/editor/medrobot.h | 56 ++ main/editor/medsel.c | 178 ++++ main/editor/medsel.h | 45 + main/editor/medwall.c | 1568 +++++++++++++++++++++++++++++ main/editor/mine.c | 549 ++++++++++ main/editor/objpage.c | 577 +++++++++++ main/editor/objpage.h | 71 ++ main/editor/seguvs.c | 1656 ++++++++++++++++++++++++++++++ main/editor/texpage.c | 379 +++++++ main/editor/texture.c | 520 ++++++++++ 50 files changed, 19254 insertions(+), 2 deletions(-) create mode 100644 main/editor/autosave.c create mode 100644 main/editor/centers.c create mode 100644 main/editor/centers.h create mode 100644 main/editor/curves.c create mode 100644 main/editor/eglobal.c create mode 100644 main/editor/ehostage.c create mode 100644 main/editor/ehostage.h create mode 100644 main/editor/elight.c create mode 100644 main/editor/eobject.c create mode 100644 main/editor/eobject.h create mode 100644 main/editor/eswitch.c create mode 100644 main/editor/eswitch.h create mode 100644 main/editor/fixseg.c create mode 100644 main/editor/func.c create mode 100644 main/editor/group.c create mode 100644 main/editor/info.c create mode 100644 main/editor/info.h create mode 100644 main/editor/kbuild.c create mode 100644 main/editor/kcurve.c create mode 100644 main/editor/kfuncs.c create mode 100644 main/editor/kfuncs.h create mode 100644 main/editor/kgame.c create mode 100644 main/editor/kgroup.c create mode 100644 main/editor/khelp.c create mode 100644 main/editor/kmine.c create mode 100644 main/editor/ksegmove.c create mode 100644 main/editor/ksegsel.c create mode 100644 main/editor/ksegsize.c create mode 100644 main/editor/ktmap.c create mode 100644 main/editor/kview.c create mode 100644 main/editor/macro.c create mode 100644 main/editor/macro.h create mode 100644 main/editor/meddraw.c create mode 100644 main/editor/meddraw.h create mode 100644 main/editor/medlisp.h create mode 100644 main/editor/medmisc.c create mode 100644 main/editor/medmisc.h create mode 100644 main/editor/medrobot.c create mode 100644 main/editor/medrobot.h create mode 100644 main/editor/medsel.c create mode 100644 main/editor/medsel.h create mode 100644 main/editor/medwall.c create mode 100644 main/editor/mine.c create mode 100644 main/editor/objpage.c create mode 100644 main/editor/objpage.h create mode 100644 main/editor/seguvs.c create mode 100644 main/editor/texpage.c create mode 100644 main/editor/texture.c diff --git a/ChangeLog b/ChangeLog index d646653c..75d008d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -27,6 +27,28 @@ * ui/Makefile.am: added Makefile.am for ui + * main/editor/Makefile.am, main/editor/autosave.c, + main/editor/centers.c, main/editor/centers.h, + main/editor/curves.c, main/editor/eglobal.c, + main/editor/ehostage.c, main/editor/ehostage.h, + main/editor/elight.c, main/editor/eobject.c, + main/editor/eobject.h, main/editor/eswitch.c, + main/editor/eswitch.h, main/editor/fixseg.c, main/editor/func.c, + main/editor/group.c, main/editor/info.c, main/editor/info.h, + main/editor/kbuild.c, main/editor/kcurve.c, main/editor/kfuncs.c, + main/editor/kfuncs.h, main/editor/kgame.c, main/editor/kgroup.c, + main/editor/khelp.c, main/editor/kmine.c, main/editor/ksegmove.c, + main/editor/ksegsel.c, main/editor/ksegsize.c, + main/editor/ktmap.c, main/editor/kview.c, main/editor/macro.c, + main/editor/macro.h, main/editor/meddraw.c, main/editor/meddraw.h, + main/editor/medlisp.h, main/editor/medmisc.c, + main/editor/medmisc.h, main/editor/medrobot.c, + main/editor/medrobot.h, main/editor/medsel.c, + main/editor/medsel.h, main/editor/medwall.c, main/editor/mine.c, + main/editor/objpage.c, main/editor/objpage.h, + main/editor/seguvs.c, main/editor/texpage.c, + main/editor/texture.c: imported missing editor files from d1x + 2004-12-17 Chris Taylor * main/state.c: open autosave file for writing, not reading diff --git a/main/editor/Makefile.am b/main/editor/Makefile.am index 3309c31c..1622c7fe 100644 --- a/main/editor/Makefile.am +++ b/main/editor/Makefile.am @@ -1,6 +1,18 @@ noinst_LIBRARIES = libeditor.a INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/arch/include -I$(top_srcdir)/main -libeditor_a_SOURCES = med.c segment.c +libeditor_a_SOURCES = \ +autosave.c centers.c curves.c eglobal.c ehostage.c \ +elight.c eobject.c eswitch.c fixseg.c func.c \ +group.c info.c kbuild.c kcurve.c kfuncs.c \ +kgame.c kgroup.c khelp.c kmine.c ksegmove.c \ +ksegsel.c ksegsize.c ktmap.c kview.c macro.c \ +med.c meddraw.c medmisc.c medrobot.c medsel.c \ +medwall.c mine.c objpage.c segment.c seguvs.c \ +texpage.c texture.c -EXTRA_DIST = editor.h kdefs.h medwall.h seguvs.h texpage.h +EXTRA_DIST = \ +centers.h editor.h ehostage.h eobject.h eswitch.h \ +info.h kdefs.h kfuncs.h macro.h meddraw.h \ +medlisp.h medmisc.h medrobot.h medsel.h medwall.h \ +objpage.h seguvs.h texpage.h diff --git a/main/editor/autosave.c b/main/editor/autosave.c new file mode 100644 index 00000000..9fcee9d5 --- /dev/null +++ b/main/editor/autosave.c @@ -0,0 +1,329 @@ +/* +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/autosave.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Autosave system: + * Saves current mine to disk to prevent loss of work, and support undo. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:47 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:53 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.25 1994/11/19 00:04:40 john + * Changed some shorts to ints. + * + * Revision 1.24 1994/11/17 11:38:59 matt + * Ripped out code to load old mines + * + * Revision 1.23 1994/07/28 17:00:01 mike + * fix diagnostic_message erasing. + * + * Revision 1.22 1994/07/21 12:48:28 mike + * Make time of day a global, fix clock so it doesn't show 10:2 instead of 10:02 + * + * Revision 1.21 1994/05/14 17:17:58 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.20 1994/05/02 18:04:14 yuan + * Fixed warning. + * + * Revision 1.19 1994/05/02 17:59:04 yuan + * Changed undo_status into an array rather than malloced pointers. + * + * Revision 1.18 1994/03/16 09:55:48 mike + * Flashing : in time. + * + * Revision 1.17 1994/02/11 10:27:36 matt + * Changed 'if !DEMO' to 'ifndef DEMO' + * + * Revision 1.16 1994/02/08 12:43:18 yuan + * Crippled save game function from demo version + * + * Revision 1.15 1994/02/01 13:27:26 yuan + * autosave default off. + * + * Revision 1.14 1994/01/05 09:57:37 yuan + * Fixed calendar/clock problem. + * + * Revision 1.13 1993/12/17 16:09:59 yuan + * Changed clock font from Red to Black. + * + * Revision 1.12 1993/12/15 13:08:38 yuan + * Fixed :0x times, so that the 0 shows up. + * + * Revision 1.11 1993/12/15 11:19:52 yuan + * Added code to display clock in upper right. + * + * Revision 1.10 1993/12/14 21:18:51 yuan + * Added diagnostic message to display + * + * Revision 1.9 1993/12/14 18:32:59 yuan + * Added timed autosave code + * + * Revision 1.8 1993/12/13 17:23:25 yuan + * Fixed bugs with undo. + * They were caused by badly changed extensions. + * + * Revision 1.7 1993/12/09 16:42:32 yuan + * Changed extension of temp mines from .mi? -> .mn? + * and now to .m? (So it doesn't interfere with .mnu) + * + * Revision 1.6 1993/12/09 16:27:06 yuan + * Added toggle for autosave + * + * Revision 1.5 1993/11/29 19:46:32 matt + * Changed includes + * + * Revision 1.4 1993/11/11 15:54:11 yuan + * Added display message for Undo... + * Eg. Attach Segment UNDONE. + * + * Revision 1.3 1993/11/09 18:53:11 yuan + * Autosave/Undo works up to 10 moves. + * + * Revision 1.2 1993/11/08 19:14:03 yuan + * Added Undo command (not working yet) + * + * Revision 1.1 1993/11/08 16:57:59 yuan + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: autosave.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#include +#ifndef __LINUX__ +#include +#endif +#include + +#include "error.h" + +#include "inferno.h" +#include "editor.h" +#include "mono.h" +#include "u_mem.h" +#include "ui.h" + +#define AUTOSAVE_PERIOD 5 // Number of minutes for timed autosave + +int Autosave_count; +int Autosave_numfiles; +int Autosave_total; +int undo_count; +int original; + +int Timer_save_flag=0; +int Autosave_flag; +int save_second=-1; + +char undo_status[10][100]; + +void init_autosave(void) { +// int i; + + Autosave_count = 0; + Autosave_numfiles = 0; + Autosave_flag = 0; + undo_count = 0; + //MALLOC( undo_status, char *, 10 ); + //for (i=0; i<10; i++) + // MALLOC( undo_status[i], char, 100 ); + autosave_mine(mine_filename); +} + +void close_autosave(void) { + int i; + char *delname, *ext; + + for (i=0;i 0) undo_count--; + if (Autosave_count > 9) Autosave_count -= 10; + if (Autosave_numfiles < 10) + Autosave_numfiles++; + if (Autosave_total < 10) + Autosave_total++; + + free(savename); + + } + +} + + +void print_clock( int seconds, char message[10] ) { + int w,h,aw; + char *p; + + // Make colon flash + if (seconds & 1) + if ((p = strchr(message, ':')) != NULL) + *p = ' '; + + gr_set_current_canvas( NULL ); + gr_set_fontcolor( CBLACK, CGREY ); + gr_get_string_size( message, &w, &h, &aw ); + gr_setcolor( CGREY ); + gr_rect( 700, 0, 799, h+1 ); + gr_string( 700, 0, message ); + gr_set_fontcolor( CBLACK, CWHITE ); +} + +static char the_time[14]; // changed from 10, I don't think that was long enough + +void clock_message( int seconds, char *format, ... ) { + va_list ap; + + va_start(ap, format); + vsprintf(the_time, format, ap); + va_end(ap); + + print_clock(seconds, the_time); +} + + +struct tm Editor_time_of_day; + +void set_editor_time_of_day() +{ + time_t ltime; + + time( <ime ); + Editor_time_of_day = *localtime( <ime ); +} + +void TimedAutosave(char *name) +{ + int month,day,hour,minute,second; + + month = (Editor_time_of_day.tm_mon) + 1; + day = Editor_time_of_day.tm_mday; + minute = Editor_time_of_day.tm_min; + hour = Editor_time_of_day.tm_hour; + second = Editor_time_of_day.tm_sec; + + if (hour > 12) hour-=12; + + if (second!=save_second) { + save_second = second; + clock_message(second, "%d/%d %d:%02d", month, day, hour, minute); + } + + +#ifndef DEMO + if (minute%AUTOSAVE_PERIOD != 0) + Timer_save_flag = 1; + + if ((minute%AUTOSAVE_PERIOD == 0) && (Timer_save_flag)) { + time_t ltime; + + autosave_mine(name); + Timer_save_flag = 0; + time( <ime ); + diagnostic_message("Mine Autosaved at %s\n", ctime(<ime)); + } +#endif + +} + + +int undo( void ) { + Int3(); + return 2; + +//@@ char *loadname, *ext; +//@@ if (undo_count == 0) original = Autosave_count; +//@@ +//@@ if (!Autosave_flag) +//@@ return 2; +//@@ +//@@ if (Autosave_numfiles > 1) { +//@@ +//@@ MALLOC(loadname, char, 128); +//@@ +//@@ strcpy ( loadname, mine_filename ); +//@@ strupr( loadname ); +//@@ if ( !strcmp(loadname, "*.MIN") ) strcpy(loadname, "TEMP.MIN"); +//@@ +//@@ undo_count++; +//@@ Autosave_count = original - undo_count; +//@@ if (Autosave_count < 0) Autosave_count = Autosave_count+10; +//@@ Autosave_numfiles--; +//@@ //mprintf(0, "u=%d a=%d o=%d num=%d\n", undo_count, Autosave_count, original, Autosave_numfiles); +//@@ +//@@ ext = strstr(loadname, ".MIN"); +//@@ if (Autosave_count == 0) sprintf( ext, ".M9" ); +//@@ else sprintf( ext, ".M%d", Autosave_count-1 ); +//@@ //mprintf( 0, "Loading: %s\n", loadname ); +//@@ med_load_mine( loadname ); +//@@ +//@@ free(loadname); +//@@ return 0; +//@@ } +//@@ else return 1; +//@@ //diagnostic_message("Can't undo\n"); + +} + diff --git a/main/editor/centers.c b/main/editor/centers.c new file mode 100644 index 00000000..9976c005 --- /dev/null +++ b/main/editor/centers.c @@ -0,0 +1,259 @@ +/* +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/centers.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Dialog box stuff for control centers, material centers, etc. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:47 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:30 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.9 1994/11/27 23:17:28 matt + * Made changes for new mprintf calling convention + * + * Revision 1.8 1994/10/05 22:13:46 mike + * Clean up Centers dialog. + * + * Revision 1.7 1994/10/03 23:39:55 mike + * Call fuelcen_activate instead of fuelcen_create. + * + * Revision 1.6 1994/08/02 12:16:35 mike + * Change materialization center functionality. + * + * Revision 1.5 1994/08/01 11:04:42 yuan + * New materialization centers. + * + * Revision 1.4 1994/07/22 17:19:10 yuan + * Working on dialog box for refuel/repair/material/control centers. + * + * Revision 1.3 1994/07/21 19:35:09 yuan + * Fixed #include problem + * + * Revision 1.2 1994/07/21 19:02:41 yuan + * *** empty log message *** + * + * Revision 1.1 1994/07/18 16:00:54 yuan + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: centers.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include + +#include "fuelcen.h" +#include "screens.h" +#include "inferno.h" +#include "segment.h" +#include "editor.h" + +#include "timer.h" +#include "objpage.h" +#include "fix.h" +#include "mono.h" +#include "error.h" +#include "kdefs.h" +#include "object.h" +#include "polyobj.h" +#include "game.h" +#include "powerup.h" +#include "ai.h" +#include "hostage.h" +#include "eobject.h" +#include "medwall.h" +#include "eswitch.h" +#include "ehostage.h" +#include "key.h" +#include "medrobot.h" +#include "bm.h" +#include "centers.h" + +//------------------------------------------------------------------------- +// Variables for this module... +//------------------------------------------------------------------------- +static UI_WINDOW *MainWindow = NULL; +static UI_GADGET_BUTTON *QuitButton; +static UI_GADGET_RADIO *CenterFlag[MAX_CENTER_TYPES]; +static UI_GADGET_CHECKBOX *RobotMatFlag[MAX_ROBOT_TYPES]; + +static int old_seg_num; + +char center_names[MAX_CENTER_TYPES][CENTER_STRING_LENGTH] = { + "Nothing", + "FuelCen", + "RepairCen", + "ControlCen", + "RobotMaker" +}; + +//------------------------------------------------------------------------- +// Called from the editor... does one instance of the centers dialog box +//------------------------------------------------------------------------- +int do_centers_dialog() +{ + int i; + + // Only open 1 instance of this window... + if ( MainWindow != NULL ) return 0; + + // Close other windows. + close_trigger_window(); + hostage_close_window(); + close_wall_window(); + robot_close_window(); + + // Open a window with a quit button + MainWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG ); + QuitButton = ui_add_gadget_button( MainWindow, 20, 252, 48, 40, "Done", NULL ); + + // These are the checkboxes for each door flag. + i = 80; + CenterFlag[0] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "NONE" ); i += 24; + CenterFlag[1] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "FuelCen" ); i += 24; + CenterFlag[2] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "RepairCen" ); i += 24; + CenterFlag[3] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "ControlCen" ); i += 24; + CenterFlag[4] = ui_add_gadget_radio( MainWindow, 18, i, 16, 16, 0, "RobotCen" ); i += 24; + + // These are the checkboxes for each door flag. + for (i=0; iflag = 0; // Tells ui that this button isn't checked + CenterFlag[i]->status = 1; // Tells ui to redraw button + } + + Assert(Cursegp->special < MAX_CENTER_TYPES); + CenterFlag[Cursegp->special]->flag = 1; + + mprintf((0, "Cursegp->matcen_num = %i\n", Cursegp->matcen_num)); + + // Read materialization center robot bit flags + for ( i=0; i < N_robot_types; i++ ) { + RobotMatFlag[i]->status = 1; // Tells ui to redraw button + if (RobotCenters[Cursegp->matcen_num].robot_flags & (1 << i)) + RobotMatFlag[i]->flag = 1; // Tells ui that this button is checked + else + RobotMatFlag[i]->flag = 0; // Tells ui that this button is not checked + } + + } + + //------------------------------------------------------------ + // If any of the radio buttons that control the mode are set, then + // update the corresponding center. + //------------------------------------------------------------ + + redraw_window=0; + for ( i=0; i < MAX_CENTER_TYPES; i++ ) { + if ( CenterFlag[i]->flag == 1 ) + { + if ( i == 0) + fuelcen_delete(Cursegp); + else if ( Cursegp->special != i ) { + fuelcen_delete(Cursegp); + redraw_window = 1; + fuelcen_activate( Cursegp, i ); + } + } + } + + for ( i=0; i < N_robot_types; i++ ) { + if ( RobotMatFlag[i]->flag == 1 ) { + if (!(RobotCenters[Cursegp->matcen_num].robot_flags & (1<matcen_num].robot_flags |= (1<matcen_num, RobotCenters[Cursegp->matcen_num].robot_flags)); + } + } else if (RobotCenters[Cursegp->matcen_num].robot_flags & 1<matcen_num].robot_flags &= ~(1<matcen_num, RobotCenters[Cursegp->matcen_num].robot_flags)); + } + } + + //------------------------------------------------------------ + // If anything changes in the ui system, redraw all the text that + // identifies this wall. + //------------------------------------------------------------ + if (redraw_window || (old_seg_num != Cursegp-Segments ) ) { +// int i; +// char temp_text[CENTER_STRING_LENGTH]; + + ui_wprintf_at( MainWindow, 12, 6, "Seg: %3d", Cursegp-Segments ); + +// for (i=0; ispecial < MAX_CENTER_TYPES); +// strncpy(temp_text, Center_names[Cursegp->special], strlen(Center_names[Cursegp->special])); +// ui_wprintf_at( MainWindow, 12, 23, " Type: %s", temp_text ); + Update_flags |= UF_WORLD_CHANGED; + } + + if ( QuitButton->pressed || (last_keypress==KEY_ESC) ) { + close_centers_window(); + return; + } + + old_seg_num = Cursegp-Segments; +} + + + diff --git a/main/editor/centers.h b/main/editor/centers.h new file mode 100644 index 00000000..90aad127 --- /dev/null +++ b/main/editor/centers.h @@ -0,0 +1,55 @@ +/* +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/centers.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Center header + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:29 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:02 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.3 1994/08/02 12:16:27 mike + * Prototype Center_names. + * + * Revision 1.2 1994/07/21 19:35:20 yuan + * Fixed #include problem + * + * Revision 1.1 1994/07/21 19:11:36 yuan + * Initial revision + * + * + */ + + + +#ifndef _CENTERS_H +#define _CENTERS_H + +#define CENTER_STRING_LENGTH 12 + +#include "fuelcen.h" + +extern char Center_names[MAX_CENTER_TYPES][CENTER_STRING_LENGTH]; + +void close_centers_window(); +void do_centers_window(); + +#endif diff --git a/main/editor/curves.c b/main/editor/curves.c new file mode 100644 index 00000000..ded13c96 --- /dev/null +++ b/main/editor/curves.c @@ -0,0 +1,513 @@ +/* +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/curves.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * curve generation stuff + * + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: curves.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#ifndef __LINUX__ +#include +#include +#endif + +#include "inferno.h" +#include "mono.h" +#include "vecmat.h" +#include "gr.h" +#include "key.h" +#include "editor.h" +#include "gameseg.h" + +#define ONE_OVER_SQRT2 F1_0 * 0.707106781 +#define CURVE_RIGHT 1 +#define CURVE_UP 2 + +segment *OriginalSeg; +segment *OriginalMarkedSeg; +int OriginalSide; +int OriginalMarkedSide; +segment *CurveSegs[MAX_SEGMENTS]; +int CurveNumSegs; +const fix Mh[4][4] = { { 2*F1_0, -2*F1_0, 1*F1_0, 1*F1_0 }, + {-3*F1_0, 3*F1_0, -2*F1_0, -1*F1_0 }, + { 0*F1_0, 0*F1_0, 1*F1_0, 0*F1_0 }, + { 1*F1_0, 0*F1_0, 0*F1_0, 0*F1_0 } }; + +void generate_banked_curve(fix maxscale, vms_equation coeffs); + +void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs) { +// Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t~3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4 + + coeffs->n.x3 = fixmul(2*F1_0,p1->x) - fixmul(2*F1_0,p4->x) + r1->x + r4->x; + coeffs->n.x2 = fixmul(-3*F1_0,p1->x) + fixmul(3*F1_0,p4->x) - fixmul(2*F1_0,r1->x) - fixmul(1*F1_0,r4->x); + coeffs->n.x1 = r1->x; + coeffs->n.x0 = p1->x; + coeffs->n.y3 = fixmul(2*F1_0,p1->y) - fixmul(2*F1_0,p4->y) + r1->y + r4->y; + coeffs->n.y2 = fixmul(-3*F1_0,p1->y) + fixmul(3*F1_0,p4->y) - fixmul(2*F1_0,r1->y) - fixmul(1*F1_0,r4->y); + coeffs->n.y1 = r1->y; + coeffs->n.y0 = p1->y; + coeffs->n.z3 = fixmul(2*F1_0,p1->z) - fixmul(2*F1_0,p4->z) + r1->z + r4->z; + coeffs->n.z2 = fixmul(-3*F1_0,p1->z) + fixmul(3*F1_0,p4->z) - fixmul(2*F1_0,r1->z) - fixmul(1*F1_0,r4->z); + coeffs->n.z1 = r1->z; + coeffs->n.z0 = p1->z; + +} + +vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t) { + fix t2, t3; + vms_vector coord; + + if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n"); + + t2 = fixmul(t,t); t3 = fixmul(t2,t); + + coord.x = fixmul(coeffs->n.x3,t3) + fixmul(coeffs->n.x2,t2) + fixmul(coeffs->n.x1,t) + coeffs->n.x0; + coord.y = fixmul(coeffs->n.y3,t3) + fixmul(coeffs->n.y2,t2) + fixmul(coeffs->n.y1,t) + coeffs->n.y0; + coord.z = fixmul(coeffs->n.z3,t3) + fixmul(coeffs->n.z2,t2) + fixmul(coeffs->n.z1,t) + coeffs->n.z0; + + return coord; +} + + +fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist) { + vms_vector coord; + fix t, diff; + + if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n"); + + for (t=t0;t<1*F1_0;t+=0.001*F1_0) { + coord = evaluate_curve(coeffs, 3, t); + diff = dist - vm_vec_dist(&coord, p0); + if (diff-ACCURACY)) + return t; + } + return -1*F1_0; + +} + +void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir) { + fix t2; + + if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n"); + + t2 = fixmul(t0,t0); + + dir->x = fixmul(3*F1_0,fixmul(coeffs->n.x3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.x2,t0)) + coeffs->n.x1; + dir->y = fixmul(3*F1_0,fixmul(coeffs->n.y3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.y2,t0)) + coeffs->n.y1; + dir->z = fixmul(3*F1_0,fixmul(coeffs->n.z3,t2)) + fixmul(2*F1_0,fixmul(coeffs->n.z2,t0)) + coeffs->n.z1; + vm_vec_normalize( dir ); + +} + +void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t) { + vms_vector coord, dcoord; + fix t, dt; + + gr_setcolor(15); + gr_box( 75, 40, 325, 290 ); + gr_box( 75, 310, 325, 560 ); + gr_box( 475, 310, 725, 560 ); + //gr_pal_fade_in( grd_curscreen->pal ); + + for (t=min_t;t fixmul( nextdist, 1.5*F1_0 )) { + vms_matrix rotmat,rotmat2; + vms_vector tdest; + + if (firstsegflag==1) + firstsegflag=0; + else + extract_forward_vector_from_segment(Cursegp, &tvec); + nextdist = vm_vec_mag(&tvec); // nextdist := distance to next point + t = curve_dist(&coeffs, 3, t, &prev_point, nextdist); // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve) + coord = evaluate_curve(&coeffs, 3, t); // coord := point about forward vector magnitude units away from prev_point + enddist = vm_vec_dist(&coord, &p4); // enddist := distance from current to end point, vec_dir used as a temporary variable + //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point)); + vm_vec_normalized_dir(&vec_dir, &coord, &prev_point); + if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) { + med_extract_matrix_from_segment( Cursegp,&rotmat ); // rotmat := matrix describing orientation of Cursegp + vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp + vec_dir = tdest; + + vm_vector_2_matrix(&rotmat2,&vec_dir,NULL,NULL); +// mprintf(0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3)); +// mprintf(0, " [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6)); +// mprintf(0, " [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9)); + + med_rotate_segment( Cursegp, &rotmat2 ); + prev_point = coord; + Curside = Side_opposite[AttachSide]; + + CurveSegs[CurveNumSegs]=Cursegp; + CurveNumSegs++; + } else return 0; + } + + extract_up_vector_from_segment( Cursegp,&tvec ); + uangle = vm_vec_delta_ang( &tvec, &r4t, &r4 ); + if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; + if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; + if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; + if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; + extract_right_vector_from_segment( Cursegp,&tvec ); + rangle = vm_vec_delta_ang( &tvec, &r4t, &r4 ); + if (rangle >= F1_0/8) rangle -= F1_0/4; + if (rangle >= F1_0/8) rangle -= F1_0/4; + if (rangle <= -F1_0/8) rangle += F1_0/4; + if (rangle <= -F1_0/8) rangle += F1_0/4; + + if ((uangle != 0) && (rangle != 0)) { + maxscale = CurveNumSegs*F1_0; +// mprintf(0, "Banked Curve Generation.. %f.\n", f2fl(maxscale)); + generate_banked_curve(maxscale, coeffs); + } + + if (CurveNumSegs) { + med_form_bridge_segment( Cursegp, Side_opposite[AttachSide], Markedsegp, Markedside ); + CurveSegs[CurveNumSegs] = &Segments[ Markedsegp->children[Markedside] ]; + CurveNumSegs++; + } + + Cursegp = OriginalSeg; + Curside = OriginalSide; + + med_create_new_segment_from_cursegp(); + + //warn_if_concave_segments(); + + if (CurveNumSegs) return 1; + else return 0; +} + +void generate_banked_curve(fix maxscale, vms_equation coeffs) { + vms_vector vec_dir, tvec, b4r4t; + vms_vector coord,prev_point; + fix enddist, nextdist; + int firstsegflag; + fixang rangle, uangle, angle, scaled_ang=0; + fix t; + + if (CurveNumSegs) { + + extract_up_vector_from_segment( Cursegp,&b4r4t ); + uangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 ); + if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; + if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4; + if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; + if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4; +// mprintf(0, "up angle %f\n", f2fl(uangle)*360); + + extract_right_vector_from_segment( Cursegp,&b4r4t ); + rangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 ); + if (rangle >= F1_0/8) rangle -= F1_0/4; + if (rangle >= F1_0/8) rangle -= F1_0/4; + if (rangle <= -F1_0/8) rangle += F1_0/4; + if (rangle <= -F1_0/8) rangle += F1_0/4; +// mprintf(0, "right angle %f\n", f2fl(rangle)*360); + + angle = uangle; + if (abs(rangle) < abs(uangle)) angle = rangle; + + delete_curve(); + + coord = prev_point = p1; + +#define MAGIC_NUM 0.707*F1_0 + + if (maxscale) + scaled_ang = fixdiv(angle,fixmul(maxscale,MAGIC_NUM)); + mprintf((0, "scaled angle = %f\n", f2fl(scaled_ang))); + + t=0; + tvec = r1save; + firstsegflag = 1; + enddist = F1_0; nextdist = 0; + while ( enddist > fixmul( nextdist, 1.5*F1_0 )) { + vms_matrix rotmat,rotmat2; + vms_vector tdest; + + if (firstsegflag==1) + firstsegflag=0; + else + extract_forward_vector_from_segment(Cursegp, &tvec); + nextdist = vm_vec_mag(&tvec); // nextdist := distance to next point + t = curve_dist(&coeffs, 3, t, &prev_point, nextdist); // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve) + coord = evaluate_curve(&coeffs, 3, t); // coord := point about forward vector magnitude units away from prev_point + enddist = vm_vec_dist(&coord, &p4); // enddist := distance from current to end point, vec_dir used as a temporary variable + //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point)); + vm_vec_normalized_dir(&vec_dir, &coord, &prev_point); + if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) { + med_extract_matrix_from_segment( Cursegp,&rotmat ); // rotmat := matrix describing orientation of Cursegp + vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp + vec_dir = tdest; + vm_vec_ang_2_matrix(&rotmat2,&vec_dir,scaled_ang); +// mprintf((0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3))); +// mprintf((0, " [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6))); +// mprintf((0, " [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9))); + + med_rotate_segment( Cursegp, &rotmat2 ); + prev_point = coord; + Curside = Side_opposite[AttachSide]; + + CurveSegs[CurveNumSegs]=Cursegp; + CurveNumSegs++; + } + } + } +} + + +void delete_curve() { + int i; + + for (i=0; isegnum )); + if (CurveSegs[i]->segnum != -1) + med_delete_segment(CurveSegs[i]); + } + Markedsegp = OriginalMarkedSeg; + Markedside = OriginalMarkedSide; + Cursegp = OriginalSeg; + Curside = OriginalSide; + med_create_new_segment_from_cursegp(); + CurveNumSegs = 0; +// mprintf((0, "Num_segments %d\n", Num_segments)); + + //editor_status(""); + //warn_if_concave_segments(); +} + +/* +void main() { + vms_vector p1; + vms_vector p4; + vms_vector r1; + vms_vector r4; + vms_equation coeffs; + float x, y, z; + vms_vector test, test2, tvec; + fix t, t0; + fix distance, dist; + int key; + + + key_init(); + printf("Enter p1 (x,y,z): "); + scanf("%f %f %f", &x, &y, &z); + p1.x = x*F1_0; p1.y = y*F1_0; p1.z = z*F1_0; + printf("Enter p4 (x,y,z): "); + scanf("%f %f %f", &x, &y, &z); + p4.x = x*F1_0; p4.y = y*F1_0; p4.z = z*F1_0; + printf("Enter r1 : "); + scanf("%f %f %f", &x, &y, &z); + r1.x = x*F1_0; r1.y = y*F1_0; r1.z = z*F1_0; + printf("Enter r4 : "); + scanf("%f %f %f", &x, &y, &z); + r4.x = x*F1_0; r4.y = y*F1_0; r4.z = z*F1_0; + + create_curve( &p1, &p4, &r1, &r4, &coeffs ); + + printf("\nQ(t) = "); + printf("x [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.n.x3), f2fl(coeffs.n.x2), f2fl(coeffs.n.x1), f2fl(coeffs.n.x0)); + printf(" y [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.n.y3), f2fl(coeffs.n.y2), f2fl(coeffs.n.y1), f2fl(coeffs.n.y0)); + printf(" z [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.n.z3), f2fl(coeffs.n.z2), f2fl(coeffs.n.z1), f2fl(coeffs.n.z0)); + + printf("\nChecking direction vectors.\n"); + + for (t=0*F1_0;t<1*F1_0;t+=0.1*F1_0) { + curve_dir(&coeffs, 3, t, &test); + printf(" t = %.3f dir = <%6.3f, %6.3f, %6.3f >\n", f2fl(t), f2fl(test.x), f2fl(test.y), f2fl(test.z) ); + } + + printf("\nChecking distance function.\n"); + printf("Enter a distance: "); + scanf("%f", &x); + distance = x*F1_0; + printf("Enter a (0 +#include "inferno.h" +#include "segment.h" +#include "editor.h" + +// Global pointer to current vertices, right now always Vertices. Set in create_new_mine. +segment New_segment; // The segment which can be added to the mine. +segment *Cursegp; // Pointer to current segment in mine. +int Curside; // Side index in 0..MAX_SIDES_PER_SEGMENT of active side. +int Curedge; // Current edge on current side, in 0..3 +int Curvert; // Current vertex on current side, in 0..3 +int AttachSide = WFRONT; // Side on segment to attach. +segment *Markedsegp; // Marked segment, used in conjunction with *Cursegp to form joints. +int Markedside; // Marked side on Markedsegp. + +int Draw_all_segments; // Set to 1 means draw_world draws all segments in Segments, else draw only connected segments + +sbyte Vertex_active[MAX_VERTICES]; // !0 means vertex is in use, 0 means not in use. + +int N_selected_segs=0; // Number of segments found at Selected_segs +short Selected_segs[MAX_SELECTED_SEGS]; // List of segment numbers currently selected + +int N_warning_segs=0; // Number of segments warning-worthy, such as a concave segment +short Warning_segs[MAX_WARNING_SEGS]; // List of segment numbers currently selected + +int N_found_segs=0; // Number of segments found with last shift-mouse-click +short Found_segs[MAX_FOUND_SEGS]; // List of warning-worthy segments + +int Show_axes_flag=0; // 0 = don't show, !0 = do show coordinate axes in *Cursegp orientation + +sbyte Been_visited[MAX_SEGMENTS]; // List of segments visited in a recursive search, if element n set, segment n done been visited + +// Variables global to this editor.c and the k?????.c files. +uint Update_flags = UF_ALL; //force total redraw +int Funky_chase_mode = 0; +vms_angvec Seg_orientation = {0,0,0}; +vms_vector Seg_scale = {F1_0*20,F1_0*20,F1_0*20}; +int mine_changed = 0; +int ModeFlag; +editor_view *current_view; + +int SegSizeMode = 1; // Mode = 0/1 = not/is legal to move bound vertices, + +//the view for the different windows. +editor_view LargeView = {0,1, NULL, i2f(100),{{f1_0,0,0},{0,f1_0,0},{0,0,f1_0}},f1_0}; +#if ORTHO_VIEWS +editor_view TopView = {1,1, NULL, i2f(100),{{f1_0,0,0},{0,0,-f1_0},{0,f1_0,0}},f1_0}; +editor_view FrontView = {2,1, NULL, i2f(100),{{f1_0,0,0},{0,f1_0,0},{0,0,f1_0}},f1_0}; +editor_view RightView = {3,1, NULL, i2f(100),{{0,0,f1_0},{0,f1_0,0},{f1_0,0,0}},f1_0}; +#endif + + +editor_view *Views[] = {&LargeView, +#if ORTHO_VIEWS + &TopView,&FrontView,&RightView +#endif + }; + +int N_views = (sizeof(Views) / sizeof(*Views)); + +int Lock_view_to_cursegp = 1; // !0 means whenever cursegp changes, view it + +int Num_tilings = 1; // Number of tilings per wall + +short Cur_object_index = -1; + +// The current robot type +int Cur_robot_type = 0; + +// !0 if a degenerate segment has been found. +int Degenerate_segment_found=0; + diff --git a/main/editor/ehostage.c b/main/editor/ehostage.c new file mode 100644 index 00000000..76ba91a8 --- /dev/null +++ b/main/editor/ehostage.c @@ -0,0 +1,565 @@ +/* +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/ehostage.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Routines for placing hostages, etc... + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:53 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:45 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.17 1995/01/14 19:18:05 john + * First version of object paging. + * + * Revision 1.16 1994/11/20 14:11:41 matt + * Show object number in hostage window + * + * Revision 1.15 1994/11/19 19:55:46 matt + * Added code to full support different hostage head clip & message for + * each hostage. + * + * + * Revision 1.14 1994/10/28 15:03:27 john + * Made digi_play_sample use volume. + * + * + * Revision 1.13 1994/10/23 02:11:39 matt + * Got rid of obsolete hostage_info stuff + * + * Revision 1.12 1994/10/04 13:15:44 john + * Changed PLAY_SOUND to digi_play_sample. + * + * Revision 1.11 1994/08/02 14:17:28 mike + * Clean up dialog boxes. + * + * Revision 1.10 1994/07/22 17:19:17 yuan + * Working on dialog box for refuel/repair/material/control centers. + * + * Revision 1.9 1994/07/06 15:22:34 john + * Added new sound. + * + * + * Revision 1.8 1994/07/06 14:26:07 john + * Added vclip. + * + * Revision 1.7 1994/07/06 13:25:52 john + * Added compress hostages functions. + * + * Revision 1.6 1994/07/06 12:52:27 john + * Fixed warnings. + * + * Revision 1.5 1994/07/06 12:43:04 john + * Made generic messages for hostages. + * + * Revision 1.4 1994/07/06 11:49:01 john + * Made adding hostage update current object. + * + * Revision 1.3 1994/07/06 10:56:00 john + * New structures for hostages. + * + * Revision 1.2 1994/07/01 17:57:13 john + * First version of not-working hostage system + * + * + * Revision 1.1 1994/07/01 14:21:44 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: ehostage.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#ifndef __LINUX__ +#include +#include +#include +#endif +#include +#include + +#include "screens.h" +#include "inferno.h" +#include "segment.h" +#include "editor.h" + +#include "timer.h" +#include "objpage.h" +#include "fix.h" +#include "mono.h" +#include "error.h" +#include "kdefs.h" +#include "object.h" +#include "polyobj.h" +#include "game.h" +#include "powerup.h" +#include "ai.h" +#include "hostage.h" +#include "eobject.h" +#include "medwall.h" +#include "eswitch.h" +#include "medrobot.h" +#include "key.h" +#include "bm.h" +#include "sounds.h" +#include "centers.h" +#include "piggy.h" + +//------------------------------------------------------------------------- +// Variables for this module... +//------------------------------------------------------------------------- +static UI_WINDOW *MainWindow = NULL; +static UI_GADGET_USERBOX *HostageViewBox; +static UI_GADGET_INPUTBOX *HostageText; +static UI_GADGET_BUTTON *QuitButton; +static int CurrentHostageIndex=-1; +static int LastHostageIndex=-1; + +static fix Vclip_animation_time=0; // How long the rescue sequence has been playing +static fix Vclip_playback_speed=0; // Calculated internally. Frames/second of vclip. +static vclip *Vclip_ptr = NULL; // Used for the vclip on monitor + +void vclip_play( vclip * vc, fix frame_time ) +{ + int bitmapnum; + + if ( vc == NULL ) + return; + + if ( vc != Vclip_ptr ) { + // Start new vclip + Vclip_ptr = vc; + Vclip_animation_time = 1; + + // Calculate the frame/second of the playback + Vclip_playback_speed = fixdiv(i2f(Vclip_ptr->num_frames),Vclip_ptr->play_time); + } + + if ( Vclip_animation_time <= 0 ) + return; + + // Find next bitmap in the vclip + bitmapnum = f2i(Vclip_animation_time); + + // Check if vclip is done playing. + if (bitmapnum >= Vclip_ptr->num_frames) { + Vclip_animation_time = 1; // Restart this vclip + bitmapnum = 0; + } + + PIGGY_PAGE_IN( Vclip_ptr->frames[bitmapnum] ); + gr_bitmap(0,0,&GameBitmaps[Vclip_ptr->frames[bitmapnum].index] ); + + Vclip_animation_time += fixmul(frame_time, Vclip_playback_speed ); +} + + + +static char HostageMessage[] = " "; + +static fix Time; + +int SelectPrevHostage() { + int start=0; + + do { + CurrentHostageIndex--; + if ( CurrentHostageIndex < 0 ) CurrentHostageIndex = MAX_HOSTAGES-1; + start++; + if ( start > MAX_HOSTAGES ) break; + } while ( !hostage_is_valid( CurrentHostageIndex ) ); + + if (hostage_is_valid( CurrentHostageIndex ) ) { + Cur_object_index = Hostages[CurrentHostageIndex].objnum; + } else { + CurrentHostageIndex =-1; + } + + return CurrentHostageIndex; +} + + +int SelectNextHostage() { + int start=0; + + do { + CurrentHostageIndex++; + if ( CurrentHostageIndex >= MAX_HOSTAGES ) CurrentHostageIndex = 0; + start++; + if ( start > MAX_HOSTAGES ) break; + } while ( !hostage_is_valid( CurrentHostageIndex ) ); + + if (hostage_is_valid( CurrentHostageIndex ) ) { + Cur_object_index = Hostages[CurrentHostageIndex].objnum; + } else { + CurrentHostageIndex =-1; + } + + return CurrentHostageIndex; +} + + +int SelectClosestHostage() { + int start=0; + + while ( !hostage_is_valid( CurrentHostageIndex ) ) { + CurrentHostageIndex++; + if ( CurrentHostageIndex >= MAX_HOSTAGES ) CurrentHostageIndex = 0; + start++; + if ( start > MAX_HOSTAGES ) break; + } + + if (hostage_is_valid( CurrentHostageIndex ) ) { + Cur_object_index = Hostages[CurrentHostageIndex].objnum; + } else { + CurrentHostageIndex =-1; + } + + return CurrentHostageIndex; +} + + +int PlaceHostage() { + int ctype,i; + vms_vector cur_object_loc; + + //update_due_to_new_segment(); + compute_segment_center(&cur_object_loc, Cursegp); + + ctype = -1; + for (i=0; i= N_hostage_types ) +//@@ Hostages[CurrentHostageIndex].type = 0; +//@@ +//@@ return 1; +//@@} +//@@ +//@@int SelectNextVclip() { +//@@ if (!hostage_is_valid( CurrentHostageIndex ) ) +//@@ return 0; +//@@ +//@@ Hostages[CurrentHostageIndex].type++; +//@@ if ( Hostages[CurrentHostageIndex].type >= N_hostage_types ) +//@@ Hostages[CurrentHostageIndex].type = 0; +//@@ +//@@ return 1; +//@@} + +int SelectNextFace() +{ + int start = Hostages[CurrentHostageIndex].vclip_num; + + if (!hostage_is_valid( CurrentHostageIndex ) ) + return 0; + + do { + Hostages[CurrentHostageIndex].vclip_num++; + if ( Hostages[CurrentHostageIndex].vclip_num >= MAX_HOSTAGES) + Hostages[CurrentHostageIndex].vclip_num = 0; + + if (Hostages[CurrentHostageIndex].vclip_num == start) + return 0; + + } while (Hostage_face_clip[Hostages[CurrentHostageIndex].vclip_num].num_frames == 0); + + return 1; +} + +int SelectPrevFace() +{ + int start = Hostages[CurrentHostageIndex].vclip_num; + + if (!hostage_is_valid( CurrentHostageIndex ) ) + return 0; + + do { + Hostages[CurrentHostageIndex].vclip_num--; + if ( Hostages[CurrentHostageIndex].vclip_num < 0) + Hostages[CurrentHostageIndex].vclip_num = MAX_HOSTAGES-1; + + if (Hostages[CurrentHostageIndex].vclip_num == start) + return 0; + + } while (Hostage_face_clip[Hostages[CurrentHostageIndex].vclip_num].num_frames == 0); + + return 1; +} + +int PlayHostageSound() { + int sound_num; + + if (!hostage_is_valid( CurrentHostageIndex ) ) + return 0; + + sound_num = Hostage_face_clip[Hostages[CurrentHostageIndex].vclip_num].sound_num; + + if ( sound_num > -1 ) { + digi_play_sample( sound_num, F1_0 ); + } + + return 1; +} + +//@@int find_next_hostage_sound() { +//@@ int start=0,n; +//@@ +//@@ n = Hostages[CurrentHostageIndex].sound_num; +//@@ do { +//@@ n++; +//@@ if ( n < SOUND_HOSTAGE_VOICES ) n = SOUND_HOSTAGE_VOICES+MAX_HOSTAGE_SOUNDS-1; +//@@ if ( n >= SOUND_HOSTAGE_VOICES+MAX_HOSTAGE_SOUNDS ) n = SOUND_HOSTAGE_VOICES; +//@@ start++; +//@@ if ( start > MAX_HOSTAGE_SOUNDS ) break; +//@@ } while ( Sounds[n] == NULL ); +//@@ +//@@ if ( Sounds[n] == NULL ) +//@@ Hostages[CurrentHostageIndex].sound_num = -1; +//@@ else { +//@@ Hostages[CurrentHostageIndex].sound_num = n; +//@@ PlayHostageSound(); +//@@ } +//@@ return 1; +//@@} +//@@ +//@@int find_prev_hostage_sound() { +//@@ int start=0,n; +//@@ +//@@ n = Hostages[CurrentHostageIndex].sound_num; +//@@ do { +//@@ n--; +//@@ if ( n < SOUND_HOSTAGE_VOICES ) n = SOUND_HOSTAGE_VOICES+MAX_HOSTAGE_SOUNDS-1; +//@@ if ( n >= SOUND_HOSTAGE_VOICES+MAX_HOSTAGE_SOUNDS ) n = SOUND_HOSTAGE_VOICES; +//@@ start++; +//@@ if ( start > MAX_HOSTAGE_SOUNDS ) break; +//@@ } while ( Sounds[n] == NULL ); +//@@ +//@@ if ( Sounds[n] == NULL ) +//@@ Hostages[CurrentHostageIndex].sound_num = -1; +//@@ else { +//@@ Hostages[CurrentHostageIndex].sound_num = n; +//@@ PlayHostageSound(); +//@@ } +//@@ return 1; +//@@} + + +//------------------------------------------------------------------------- +// Called from the editor... does one instance of the hostage dialog box +//------------------------------------------------------------------------- +int do_hostage_dialog() +{ + int i; + + // Only open 1 instance of this window... + if ( MainWindow != NULL ) return 0; + + // Close other windows + close_all_windows(); + + CurrentHostageIndex = 0; + SelectClosestHostage(); + + // Open a window with a quit button + MainWindow = ui_open_window( TMAPBOX_X+10, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG ); + QuitButton = ui_add_gadget_button( MainWindow, 20, 222, 48, 40, "Done", NULL ); + + ui_wprintf_at( MainWindow, 10, 32,"&Message:" ); + HostageText = ui_add_gadget_inputbox( MainWindow, 10, 50, HOSTAGE_MESSAGE_LEN, HOSTAGE_MESSAGE_LEN, HostageMessage ); + + // The little box the hostage vclip will play in. + HostageViewBox = ui_add_gadget_userbox( MainWindow,10, 90+10, 64, 64 ); + + // A bunch of buttons... + i = 90; +//@@ ui_add_gadget_button( MainWindow,155,i,70, 26, "<< Type", SelectPrevVclip ); +//@@ ui_add_gadget_button( MainWindow,155+70,i,70, 26, "Type >>", SelectNextVclip );i += 29; +//@@ ui_add_gadget_button( MainWindow,155,i,70, 26, "<< Sound", find_prev_hostage_sound ); +//@@ ui_add_gadget_button( MainWindow,155+70,i,70, 26, "Sound >>", find_next_hostage_sound );i += 29; + + ui_add_gadget_button( MainWindow,155,i,70, 26, "<< Face", SelectPrevFace ); + ui_add_gadget_button( MainWindow,155+70,i,70, 26, "Face >>", SelectNextFace );i += 29; + ui_add_gadget_button( MainWindow,155,i,140, 26, "Play sound", PlayHostageSound );i += 29; + ui_add_gadget_button( MainWindow,155,i,140, 26, "Next Hostage", SelectNextHostage ); i += 29; + ui_add_gadget_button( MainWindow,155,i,140, 26, "Prev Hostage", SelectPrevHostage ); i += 29; + ui_add_gadget_button( MainWindow,155,i,140, 26, "Compress All", CompressHostages ); i += 29; + ui_add_gadget_button( MainWindow,155,i,140, 26, "Delete", ObjectDelete ); i += 29; + ui_add_gadget_button( MainWindow,155,i,140, 26, "Create New", PlaceHostage ); i += 29; + + Time = timer_get_fixed_seconds(); + + LastHostageIndex = -2; // Set to some dummy value so everything works ok on the first frame. + +// if ( CurrentHostageIndex == -1 ) +// SelectNextHostage(); + + return 1; + +} + +void hostage_close_window() +{ + if ( MainWindow!=NULL ) { + ui_close_window( MainWindow ); + MainWindow = NULL; + } +} + +void do_hostage_window() +{ + fix DeltaTime, Temp; + + if ( MainWindow == NULL ) return; + + SelectClosestHostage(); + + //------------------------------------------------------------ + // Call the ui code.. + //------------------------------------------------------------ + ui_button_any_drawn = 0; + ui_window_do_gadgets(MainWindow); + + //------------------------------------------------------------ + // If we change objects, we need to reset the ui code for all + // of the radio buttons that control the ai mode. Also makes + // the current AI mode button be flagged as pressed down. + //------------------------------------------------------------ + if (LastHostageIndex != CurrentHostageIndex ) { + + if ( CurrentHostageIndex > -1 ) + strcpy( HostageText->text, Hostages[CurrentHostageIndex].text ); + else + strcpy(HostageText->text, " " ); + + HostageText->position = strlen(HostageText->text); + HostageText->oldposition = HostageText->position; + HostageText->status=1; + HostageText->first_time = 1; + + } + + //------------------------------------------------------------ + // If any of the radio buttons that control the mode are set, then + // update the cooresponding AI state. + //------------------------------------------------------------ + if ( CurrentHostageIndex > -1 ) + strcpy( Hostages[CurrentHostageIndex].text, HostageText->text ); + + //------------------------------------------------------------ + // A simple frame time counter for spinning the objects... + //------------------------------------------------------------ + Temp = timer_get_fixed_seconds(); + DeltaTime = Temp - Time; + Time = Temp; + + //------------------------------------------------------------ + // Redraw the object in the little 64x64 box + //------------------------------------------------------------ + if (CurrentHostageIndex > -1 ) { + int vclip_num; + + vclip_num = Hostages[CurrentHostageIndex].vclip_num; + + Assert(vclip_num != -1); + + gr_set_current_canvas( HostageViewBox->canvas ); + + if ( vclip_num > -1 ) { + vclip_play( &Hostage_face_clip[vclip_num], DeltaTime ); + } else { + gr_clear_canvas( CGREY ); + } + } else { + // no hostage, so just blank out + gr_set_current_canvas( HostageViewBox->canvas ); + gr_clear_canvas( CGREY ); + } + + //------------------------------------------------------------ + // If anything changes in the ui system, redraw all the text that + // identifies this robot. + //------------------------------------------------------------ + if (ui_button_any_drawn || (LastHostageIndex != CurrentHostageIndex) ) { + if ( CurrentHostageIndex > -1 ) { + ui_wprintf_at( MainWindow, 10, 15, "Hostage: %d Object: %d", CurrentHostageIndex, Hostages[CurrentHostageIndex].objnum ); + //@@ui_wprintf_at( MainWindow, 10, 73, "Type: %d Sound: %d ", Hostages[CurrentHostageIndex].type, Hostages[CurrentHostageIndex].sound_num ); + ui_wprintf_at( MainWindow, 10, 73, "Face: %d ", Hostages[CurrentHostageIndex].vclip_num); + } else { + ui_wprintf_at( MainWindow, 10, 15, "Hostage: none " ); + //@@ui_wprintf_at( MainWindow, 10, 73, "Type: Sound: " ); + ui_wprintf_at( MainWindow, 10, 73, "Face: " ); + } + Update_flags |= UF_WORLD_CHANGED; + } + + if ( QuitButton->pressed || (last_keypress==KEY_ESC)) { + hostage_close_window(); + return; + } + + LastHostageIndex = CurrentHostageIndex; +} + + + diff --git a/main/editor/ehostage.h b/main/editor/ehostage.h new file mode 100644 index 00000000..ac6cace1 --- /dev/null +++ b/main/editor/ehostage.h @@ -0,0 +1,48 @@ +/* +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/ehostage.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * . + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:35 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:13 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.2 1994/07/01 17:57:14 john + * First version of not-working hostage system + * + * + * Revision 1.1 1994/07/01 14:24:41 john + * Initial revision + * + * + */ + + + +#ifndef _EHOSTAGE_H +#define _EHOSTAGE_H + +extern int do_hostage_dialog(); +extern void hostage_close_window(); +extern void do_hostage_window(); + +#endif diff --git a/main/editor/elight.c b/main/editor/elight.c new file mode 100644 index 00000000..9559cdae --- /dev/null +++ b/main/editor/elight.c @@ -0,0 +1,404 @@ +/* +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/elight.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Editor lighting functions. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:55 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:16 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.21 1994/06/14 16:59:23 mike + * Fix references to tmap_num2, must strip off orientation bits. + * + * Revision 1.20 1994/05/31 12:31:57 mike + * fix bug in lighting -- WALL_IS_DOORWAY return value getting ignored, + * almost never recursively propagated light. + * + * Revision 1.19 1994/05/19 23:35:12 mike + * Support uv coordinates in range 0..1.0. + * + * Revision 1.18 1994/05/16 12:05:29 john + * Made texturemap light be a fix from 0 to 1. + * + * Revision 1.17 1994/05/14 18:00:38 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.16 1994/05/03 11:04:27 mike + * Add function to select edge. + * + * Revision 1.15 1994/04/20 17:29:11 yuan + * Fixed bug where tmaps above 256 don't light properly. + * (duh!) + * + * Revision 1.14 1994/03/22 14:20:46 yuan + * Made texture map 1 also cast light. (Cumulative with tmap_num2) + * + * Revision 1.13 1994/03/15 16:34:14 yuan + * Fixed bm loader (might have some changes in walls and switches) + * + * Revision 1.12 1994/02/22 18:55:10 yuan + * Ambient lighting "shines" on doors too! + * + * Revision 1.11 1994/02/17 12:05:55 matt + * Got rid of warnings + * + * Revision 1.10 1994/02/16 22:28:03 mike + * fix ambient lighting and smoothing. + * + * Revision 1.9 1994/02/14 12:05:42 mike + * change segment data structure. + * + * Revision 1.8 1994/01/26 17:27:45 yuan + * Still not perfected ambient lighting + * + * Revision 1.7 1994/01/25 17:58:08 yuan + * Added ambient lighting, and also added fixing bogus segments + * functions to the editor... (they don't work fully... need to + * check out seguvs.c + * + * Revision 1.6 1994/01/24 11:46:10 yuan + * *** empty log message *** + * + * Revision 1.5 1994/01/24 11:03:05 yuan + * Set lgiht maximum added... Changes are still in progress + * + * Revision 1.4 1994/01/18 19:16:07 yuan + * Added assign default to lighting pad. + * + * Revision 1.3 1993/12/17 12:26:00 mike + * Add functions for setting light values on whole segment at once. + * + * Revision 1.2 1993/12/16 16:56:12 mike + * Add new texture map lighting control functions. + * + * Revision 1.1 1993/12/16 13:21:50 mike + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: elight.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +//#include +//#include +//#include +//#include + +#include "inferno.h" +#include "segment.h" +#include "editor.h" +#include "seguvs.h" + +#include "wall.h" + +#include "textures.h" + +#include "fix.h" +#include "mono.h" +#include "error.h" +#include "kdefs.h" +#include "gameseg.h" + +#include "texmap.h" + +// ----------------------------------------------------------------------------- +// Return light intensity at an instance of a vertex on a side in a segment. +fix get_light_intensity(segment *segp, int sidenum, int vert) +{ + Assert(sidenum <= MAX_SIDES_PER_SEGMENT); + Assert(vert <= 3); + + return segp->sides[sidenum].uvls[vert].l; +} + +// ----------------------------------------------------------------------------- +// Set light intensity at a vertex, saturating in .5 to 15.5 +void set_light_intensity(segment *segp, int sidenum, int vert, fix intensity) +{ + Assert(sidenum <= MAX_SIDES_PER_SEGMENT); + Assert(vert <= 3); + + if (intensity < MIN_LIGHTING_VALUE) + intensity = MIN_LIGHTING_VALUE; + + if (intensity > MAX_LIGHTING_VALUE) + intensity = MAX_LIGHTING_VALUE; + + segp->sides[sidenum].uvls[vert].l = intensity; + + Update_flags |= UF_WORLD_CHANGED; +} + + +// ----------------------------------------------------------------------------- +// Add light intensity to a vertex, saturating in .5 to 15.5 +void add_light_intensity(segment *segp, int sidenum, int vert, fix intensity) +{ +// fix new_intensity; + + set_light_intensity(segp, sidenum, vert, segp->sides[sidenum].uvls[vert].l + intensity); +} + + +// ----------------------------------------------------------------------------- +// Recursively apply light to segments. +// If current side is a wall, apply light there. +// If not a wall, apply light to child through that wall. +// Notes: +// It is possible to enter a segment twice by taking different paths. It is easy +// to prevent this by maintaining a list of visited segments, but it is important +// to reach segments with the greatest light intensity. This can be done by doing +// a breadth-first-search, or by storing the applied intensity with a visited segment, +// and if the current intensity is brighter, then apply the difference between it and +// the previous intensity. +// Note that it is also possible to visit the original light-casting segment, for example +// going from segment 0 to 2, then from 2 to 0. This is peculiar and probably not +// desired, but not entirely invalid. 2 reflects some light back to 0. +void apply_light_intensity(segment *segp, int sidenum, fix intensity, int depth) +{ + int wid_result; + + if (intensity == 0) + return; + + wid_result = WALL_IS_DOORWAY(segp, sidenum); + if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) { + int v; + for (v=0; v<4; v++) // add light to this wall + add_light_intensity(segp, sidenum, v, intensity); + return; // we return because there is a wall here, and light does not shine through walls + } + + // No wall here, so apply light recursively + if (depth < 3) { + int s; + for (s=0; schildren[sidenum]], s, intensity/3, depth+1); + } + +} + +// ----------------------------------------------------------------------------- +// Top level recursive function for applying light. +// Calls apply_light_intensity. +// Uses light value on segp:sidenum (tmap_num2 defines light value) and applies +// the associated intensity to segp. It calls apply_light_intensity to apply intensity/3 +// to all neighbors. apply_light_intensity recursively calls itself to apply light to +// subsequent neighbors (and forming loops, see above). +void propagate_light_intensity(segment *segp, int sidenum) +{ + int v,s; + fix intensity; + short texmap; + + intensity = 0; + texmap = segp->sides[sidenum].tmap_num; + intensity += TmapInfo[texmap].lighting; + texmap = (segp->sides[sidenum].tmap_num2) & 0x3fff; + intensity += TmapInfo[texmap].lighting; + + if (intensity > 0) { + for (v=0; v<4; v++) + add_light_intensity(segp, sidenum, v, intensity); + + // Now, for all sides which are not the same as sidenum (the side casting the light), + // add a light value to them (if they have no children, ie, they have a wall there). + for (s=0; s= 4) + Curvert = 0; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ----------------------------------------------------------------------------- +int LightSelectNextEdge(void) +{ + Curedge++; + if (Curedge >= 4) + Curedge = 0; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ----------------------------------------------------------------------------- +// Copy intensity from current vertex to all other vertices on side. +int LightCopyIntensity(void) +{ + int v,intensity; + + intensity = get_light_intensity(Cursegp, Curside, Curvert); + + for (v=0; v<4; v++) + if (v != Curvert) + set_light_intensity(Cursegp, Curside, v, intensity); + + return 1; +} + +// ----------------------------------------------------------------------------- +// Copy intensity from current vertex to all other vertices on side. +int LightCopyIntensitySegment(void) +{ + int s,v,intensity; + + intensity = get_light_intensity(Cursegp, Curside, Curvert); + + for (s=0; s +#include +#include +#include +#include + +#include "inferno.h" +#include "segment.h" +#include "editor.h" + +#include "objpage.h" +#include "fix.h" +#include "mono.h" +#include "error.h" +#include "kdefs.h" +#include "object.h" +#include "polyobj.h" +#include "game.h" +#include "ai.h" +#include "bm.h" +#include "3d.h" // For g3_point_to_vec +#include "fvi.h" + +#include "powerup.h" +#include "fuelcen.h" +#include "hostage.h" +#include "medrobot.h" +#include "player.h" +#include "gameseg.h" + +#define OBJ_SCALE (F1_0/2) +#define OBJ_DEL_SIZE (F1_0/2) + +#define ROTATION_UNIT (4096/4) + +//segment *Cur_object_seg = -1; + +void show_objects_in_segment(segment *sp) +{ + short objid; + + mprintf((0,"Objects in segment #%i: ",sp-Segments)); + + objid = sp->objects; + while (objid != -1) { + mprintf((0,"%2i ",objid)); + objid = Objects[objid].next; + } + mprintf((0,"\n")); +} + +//returns the number of the first object in a segment, skipping the player +int get_first_object(segment *seg) +{ + int id; + + id = seg->objects; + + if (id == (ConsoleObject-Objects)) + id = Objects[id].next; + + return id; +} + +//returns the number of the next object in a segment, skipping the player +int get_next_object(segment *seg,int id) +{ + if (id==-1 || (id=Objects[id].next)==-1) + return get_first_object(seg); + + if (id == (ConsoleObject-Objects)) + return get_next_object(seg,id); + + return id; +} + + +//@@// ------------------------------------------------------------------------------------------------------ +//@@// this should be called whenever the current segment may have changed +//@@// If Cur_object_seg != Cursegp, then update various variables. +//@@// this used to be called update_due_to_new_segment() +//@@void ObjectUpdateCurrent(void) +//@@{ +//@@ if (Cur_object_seg != Cursegp) { +//@@ Cur_object_seg = Cursegp; +//@@ Cur_object_index = get_first_object(Cur_object_seg); +//@@ Update_flags |= UF_WORLD_CHANGED; +//@@ } +//@@ +//@@} + +// ------------------------------------------------------------------------------------ +int place_object(segment *segp, vms_vector *object_pos, int object_type) +{ + short objnum=0; + object *obj; + vms_matrix seg_matrix; + + med_extract_matrix_from_segment(segp,&seg_matrix); + + switch(ObjType[object_type]) { + + case OL_HOSTAGE: + + objnum = obj_create(OBJ_HOSTAGE, -1, + segp-Segments,object_pos,&seg_matrix,HOSTAGE_SIZE, + CT_NONE,MT_NONE,RT_HOSTAGE); + + if ( objnum < 0 ) + return 0; + + obj = &Objects[objnum]; + + // Fill in obj->id and other hostage info + hostage_init_info( objnum ); + + obj->control_type = CT_POWERUP; + + obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[ObjId[object_type]]; + obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time; + obj->rtype.vclip_info.framenum = 0; + + break; + + case OL_ROBOT: + + objnum = obj_create(OBJ_ROBOT,ObjId[object_type],segp-Segments,object_pos, + &seg_matrix,Polygon_models[Robot_info[ObjId[object_type]].model_num].rad, + CT_AI,MT_PHYSICS,RT_POLYOBJ); + + if ( objnum < 0 ) + return 0; + + obj = &Objects[objnum]; + + //Set polygon-object-specific data + + obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; + obj->rtype.pobj_info.subobj_flags = 0; + + //set Physics info + + obj->mtype.phys_info.mass = Robot_info[obj->id].mass; + obj->mtype.phys_info.drag = Robot_info[obj->id].drag; + + obj->mtype.phys_info.flags |= (PF_LEVELLING); + + obj->shields = Robot_info[obj->id].strength; + + { int hide_segment; + if (Markedsegp) + hide_segment = Markedsegp-Segments; + else + hide_segment = -1; + // robots which lunge forward to attack cannot have behavior type still. + if (Robot_info[obj->id].attack_type) + init_ai_object(obj-Objects, AIB_NORMAL, hide_segment); + else + init_ai_object(obj-Objects, AIB_STILL, hide_segment); + } + break; + + case OL_POWERUP: + + objnum = obj_create(OBJ_POWERUP,ObjId[object_type], + segp-Segments,object_pos,&seg_matrix,Powerup_info[ObjId[object_type]].size, + CT_POWERUP,MT_NONE,RT_POWERUP); + + if ( objnum < 0 ) + return 0; + + obj = &Objects[objnum]; + + //set powerup-specific data + + obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num; + obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames; + obj->rtype.vclip_info.framenum = 0; + + if (obj->id == POW_VULCAN_WEAPON) + obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT; + else + obj->ctype.powerup_info.count = 1; + + break; + + case OL_CLUTTER: + case OL_CONTROL_CENTER: + { + int obj_type,control_type; + + if (ObjType[object_type]==OL_CONTROL_CENTER) { + obj_type = OBJ_CNTRLCEN; + control_type = CT_CNTRLCEN; + } + else { + obj_type = OBJ_CLUTTER; + control_type = CT_NONE; + } + + objnum = obj_create(obj_type,object_type,segp-Segments,object_pos, + &seg_matrix,Polygon_models[ObjId[object_type]].rad, + control_type,MT_NONE,RT_POLYOBJ); + + if ( objnum < 0 ) + return 0; + + obj = &Objects[objnum]; + + obj->shields = ObjStrength[object_type]; + + //Set polygon-object-specific data + obj->shields = ObjStrength[object_type]; + obj->rtype.pobj_info.model_num = ObjId[object_type]; + obj->rtype.pobj_info.subobj_flags = 0; + + break; + } + + case OL_PLAYER: { + objnum = obj_create(OBJ_PLAYER,ObjId[object_type],segp-Segments,object_pos, + &seg_matrix,Polygon_models[Player_ship->model_num].rad, + CT_NONE,MT_PHYSICS,RT_POLYOBJ); + + if ( objnum < 0 ) + return 0; + + obj = &Objects[objnum]; + + //Set polygon-object-specific data + + obj->rtype.pobj_info.model_num = Player_ship->model_num; + obj->rtype.pobj_info.subobj_flags = 0; + //for (i=0;irtype.pobj_info.anim_angles[i]); + + //set Physics info + + vm_vec_zero(&obj->mtype.phys_info.velocity); + obj->mtype.phys_info.mass = Player_ship->mass; + obj->mtype.phys_info.drag = Player_ship->drag; + obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE; + obj->shields = i2f(100); + + break; + } + default: + break; + } + + Cur_object_index = objnum; + //Cur_object_seg = Cursegp; + + show_objects_in_segment(Cursegp); //mprintf the objects + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +// Count number of player objects, return value. +int compute_num_players(void) +{ + int i, count = 0; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].type == OBJ_PLAYER) + count++; + + return count; + +} + +int ObjectMakeCoop(void) +{ + Assert(Cur_object_index != -1); + Assert(Cur_object_index < MAX_OBJECTS); +// Assert(Objects[Cur_object_index.type == OBJ_PLAYER); + + if (Objects[Cur_object_index].type == OBJ_PLAYER ) { + Objects[Cur_object_index].type = OBJ_COOP; + editor_status("You just made a player object COOPERATIVE"); + } else + editor_status("This is not a player object"); + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +// Place current object at center of current segment. +int ObjectPlaceObject(void) +{ + int old_cur_object_index; + int rval; + + vms_vector cur_object_loc; + +#ifdef SHAREWARE + if (ObjType[Cur_robot_type] == OL_PLAYER) { + int num_players = compute_num_players(); + Assert(num_players <= MAX_PLAYERS); + if (num_players == MAX_PLAYERS) { + editor_status("Can't place player object. Already %i players.", MAX_PLAYERS); + return -1; + } + } +#endif + +#ifndef SHAREWARE + if (ObjType[Cur_robot_type] == OL_PLAYER) { + int num_players = compute_num_players(); + Assert(num_players <= MAX_MULTI_PLAYERS); + if (num_players > MAX_PLAYERS) + editor_status("You just placed a cooperative player object"); + if (num_players == MAX_MULTI_PLAYERS) { + editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS); + return -1; + } + } +#endif + + //update_due_to_new_segment(); + compute_segment_center(&cur_object_loc, Cursegp); + + old_cur_object_index = Cur_object_index; + rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type); + + if (old_cur_object_index != Cur_object_index) + Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1; + + return rval; + +} + +// ------------------------------------------------------------------------------------------------------ +// Place current object at center of current segment. +int ObjectPlaceObjectTmap(void) +{ + int rval, old_cur_object_index; + vms_vector cur_object_loc; + + //update_due_to_new_segment(); + compute_segment_center(&cur_object_loc, Cursegp); + + old_cur_object_index = Cur_object_index; + rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type); + + if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ)) + Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture; + else + editor_status("Unable to apply current texture map to this object."); + + return rval; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectSelectNextinSegment(void) +{ + int id; + segment *objsegp; + + + //update_due_to_new_segment(); + + //Assert(Cur_object_seg == Cursegp); + + if (Cur_object_index == -1) { + objsegp = Cursegp; + Cur_object_index = objsegp->objects; + } else { + objsegp = Cursegp; + if (Objects[Cur_object_index].segnum != Cursegp-Segments) + Cur_object_index = objsegp->objects; + } + + + //Debug: make sure current object is in current segment + for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next); + Assert(id == Cur_object_index); //should have found object + + // Select the next object, wrapping back to start if we are at the end of the linked list for this segment. + if (id != -1) + Cur_object_index = get_next_object(objsegp,Cur_object_index); + + //mprintf((0,"Cur_object_index == %i\n", Cur_object_index)); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; + +} + +//Moves to next object in the mine, skipping the player +int ObjectSelectNextInMine() +{ int i; + for (i=0;i= MAX_OBJECTS ) Cur_object_index= 0; + + if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) { + Cursegp = &Segments[Objects[Cur_object_index ].segnum]; + med_create_new_segment_from_cursegp(); + //Cur_object_seg = Cursegp; + return 1; + } + } + Cur_object_index = -1; + + Update_flags |= UF_WORLD_CHANGED; + + return 0; +} + +//Moves to next object in the mine, skipping the player +int ObjectSelectPrevInMine() +{ int i; + for (i=0;ipos,segnum,0); + if (result.centermask == 0) { + int fate; + fvi_info hit_info; + fvi_query fq; + + // See if the radius pokes through any wall. + fq.p0 = &obj->pos; + fq.startseg = obj->segnum; + fq.p1 = newpos; + fq.rad = obj->size; + fq.thisobjnum = -1; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + fate = find_vector_intersection(&fq,&hit_info); + + if (fate != HIT_WALL) { + if ( segnum != obj->segnum ) + obj_relink( obj-Objects, segnum); + obj->pos = *newpos; + return 0; + } //else + //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side)); + } + } + + return 1; + +} + + +// Return 0 if object is in expected segment, else return 1 +int verify_object_seg(object *objp, vms_vector *newpos) +{ + segmasks result = get_seg_masks(newpos, objp->segnum, objp->size); + + if (result.facemask == 0) + return 0; + else + return move_object_within_mine(objp, newpos); + +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMoveForward(void) +{ + object *obj; + vms_vector fvec; + vms_vector newpos; + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + obj = &Objects[Cur_object_index]; + + extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec); + vm_vec_normalize(&fvec); + + vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE)); + + if (!verify_object_seg(obj, &newpos)) + obj->pos = newpos; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMoveBack(void) +{ + object *obj; + vms_vector fvec; + vms_vector newpos; + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + obj = &Objects[Cur_object_index]; + + extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec); + vm_vec_normalize(&fvec); + + vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE)); + + if (!verify_object_seg(obj, &newpos)) + obj->pos = newpos; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMoveLeft(void) +{ + object *obj; + vms_vector rvec; + vms_vector newpos; + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + obj = &Objects[Cur_object_index]; + + extract_right_vector_from_segment(&Segments[obj->segnum], &rvec); + vm_vec_normalize(&rvec); + + vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE)); + + if (!verify_object_seg(obj, &newpos)) + obj->pos = newpos; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMoveRight(void) +{ + object *obj; + vms_vector rvec; + vms_vector newpos; + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + obj = &Objects[Cur_object_index]; + + extract_right_vector_from_segment(&Segments[obj->segnum], &rvec); + vm_vec_normalize(&rvec); + + vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE)); + + if (!verify_object_seg(obj, &newpos)) + obj->pos = newpos; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectSetDefault(void) +{ + //update_due_to_new_segment(); + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + + +// ------------------------------------------------------------------------------------------------------ +int ObjectMoveUp(void) +{ + object *obj; + vms_vector uvec; + vms_vector newpos; + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + obj = &Objects[Cur_object_index]; + + extract_up_vector_from_segment(&Segments[obj->segnum], &uvec); + vm_vec_normalize(&uvec); + + vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE)); + + if (!verify_object_seg(obj, &newpos)) + obj->pos = newpos; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMoveDown(void) +{ + object *obj; + vms_vector uvec; + vms_vector newpos; + + if (Cur_object_index == -1) { + editor_status("No current object, cannot move."); + return 1; + } + + obj = &Objects[Cur_object_index]; + + extract_up_vector_from_segment(&Segments[obj->segnum], &uvec); + vm_vec_normalize(&uvec); + + vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE)); + + if (!verify_object_seg(obj, &newpos)) + obj->pos = newpos; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMakeSmaller(void) +{ + fix cur_size; + + //update_due_to_new_segment(); + + cur_size = Objects[Cur_object_index].size; + + cur_size -= OBJ_DEL_SIZE; + if (cur_size < OBJ_DEL_SIZE) + cur_size = OBJ_DEL_SIZE; + + Objects[Cur_object_index].size = cur_size; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ +int ObjectMakeLarger(void) +{ + fix cur_size; + + //update_due_to_new_segment(); + + cur_size = Objects[Cur_object_index].size; + + cur_size += OBJ_DEL_SIZE; + + Objects[Cur_object_index].size = cur_size; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ------------------------------------------------------------------------------------------------------ + +int rotate_object(short objnum, int p, int b, int h) +{ + object *obj = &Objects[objnum]; + vms_angvec ang; + vms_matrix rotmat,tempm; + +// vm_extract_angles_matrix( &ang,&obj->orient); + +// ang.p += p; +// ang.b += b; +// ang.h += h; + + ang.p = p; + ang.b = b; + ang.h = h; + + vm_angles_2_matrix(&rotmat, &ang); + vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat); + obj->orient = tempm; + +// vm_angles_2_matrix(&obj->orient, &ang); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + + +void reset_object(short objnum) +{ + object *obj = &Objects[objnum]; + + med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient); + +} + + + +int ObjectResetObject() +{ + reset_object(Cur_object_index); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + + +int ObjectFlipObject() +{ + vms_matrix *m=&Objects[Cur_object_index].orient; + + vm_vec_negate(&m->uvec); + vm_vec_negate(&m->rvec); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);} +int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);} +int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);} +int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);} +int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);} +int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);} + +int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);} +int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);} +int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);} +int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);} +int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));} +int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));} + +// ----------------------------------------------------------------------------------------------------- +// Move object around based on clicks in 2d screen. +// Slide an object parallel to the 2d screen, to a point on a vector. +// The vector is defined by a point on the 2d screen and the eye. + +// V = vector from eye to 2d screen point. +// E = eye +// F = forward vector from eye +// O = 3-space location of object + +// D = depth of object given forward vector F +// = (OE dot norm(F)) + +// Must solve intersection of: +// E + tV ( equation of vector from eye through point on 2d screen) +// Fs + D ( equation of plane parallel to 2d screen, at depth D) +// = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0 +// +// FxEx + FyEy + FzEz - D +// t = - ---------------------- +// VxFx + VyFy + VzFz + + +//void print_vec(vms_vector *vec, char *text) +//{ +// mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z))); +//} +// +// void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F) +// { +// fix t, D; +// vms_vector Fnorm, Vnorm; +// fix num, denom; +// // float test_plane; +// +// print_vec(E, "E"); +// print_vec(V, "V"); +// print_vec(O, "O"); +// print_vec(F, "F"); +// +// Fnorm = *F; vm_vec_normalize(&Fnorm); +// Vnorm = *V; vm_vec_normalize(&Vnorm); +// +// D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z)); +// mprintf((0, "D = %9.5f\n", f2fl(D))); +// +// num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D; +// denom = vm_vec_dot(&Vnorm, &Fnorm); +// t = - num/denom; +// +// mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t))); +// +// result->x = E->x + fixmul(t, Vnorm.x); +// result->y = E->y + fixmul(t, Vnorm.y); +// result->z = E->z + fixmul(t, Vnorm.z); +// +// print_vec(result, "result"); +// +// // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D; +// // if (abs(test_plane) > .001) +// // printf("OOPS: test_plane = %9.5f\n", test_plane); +// } + +void move_object_to_position(int objnum, vms_vector *newpos) +{ + object *objp = &Objects[objnum]; + + segmasks result = get_seg_masks(newpos, objp->segnum, objp->size); + + if (result.facemask == 0) { + //mprintf((0, "Object #%i moved from (%7.3f %7.3f %7.3f) to (%7.3f %7.3f %7.3f)\n", objnum, f2fl(objp->pos.x), f2fl(objp->pos.y), f2fl(objp->pos.z), f2fl(newpos->x), f2fl(newpos->y), f2fl(newpos->z))); + objp->pos = *newpos; + } else { + if (verify_object_seg(&Objects[objnum], newpos)) { + int fate, count; + int viewer_segnum; + object temp_viewer_obj; + fvi_query fq; + fvi_info hit_info; + vms_vector last_outside_pos; + vms_vector last_inside_pos; + + temp_viewer_obj = *Viewer; + viewer_segnum = find_object_seg(&temp_viewer_obj); + temp_viewer_obj.segnum = viewer_segnum; + + // If the viewer is outside the mine, get him in the mine! + if (viewer_segnum == -1) { + // While outside mine, move towards object + count = 0; + while (viewer_segnum == -1) { + vms_vector temp_vec; + + //mprintf((0, "[towards %7.3f %7.3f %7.3f]\n", f2fl(temp_viewer_obj.pos.x), f2fl(temp_viewer_obj.pos.y), f2fl(temp_viewer_obj.pos.z))); + last_outside_pos = temp_viewer_obj.pos; + + vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos); + temp_viewer_obj.pos = temp_vec; + viewer_segnum = find_object_seg(&temp_viewer_obj); + temp_viewer_obj.segnum = viewer_segnum; + + if (count > 5) { + editor_status("Unable to move object, can't get viewer in mine. Aborting"); + return; + } + } + + count = 0; + // While inside mine, move away from object. + while (viewer_segnum != -1) { + + vms_vector temp_vec; + + //mprintf((0, "[away %7.3f %7.3f %7.3f]\n", f2fl(temp_viewer_obj.pos.x), f2fl(temp_viewer_obj.pos.y), f2fl(temp_viewer_obj.pos.z))); + last_inside_pos = temp_viewer_obj.pos; + + vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos); + temp_viewer_obj.pos = temp_vec; + update_object_seg(&temp_viewer_obj); + viewer_segnum = find_object_seg(&temp_viewer_obj); + temp_viewer_obj.segnum = viewer_segnum; + + if (count > 5) { + editor_status("Unable to move object, can't get viewer back out of mine. Aborting"); + return; + } + } + } + + fq.p0 = &temp_viewer_obj.pos; + fq.startseg = temp_viewer_obj.segnum; + fq.p1 = newpos; + fq.rad = temp_viewer_obj.size; + fq.thisobjnum = -1; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + fate = find_vector_intersection(&fq,&hit_info); + if (fate == HIT_WALL) { + int new_segnum; + + //mprintf((0, "Hit wall seg:side = %i:%i, point = (%7.3f %7.3f %7.3f)\n", hit_info.hit_seg, hit_info.hit_side, f2fl(hit_info.hit_pnt.x), f2fl(hit_info.hit_pnt.y), f2fl(hit_info.hit_pnt.z))); + objp->pos = hit_info.hit_pnt; + new_segnum = find_object_seg(objp); + Assert(new_segnum != -1); + obj_relink(objp-Objects, new_segnum); + //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum)); + } else { + editor_status("Attempted to move object out of mine. Object not moved."); + //mprintf((0,"Attempted to move object out of mine. Object not moved.")); + } + } + } + + Update_flags |= UF_WORLD_CHANGED; +} + +void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance) +{ + vms_vector result; + + vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance); + + move_object_to_position(Cur_object_index, &result); + +} + +void move_object_to_mouse_click_delta(fix delta_distance) +{ + short xcrd,ycrd; + vms_vector vec_through_screen; + + if (Cur_object_index == -1) { + editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!"); + return; + } + + xcrd = GameViewBox->b1_drag_x1; + ycrd = GameViewBox->b1_drag_y1; + + med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd); + + //mprintf((0, "Mouse click at %i %i, vector = %7.3f %7.3f %7.3f\n", xcrd, ycrd, f2fl(vec_through_screen.x), f2fl(vec_through_screen.y), f2fl(vec_through_screen.z))); + + move_object_to_vector(&vec_through_screen, delta_distance); + +} + +void move_object_to_mouse_click(void) +{ + move_object_to_mouse_click_delta(0); +} + +int ObjectMoveNearer(void) +{ + vms_vector result; + + if (Cur_object_index == -1) { + editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!"); + return 1; + } + +// move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye + + vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos); + vm_vec_normalize(&result); + move_object_to_vector(&result, -4*F1_0); + + return 1; +} + +int ObjectMoveFurther(void) +{ + vms_vector result; + + if (Cur_object_index == -1) { + editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!"); + return 1; + } + +// move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye + + vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos); + vm_vec_normalize(&result); + move_object_to_vector(&result, 4*F1_0); + + return 1; +} + diff --git a/main/editor/eobject.h b/main/editor/eobject.h new file mode 100644 index 00000000..a7fb4c7f --- /dev/null +++ b/main/editor/eobject.h @@ -0,0 +1,64 @@ +/* +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/eobject.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Header for eobject.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:35 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:30 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.5 1994/09/15 22:57:46 matt + * Made new objects be oriented to their segment + * Added keypad function to flip an object upside-down + * + * Revision 1.4 1994/08/25 21:57:23 mike + * Prototype ObjectSelectPrevInMine, and probably wrote it too, though not in this file. + * + * Revision 1.3 1994/08/05 18:17:48 matt + * Made object rotation have 4x resolution, and SHIFT+rotate do old resolution. + * + * Revision 1.2 1994/05/14 18:00:59 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.1 1994/05/14 17:36:30 matt + * Initial revision + * + * + */ + + + +#ifndef _EOBJECT_H +#define _EOBJECT_H + +int ObjectSelectNextInMine(void); +int ObjectSelectPrevInMine(void); + +int ObjectDecreaseBankBig(); +int ObjectIncreaseBankBig(); +int ObjectDecreasePitchBig(); +int ObjectIncreasePitchBig(); +int ObjectDecreaseHeadingBig(); +int ObjectIncreaseHeadingBig(); +int ObjectFlipObject(); + +#endif diff --git a/main/editor/eswitch.c b/main/editor/eswitch.c new file mode 100644 index 00000000..c6b96e98 --- /dev/null +++ b/main/editor/eswitch.c @@ -0,0 +1,635 @@ +/* +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/eswitch.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Editor switch functions. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:03 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:18 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.33 1995/01/14 19:18:04 john + * First version of object paging. + * + * Revision 1.32 1994/11/27 23:18:01 matt + * Made changes for new mprintf calling convention + * + * Revision 1.31 1994/11/07 10:55:42 yuan + * *** empty log message *** + * + * Revision 1.30 1994/10/13 13:15:06 yuan + * Fixed trigger removal bug. + * + * Revision 1.29 1994/10/06 21:24:16 matt + * Added switch for exit to secret level + * + * Revision 1.28 1994/09/29 17:06:10 matt + * Took out references to obsolete external triggers + * + * Revision 1.27 1994/09/28 13:40:34 yuan + * Fixed control center trigger bug. + * + * Revision 1.26 1994/09/26 16:25:04 yuan + * Only allow one binding of each matcen . + * + * Revision 1.25 1994/09/24 17:10:19 yuan + * Added Matcen triggers. + * + * Revision 1.24 1994/09/20 18:23:58 yuan + * Killed the BOGIFYING WALL DRAGON... + * + * There was a problem with triggers being created that had bogus + * pointers back to their segments. + * + * Revision 1.23 1994/08/25 21:56:33 mike + * IS_CHILD stuff. + * + * Revision 1.22 1994/08/15 18:06:54 yuan + * Added external trigger. + * + * Revision 1.21 1994/07/22 17:18:47 yuan + * Working on dialog box for refuel/repair/material/control centers. + * + * Revision 1.20 1994/07/06 10:55:55 john + * New structures for hostages. + * + * Revision 1.19 1994/07/01 16:36:20 yuan + * Working on triggers that aren't always on. + * + * Revision 1.18 1994/06/21 18:50:14 john + * Made ESC key exit dialog. + * + * Revision 1.17 1994/06/20 22:30:36 yuan + * Fixed crazy runaway trigger bug that Adam found + * + * Revision 1.16 1994/05/31 10:03:48 yuan + * Fixed compiler warnings... + * + * + * Revision 1.15 1994/05/30 20:22:30 yuan + * New triggers. + * + * Revision 1.14 1994/05/27 12:33:50 yuan + * Fixed some bugs when adding trigger. + * + * Revision 1.13 1994/05/27 10:34:29 yuan + * Added new Dialog boxes for Walls and Triggers. + * + * Revision 1.12 1994/05/25 18:15:02 yuan + * Fixed make warnings to save 10 cents! + * + * Revision 1.11 1994/05/25 18:08:03 yuan + * Revamping walls and triggers interface. + * Wall interface complete, but triggers are still in progress. + * + * Revision 1.10 1994/04/29 15:05:50 yuan + * Trigger/Link removing stuff still needs to be fixed. + * + * Revision 1.9 1994/04/28 23:25:34 yuan + * Obliterated warnings. + * + * Revision 1.8 1994/04/28 18:08:06 yuan + * Fixed trigger bug. + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: eswitch.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include + +#include "inferno.h" +#include "editor.h" +#include "eswitch.h" +#include "segment.h" +#include "error.h" +#include "gameseg.h" +#include "mono.h" +#include "wall.h" +#include "medwall.h" + +#include "screens.h" + +#include "textures.h" +#include "texmerge.h" +#include "medrobot.h" +#include "timer.h" +#include "key.h" +#include "ehostage.h" +#include "centers.h" +#include "piggy.h" + +//------------------------------------------------------------------------- +// Variables for this module... +//------------------------------------------------------------------------- +#define NUM_TRIGGER_FLAGS 10 + +static UI_WINDOW *MainWindow = NULL; +static UI_GADGET_USERBOX *WallViewBox; +static UI_GADGET_BUTTON *QuitButton; +static UI_GADGET_CHECKBOX *TriggerFlag[NUM_TRIGGER_FLAGS]; + +static int old_trigger_num; + +//----------------------------------------------------------------- +// Adds a trigger to wall, and returns the trigger number. +// If there is a trigger already present, it returns the trigger number. (To be replaced) +int add_trigger(segment *seg, short side) +{ + int trigger_num = Num_triggers; + int wall_num = seg->sides[side].wall_num; + + Assert(trigger_num < MAX_TRIGGERS); + if (trigger_num>=MAX_TRIGGERS) return -1; + + if (wall_num == -1) { + wall_add_to_markedside(WALL_OPEN); + wall_num = seg->sides[side].wall_num; + Walls[wall_num].trigger = trigger_num; + + // Set default values first time trigger is added + Triggers[trigger_num].flags = 0; + Triggers[trigger_num].value = F1_0*5; + Triggers[trigger_num].num_links = 0; + Triggers[trigger_num].flags &= TRIGGER_ON; + + Num_triggers++; + return trigger_num; + } else { + if (Walls[wall_num].trigger != -1) + return Walls[wall_num].trigger; + + // Create new trigger. + Walls[wall_num].trigger = trigger_num; + + // Set default values first time trigger is added + Triggers[trigger_num].flags = 0; + Triggers[trigger_num].value = F1_0*5; + Triggers[trigger_num].num_links = 0; + Triggers[trigger_num].flags &= TRIGGER_ON; + + Num_triggers++; + return trigger_num; + } +} + +//----------------------------------------------------------------- +// Adds a specific trigger flag to Markedsegp/Markedside if it is possible. +// Automatically adds flag to Connectside if possible unless it is a control trigger. +// Returns 1 if trigger flag added. +// Returns 0 if trigger flag cannot be added. +int trigger_add_to_Markedside(short flag) { + int trigger_num; //, ctrigger_num; + + if (!Markedsegp) { + editor_status("No Markedside."); + return 0; + } + + // If no child on Markedside return + if (!IS_CHILD(Markedsegp->children[Markedside])) return 0; + + trigger_num = add_trigger(Markedsegp, Markedside); + + if (trigger_num == -1) { + editor_status("Cannot add trigger at Markedside."); + return 0; + } + + Triggers[trigger_num].flags |= flag; + + return 1; +} + +int trigger_remove_flag_from_Markedside(short flag) { + int trigger_num; //, ctrigger_num; + int wall_num; + + if (!Markedsegp) { + editor_status("No Markedside."); + return 0; + } + + // If no child on Markedside return + if (!IS_CHILD(Markedsegp->children[Markedside])) return 0; + + // If no wall just return + wall_num = Markedsegp->sides[Markedside].wall_num; + if (wall_num == -1) return 0; + + trigger_num = Walls[wall_num].trigger; + + // If flag is already cleared, then don't change anything. + if ( trigger_num == -1 ) { + editor_status("No trigger at Markedside."); + return 0; + } + + if (!Triggers[trigger_num].flags & flag) + return 1; + + Triggers[trigger_num].flags &= ~flag; + + return 1; +} + + +int bind_matcen_to_trigger() { + + int wall_num, trigger_num, link_num; + int i; + + if (!Markedsegp) { + editor_status("No marked segment."); + return 0; + } + + wall_num = Markedsegp->sides[Markedside].wall_num; + if (wall_num == -1) { + editor_status("No wall at Markedside."); + return 0; + } + + trigger_num = Walls[wall_num].trigger; + + if (trigger_num == -1) { + editor_status("No trigger at Markedside."); + return 0; + } + + if (!(Cursegp->special & SEGMENT_IS_ROBOTMAKER)) { + editor_status("No Matcen at Cursegp."); + return 0; + } + + link_num = Triggers[trigger_num].num_links; + for (i=0;isides[Markedside].wall_num; + if (wall_num == -1) { + editor_status("No wall at Markedside."); + return 0; + } + + trigger_num = Walls[wall_num].trigger; + + if (trigger_num == -1) { + editor_status("No trigger at Markedside."); + return 0; + } + + if (Cursegp->sides[Curside].wall_num == -1) { + editor_status("No wall at Curside."); + return 0; + } + + if ((Cursegp==Markedsegp) && (Curside==Markedside)) { + editor_status("Cannot bind wall to itself."); + return 0; + } + + link_num = Triggers[trigger_num].num_links; + for (i=0;isides[side].wall_num == -1) { + mprintf((0, "Can't remove trigger from wall_num -1\n")); + return 0; + } + + trigger_num = Walls[seg->sides[side].wall_num].trigger; + + if (trigger_num != -1) { + Walls[seg->sides[side].wall_num].trigger = -1; + for (t=trigger_num;t trigger_num) + Walls[w].trigger--; + } + + Num_triggers--; + for (t=0;tsides[side].wall_num].trigger > trigger_num) + Walls[seg->sides[side].wall_num].trigger--; + + return 1; + } + + editor_status("No trigger to remove"); + return 0; +} + + +int add_trigger_control() +{ + trigger_add_to_Markedside(TRIGGER_CONTROL_DOORS); + Update_flags = UF_WORLD_CHANGED; + return 1; +} + +int trigger_remove() +{ + remove_trigger(Markedsegp, Markedside); + Update_flags = UF_WORLD_CHANGED; + return 1; +} + +int trigger_turn_all_ON() +{ + int t; + + for (t=0;tsides[Markedside].wall_num; + if (Markedwall != -1) + trigger_num = Walls[Markedwall].trigger; + else trigger_num = -1; + + if (old_trigger_num != trigger_num ) { + for ( i=0; i < NUM_TRIGGER_FLAGS; i++ ) { + TriggerFlag[i]->flag = 0; // Tells ui that this button isn't checked + TriggerFlag[i]->status = 1; // Tells ui to redraw button + } + + if (trigger_num != -1) { + if (Triggers[trigger_num].flags & TRIGGER_CONTROL_DOORS) + TriggerFlag[0]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_SHIELD_DAMAGE) + TriggerFlag[1]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_ENERGY_DRAIN) + TriggerFlag[2]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_EXIT) + TriggerFlag[3]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_ONE_SHOT) + TriggerFlag[4]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_ILLUSION_ON) + TriggerFlag[5]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_ILLUSION_OFF) + TriggerFlag[6]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_ON) + TriggerFlag[7]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_MATCEN) + TriggerFlag[8]->flag = 1; + if (Triggers[trigger_num].flags & TRIGGER_SECRET_EXIT) + TriggerFlag[9]->flag = 1; + } + } + + //------------------------------------------------------------ + // If any of the checkboxes that control the wallflags are set, then + // update the cooresponding wall flag. + //------------------------------------------------------------ + if (IS_CHILD(Markedsegp->children[Markedside])) { + if (TriggerFlag[0]->flag == 1) + trigger_add_to_Markedside(TRIGGER_CONTROL_DOORS); + else + trigger_remove_flag_from_Markedside(TRIGGER_CONTROL_DOORS); + if (TriggerFlag[1]->flag == 1) + trigger_add_to_Markedside(TRIGGER_SHIELD_DAMAGE); + else + trigger_remove_flag_from_Markedside(TRIGGER_SHIELD_DAMAGE); + if (TriggerFlag[2]->flag == 1) + trigger_add_to_Markedside(TRIGGER_ENERGY_DRAIN); + else + trigger_remove_flag_from_Markedside(TRIGGER_ENERGY_DRAIN); + if (TriggerFlag[3]->flag == 1) + trigger_add_to_Markedside(TRIGGER_EXIT); + else + trigger_remove_flag_from_Markedside(TRIGGER_EXIT); + if (TriggerFlag[4]->flag == 1) + trigger_add_to_Markedside(TRIGGER_ONE_SHOT); + else + trigger_remove_flag_from_Markedside(TRIGGER_ONE_SHOT); + if (TriggerFlag[5]->flag == 1) + trigger_add_to_Markedside(TRIGGER_ILLUSION_ON); + else + trigger_remove_flag_from_Markedside(TRIGGER_ILLUSION_ON); + if (TriggerFlag[6]->flag == 1) + trigger_add_to_Markedside(TRIGGER_ILLUSION_OFF); + else + trigger_remove_flag_from_Markedside(TRIGGER_ILLUSION_OFF); + if (TriggerFlag[7]->flag == 1) + trigger_add_to_Markedside(TRIGGER_ON); + else + trigger_remove_flag_from_Markedside(TRIGGER_ON); + + if (TriggerFlag[8]->flag == 1) + trigger_add_to_Markedside(TRIGGER_MATCEN); + else + trigger_remove_flag_from_Markedside(TRIGGER_MATCEN); + + if (TriggerFlag[9]->flag == 1) + trigger_add_to_Markedside(TRIGGER_SECRET_EXIT); + else + trigger_remove_flag_from_Markedside(TRIGGER_SECRET_EXIT); + + } else + for ( i=0; i < NUM_TRIGGER_FLAGS; i++ ) + if (TriggerFlag[i]->flag == 1) { + TriggerFlag[i]->flag = 0; // Tells ui that this button isn't checked + TriggerFlag[i]->status = 1; // Tells ui to redraw button + } + + //------------------------------------------------------------ + // Draw the wall in the little 64x64 box + //------------------------------------------------------------ + gr_set_current_canvas( WallViewBox->canvas ); + + if ((Markedsegp->sides[Markedside].wall_num == -1) || (Walls[Markedsegp->sides[Markedside].wall_num].trigger) == -1) + gr_clear_canvas( CBLACK ); + else { + if (Markedsegp->sides[Markedside].tmap_num2 > 0) { + gr_ubitmap(0,0, texmerge_get_cached_bitmap( Markedsegp->sides[Markedside].tmap_num, Markedsegp->sides[Markedside].tmap_num2)); + } else { + if (Markedsegp->sides[Markedside].tmap_num > 0) { + PIGGY_PAGE_IN(Textures[Markedsegp->sides[Markedside].tmap_num]); + gr_ubitmap(0,0, &GameBitmaps[Textures[Markedsegp->sides[Markedside].tmap_num].index]); + } else + gr_clear_canvas( CGREY ); + } + } + + //------------------------------------------------------------ + // If anything changes in the ui system, redraw all the text that + // identifies this robot. + //------------------------------------------------------------ + if (ui_button_any_drawn || (old_trigger_num != trigger_num) ) { + if ( Markedsegp->sides[Markedside].wall_num > -1 ) { + ui_wprintf_at( MainWindow, 12, 6, "Trigger: %d ", trigger_num); + } else { + ui_wprintf_at( MainWindow, 12, 6, "Trigger: none "); + } + Update_flags |= UF_WORLD_CHANGED; + } + + if ( QuitButton->pressed || (last_keypress==KEY_ESC)) { + close_trigger_window(); + return; + } + + old_trigger_num = trigger_num; +} + + + + + diff --git a/main/editor/eswitch.h b/main/editor/eswitch.h new file mode 100644 index 00000000..4e99ecfe --- /dev/null +++ b/main/editor/eswitch.h @@ -0,0 +1,69 @@ +/* +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/eswitch.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Headers for switch adding functions + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:35 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:40 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.6 1994/05/30 20:22:35 yuan + * New triggers. + * + * Revision 1.5 1994/05/27 10:34:35 yuan + * Added new Dialog boxes for Walls and Triggers. + * + * Revision 1.4 1994/05/25 18:08:39 yuan + * Revamping walls and triggers interface. + * Wall interface complete, but triggers are still in progress. + * + * Revision 1.3 1994/04/28 23:46:56 yuan + * Added prototype for remove_trigger. + * + * Revision 1.2 1994/03/15 16:34:20 yuan + * Fixed bm loader (might have some changes in walls and switches) + * + * Revision 1.1 1994/03/10 14:49:03 yuan + * Initial revision + * + * + */ + +#ifndef _ESWITCH_H +#define _ESWITCH_H + +#include "inferno.h" +#include "segment.h" +#include "switch.h" + +extern int bind_wall_to_trigger(); + +extern int trigger_remove(); + +extern int remove_trigger(segment *seg, short side); + +extern void close_trigger_window(); + +extern void do_trigger_window(); + +#endif + diff --git a/main/editor/fixseg.c b/main/editor/fixseg.c new file mode 100644 index 00000000..e4414118 --- /dev/null +++ b/main/editor/fixseg.c @@ -0,0 +1,244 @@ +/* +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/fixseg.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions to make faces planar and probably other things. + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 2003/03/09 06:34:09 donut + * change byte typedef to sbyte to avoid conflict with win32 byte which is unsigned + * + * Revision 1.1.1.1 1999/06/14 22:03:05 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:36:25 john + * Version 2.0. Ansi-fied. + * + * Revision 1.7 1994/11/27 23:18:01 matt + * Made changes for new mprintf calling convention + * + * Revision 1.6 1994/11/17 14:48:00 mike + * validation functions moved from editor to game. + * + * Revision 1.5 1994/08/04 19:13:26 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.4 1994/02/10 15:36:31 matt + * Various changes to make editor compile out. + * + * Revision 1.3 1993/12/03 18:45:09 mike + * initial stuff. + * + * Revision 1.2 1993/11/30 17:05:09 mike + * Added part of code to make a side planar. + * + * Revision 1.1 1993/11/30 10:05:36 mike + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: fixseg.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#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 "gameseg.h" + +#define SWAP(a,b) {temp = (a); (a) = (b); (b) = temp;} + +// ----------------------------------------------------------------------------------------------------------------- +// Gauss-Jordan elimination solution of a system of linear equations. +// a[1..n][1..n] is the input matrix. b[1..n][1..m] is input containing the m right-hand side vectors. +// On output, a is replaced by its matrix inverse and b is replaced by the corresponding set of solution vectors. +void gaussj(fix **a, int n, fix **b, int m) +{ + int indxc[4], indxr[4], ipiv[4]; + int i, icol=0, irow=0, j, k, l, ll; + fix big, dum, pivinv, temp; + + if (n > 4) { + mprintf((0,"Error -- array too large in gaussj.\n")); + Int3(); + } + + for (j=1; j<=n; j++) + ipiv[j] = 0; + + for (i=1; i<=n; i++) { + big = 0; + for (j=1; j<=n; j++) + if (ipiv[j] != 1) + for (k=1; k<=n; k++) { + if (ipiv[k] == 0) { + if (abs(a[j][k]) >= big) { + big = abs(a[j][k]); + irow = j; + icol = k; + } + } else if (ipiv[k] > 1) { + mprintf((0,"Error: Singular matrix-1\n")); + Int3(); + } + } + + ++(ipiv[icol]); + + // We now have the pivot element, so we interchange rows, if needed, to put the pivot + // element on the diagonal. The columns are not physically interchanged, only relabeled: + // indxc[i], the column of the ith pivot element, is the ith column that is reduced, while + // indxr[i] is the row in which that pivot element was originally located. If indxr[i] != + // indxc[i] there is an implied column interchange. With this form of bookkeeping, the + // solution b's will end up in the correct order, and the inverse matrix will be scrambled + // by columns. + + if (irow != icol) { + for (l=1; l<=n; l++) + SWAP(a[irow][l], a[icol][l]); + for (l=1; l<=m; l++) + SWAP(b[irow][l], b[icol][l]); + } + + indxr[i] = irow; + indxc[i] = icol; + if (a[icol][icol] == 0) { + mprintf((0,"Error: Singular matrix-2\n")); + Int3(); + } + pivinv = fixdiv(F1_0, a[icol][icol]); + a[icol][icol] = F1_0; + + for (l=1; l<=n; l++) + a[icol][l] = fixmul(a[icol][l], pivinv); + for (l=1; l<=m; l++) + b[icol][l] = fixmul(b[icol][l], pivinv); + + for (ll=1; ll<=n; ll++) + if (ll != icol) { + dum = a[ll][icol]; + a[ll][icol] = 0; + for (l=1; l<=n; l++) + a[ll][l] -= a[icol][l]*dum; + for (l=1; l<=m; l++) + b[ll][l] -= b[icol][l]*dum; + } + } + + // This is the end of the main loop over columns of the reduction. It only remains to unscramble + // the solution in view of the column interchanges. We do this by interchanging pairs of + // columns in the reverse order that the permutation was built up. + for (l=n; l>=1; l--) { + if (indxr[l] != indxc[l]) + for (k=1; k<=n; k++) + SWAP(a[k][indxr[l]], a[k][indxc[l]]); + } + +} + + +// ----------------------------------------------------------------------------------------------------------------- +// Return true if side is planar, else return false. +int side_is_planar_p(segment *sp, int side) +{ + sbyte *vp; + vms_vector *v0,*v1,*v2,*v3; + vms_vector va,vb; + + vp = Side_to_verts[side]; + v0 = &Vertices[sp->verts[vp[0]]]; + v1 = &Vertices[sp->verts[vp[1]]]; + v2 = &Vertices[sp->verts[vp[2]]]; + v3 = &Vertices[sp->verts[vp[3]]]; + + vm_vec_normalize(vm_vec_normal(&va,v0,v1,v2)); + vm_vec_normalize(vm_vec_normal(&vb,v0,v2,v3)); + + // If the two vectors are very close to being the same, then generate one quad, else generate two triangles. + return (vm_vec_dist(&va,&vb) < F1_0/1000); +} + +// ------------------------------------------------------------------------------------------------- +// Return coordinates of a vertex which is vertex v moved so that all sides of which it is a part become planar. +void compute_planar_vert(segment *sp, int side, int v, vms_vector *vp) +{ + if ((sp) && (side > -3)) + *vp = Vertices[v]; +} + +// ------------------------------------------------------------------------------------------------- +// Making Cursegp:Curside planar. +// If already planar, return. +// for each vertex v on side, not part of another segment +// choose the vertex v which can be moved to make all sides of which it is a part planar, minimizing distance moved +// if there is no vertex v on side, not part of another segment, give up in disgust +// Return value: +// 0 curside made planar (or already was) +// 1 did not make curside planar +int make_curside_planar(void) +{ + int v; + sbyte *vp; + vms_vector planar_verts[4]; // store coordinates of up to 4 vertices which will make Curside planar, corresponding to each of 4 vertices on side + int present_verts[4]; // set to 1 if vertex is present + + if (side_is_planar_p(Cursegp, Curside)) + return 0; + + // Look at all vertices in side to find a free one. + for (v=0; v<4; v++) + present_verts[v] = 0; + + vp = Side_to_verts[Curside]; + + for (v=0; v<4; v++) { + int v1 = vp[v]; // absolute vertex id + if (is_free_vertex(Cursegp->verts[v1])) { + compute_planar_vert(Cursegp, Curside, Cursegp->verts[v1], &planar_verts[v]); + present_verts[v] = 1; + } + } + + // Now, for each v for which present_verts[v] == 1, there is a vector (point) in planar_verts[v]. + // See which one is closest to the plane defined by the other three points. + // Nah...just use the first one we find. + for (v=0; v<4; v++) + if (present_verts[v]) { + med_set_vertex(vp[v],&planar_verts[v]); + validate_segment(Cursegp); + // -- should propagate tmaps to segments or something here... + + return 0; + } + // We tried, but we failed, to make Curside planer. + return 1; +} + diff --git a/main/editor/func.c b/main/editor/func.c new file mode 100644 index 00000000..a73e8c7c --- /dev/null +++ b/main/editor/func.c @@ -0,0 +1,128 @@ +/* +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/func.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * . + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:05 donut + * Import of d1x 1.37 source. + * + * Revision 1.1 1994/11/21 14:13:17 matt + * Initial revision + * + * Revision 1.1 1993/11/15 12:28:17 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: func.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include + +#include "func.h" + +#define MAX_PARAMS 10 + +static FUNCTION * func_table = NULL; +static int func_size = 0; +static int initialized = 0; +static int func_params[MAX_PARAMS]; + +int func_howmany() +{ + return func_size; +} + +void func_init( FUNCTION * funtable, int size ) +{ + if (!initialized) + { + initialized = 1; + func_table = funtable; + func_size = size; + atexit( func_close ); + } +} + + +void func_close() +{ + if (initialized) + { + initialized = 0; + func_table = NULL; + func_size = 0; + } +} + +int (*func_get( char * name, int * numparams ))(void) +{ + int i; + + for (i=0; inext equal itself error. + * + * Revision 1.39 1994/04/18 17:15:13 yuan + * Added error checking for select prev, and next group. + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: group.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + + +#include +#include + +#include "mono.h" +#include "gr.h" +#include "nocfile.h" +#include "ui.h" + +#include "inferno.h" +#include "segment.h" +#include "editor/editor.h" +#include "error.h" +#include "gamemine.h" +#include "gameseg.h" + +#include "bm.h" // For MAX_TEXTURES. +#include "textures.h" +#include "hash.h" +#include "fuelcen.h" + +#include "medwall.h" + +void validate_selected_segments(void); + +struct { + int fileinfo_version; + int fileinfo_sizeof; +} group_top_fileinfo; // Should be same as first two fields below... + +struct { + int fileinfo_version; + int fileinfo_sizeof; + int header_offset; // Stuff common to game & editor + int header_size; + int editor_offset; // Editor specific stuff + int editor_size; + int vertex_offset; + int vertex_howmany; + int vertex_sizeof; + int segment_offset; + int segment_howmany; + int segment_sizeof; + int texture_offset; + int texture_howmany; + int texture_sizeof; +} group_fileinfo; + +struct { + int num_vertices; + int num_segments; +} group_header; + +struct { + int current_seg; + int newsegment_offset; + int newsegment_size; + int Groupsegp; + int Groupside; +} group_editor; + +group GroupList[MAX_GROUPS+1]; +segment *Groupsegp[MAX_GROUPS+1]; +int Groupside[MAX_GROUPS+1]; +int Group_orientation[MAX_GROUPS+1]; +int current_group=-1; +int num_groups=0; + +extern void validate_segment_side(segment *sp, int sidenum); + +// -- void swap_negate_columns(vms_matrix *rotmat, int col1, int col2) +// -- { +// -- fix col1_1,col1_2,col1_3; +// -- fix col2_1,col2_2,col2_3; +// -- +// -- switch (col1) { +// -- case 0: +// -- col1_1 = rotmat->m1; +// -- col1_2 = rotmat->m2; +// -- col1_3 = rotmat->m3; +// -- break; +// -- +// -- case 1: +// -- col1_1 = rotmat->m4; +// -- col1_2 = rotmat->m5; +// -- col1_3 = rotmat->m6; +// -- break; +// -- +// -- case 2: +// -- col1_1 = rotmat->m7; +// -- col1_2 = rotmat->m8; +// -- col1_3 = rotmat->m9; +// -- break; +// -- } +// -- +// -- switch (col2) { +// -- case 0: +// -- col2_1 = rotmat->m1; +// -- col2_2 = rotmat->m2; +// -- col2_3 = rotmat->m3; +// -- break; +// -- +// -- case 1: +// -- col2_1 = rotmat->m4; +// -- col2_2 = rotmat->m5; +// -- col2_3 = rotmat->m6; +// -- break; +// -- +// -- case 2: +// -- col2_1 = rotmat->m7; +// -- col2_2 = rotmat->m8; +// -- col2_3 = rotmat->m9; +// -- break; +// -- } +// -- +// -- switch (col2) { +// -- case 0: +// -- rotmat->m1 = -col1_1; +// -- rotmat->m2 = -col1_2; +// -- rotmat->m3 = -col1_3; +// -- break; +// -- +// -- case 1: +// -- rotmat->m4 = -col1_1; +// -- rotmat->m5 = -col1_2; +// -- rotmat->m6 = -col1_3; +// -- break; +// -- +// -- case 2: +// -- rotmat->m7 = -col1_1; +// -- rotmat->m8 = -col1_2; +// -- rotmat->m9 = -col1_3; +// -- break; +// -- } +// -- +// -- switch (col1) { +// -- case 0: +// -- rotmat->m1 = -col2_1; +// -- rotmat->m2 = -col2_2; +// -- rotmat->m3 = -col2_3; +// -- break; +// -- +// -- case 1: +// -- rotmat->m4 = -col2_1; +// -- rotmat->m5 = -col2_2; +// -- rotmat->m6 = -col2_3; +// -- break; +// -- +// -- case 2: +// -- rotmat->m7 = -col2_1; +// -- rotmat->m8 = -col2_2; +// -- rotmat->m9 = -col2_3; +// -- break; +// -- } +// -- +// -- } +// -- +// -- void swap_negate_rows(vms_matrix *rotmat, int row1, int row2) +// -- { +// -- fix row1_1,row1_2,row1_3; +// -- fix row2_1,row2_2,row2_3; +// -- +// -- switch (row1) { +// -- case 0: +// -- row1_1 = rotmat->m1; +// -- row1_2 = rotmat->m4; +// -- row1_3 = rotmat->m7; +// -- break; +// -- +// -- case 1: +// -- row1_1 = rotmat->m2; +// -- row1_2 = rotmat->m5; +// -- row1_3 = rotmat->m8; +// -- break; +// -- +// -- case 2: +// -- row1_1 = rotmat->m3; +// -- row1_2 = rotmat->m6; +// -- row1_3 = rotmat->m9; +// -- break; +// -- } +// -- +// -- switch (row2) { +// -- case 0: +// -- row2_1 = rotmat->m1; +// -- row2_2 = rotmat->m4; +// -- row2_3 = rotmat->m7; +// -- break; +// -- +// -- case 1: +// -- row2_1 = rotmat->m2; +// -- row2_2 = rotmat->m5; +// -- row2_3 = rotmat->m8; +// -- break; +// -- +// -- case 2: +// -- row2_1 = rotmat->m3; +// -- row2_2 = rotmat->m6; +// -- row2_3 = rotmat->m9; +// -- break; +// -- } +// -- +// -- switch (row2) { +// -- case 0: +// -- rotmat->m1 = -row1_1; +// -- rotmat->m4 = -row1_2; +// -- rotmat->m7 = -row1_3; +// -- break; +// -- +// -- case 1: +// -- rotmat->m2 = -row1_1; +// -- rotmat->m5 = -row1_2; +// -- rotmat->m8 = -row1_3; +// -- break; +// -- +// -- case 2: +// -- rotmat->m3 = -row1_1; +// -- rotmat->m6 = -row1_2; +// -- rotmat->m9 = -row1_3; +// -- break; +// -- } +// -- +// -- switch (row1) { +// -- case 0: +// -- rotmat->m1 = -row2_1; +// -- rotmat->m4 = -row2_2; +// -- rotmat->m7 = -row2_3; +// -- break; +// -- +// -- case 1: +// -- rotmat->m2 = -row2_1; +// -- rotmat->m5 = -row2_2; +// -- rotmat->m8 = -row2_3; +// -- break; +// -- +// -- case 2: +// -- rotmat->m3 = -row2_1; +// -- rotmat->m6 = -row2_2; +// -- rotmat->m9 = -row2_3; +// -- break; +// -- } +// -- +// -- } +// -- +// -- // ------------------------------------------------------------------------------------------------ +// -- void side_based_matrix(vms_matrix *rotmat,int destside) +// -- { +// -- vms_angvec rotvec; +// -- vms_matrix r1,rtemp; +// -- +// -- switch (destside) { +// -- case WLEFT: +// -- // swap_negate_columns(rotmat,1,2); +// -- // swap_negate_rows(rotmat,1,2); +// -- break; +// -- +// -- case WTOP: +// -- break; +// -- +// -- case WRIGHT: +// -- // swap_negate_columns(rotmat,1,2); +// -- // swap_negate_rows(rotmat,1,2); +// -- break; +// -- +// -- case WBOTTOM: +// -- break; +// -- +// -- case WFRONT: +// -- break; +// -- +// -- case WBACK: +// -- break; +// -- } +// -- +// -- } + + +// ------------------------------------------------------------------------------------------------ +// Rotate a group about a point. +// The segments in the group are indicated (by segment number) in group_seglist. There are group_size segments. +// The point about which the groups is rotated is the center of first_seg:first_side. +// delta_flag: +// 0 absolute rotation, destination specified in terms of base_seg:base_side, used in moving or copying a group +// 1 relative rotation, destination specified relative to current orientation of first_seg:first_side +// Note: The group must exist in the mine, consisting of actual points in the world. If any points in the +// segments in the group are shared by segments not in the group, those points will get rotated and the +// segments not in the group will have their shapes modified. +// Return value: +// 0 group rotated +// 1 unable to rotate group +void med_create_group_rotation_matrix(vms_matrix *result_mat, int delta_flag, segment *first_seg, int first_side, segment *base_seg, int base_side, vms_matrix *orient_matrix, int orientation) +{ + vms_matrix rotmat2,rotmat,rotmat3,rotmat4; + vms_angvec pbh = {0,0,0}; + + // Determine whether this rotation is a delta rotation, meaning to just rotate in place, or an absolute rotation, + // which means that the destination rotation is specified, not as a delta, but as an absolute + if (delta_flag) { + // Create rotation matrix describing rotation. + med_extract_matrix_from_segment(first_seg, &rotmat4); // get rotation matrix describing current orientation of first seg + set_matrix_based_on_side(&rotmat4, first_side); + rotmat3 = *orient_matrix; + vm_transpose_matrix(&rotmat3); + vm_matrix_x_matrix(&rotmat,&rotmat4,&rotmat3); // this is the desired orientation of the new segment + vm_transpose_matrix(&rotmat4); + vm_matrix_x_matrix(&rotmat2,&rotmat,&rotmat4); // this is the desired orientation of the new segment + } else { + // Create rotation matrix describing rotation. + + med_extract_matrix_from_segment(base_seg, &rotmat); // get rotation matrix describing desired orientation + set_matrix_based_on_side(&rotmat, base_side); // modify rotation matrix for desired side + + // If the new segment is to be attached without rotation, then its orientation is the same as the base_segment + vm_matrix_x_matrix(&rotmat4,&rotmat,orient_matrix); // this is the desired orientation of the new segment + + pbh.b = orientation*16384; + vm_angles_2_matrix(&rotmat3,&pbh); + vm_matrix_x_matrix(&rotmat, &rotmat4, &rotmat3); + rotmat4 = rotmat; + + rotmat = rotmat4; + + med_extract_matrix_from_segment(first_seg, &rotmat3); // get rotation matrix describing current orientation of first seg + + // It is curious that the following statement has no analogue in the med_attach_segment_rotated code. + // Perhaps it is because segments are always attached at their front side. If the back side is the side + // passed to the function, then the matrix is not modified, which might suggest that what you need to do below + // is use Side_opposite[first_side]. + set_matrix_based_on_side(&rotmat3, Side_opposite[first_side]); // modify rotation matrix for desired side + + vm_transpose_matrix(&rotmat3); // get the inverse of the current orientation matrix + vm_matrix_x_matrix(&rotmat2,&rotmat,&rotmat3); // now rotmat2 takes the current segment to the desired orientation + vm_transpose_matrix(&rotmat2); + } + + *result_mat = rotmat2; + +} + +// ----------------------------------------------------------------------------------------- +// Rotate all vertices and objects in group. +void med_rotate_group(vms_matrix *rotmat, short *group_seglist, int group_size, segment *first_seg, int first_side) +{ + int v,s, objnum; + sbyte vertex_list[MAX_VERTICES]; + vms_vector rotate_center; + + compute_center_point_on_side(&rotate_center, first_seg, first_side); + + // Create list of points to rotate. + for (v=0; v<=Highest_vertex_index; v++) + vertex_list[v] = 0; + + for (s=0; sverts[v]] = 1; + + // Rotate center of all objects in group. + objnum = sp->objects; + while (objnum != -1) { + vms_vector tv, tv1; + + mprintf((0, "%2i ", objnum)); + vm_vec_sub(&tv1,&Objects[objnum].pos,&rotate_center); + vm_vec_rotate(&tv,&tv1,rotmat); + vm_vec_add(&Objects[objnum].pos, &tv, &rotate_center); + + objnum = Objects[objnum].next; + } + } + + // Do the pre-rotation xlate, do the rotation, do the post-rotation xlate + for (v=0; v<=Highest_vertex_index; v++) + if (vertex_list[v]) { + vms_vector tv,tv1; + + vm_vec_sub(&tv1,&Vertices[v],&rotate_center); + vm_vec_rotate(&tv,&tv1,rotmat); + vm_vec_add(&Vertices[v],&tv,&rotate_center); + + } + +} + + +// ------------------------------------------------------------------------------------------------ +void cgl_aux(segment *segp, short *seglistp, int *num_segs, short *ignore_list, int num_ignore_segs) +{ + int i, side; + int curseg = segp-Segments; + + for (i=0; i= MAX_SEGMENTS)) { + mprintf((0,"Warning -- invalid segment index = %i, max = %i\n",segp-Segments,MAX_SEGMENTS)); + Int3(); + } + + if (!Been_visited[segp-Segments]) { + seglistp[(*num_segs)++] = segp-Segments; + Been_visited[segp-Segments] = 1; + + for (side=0; sidechildren[side])) + cgl_aux(&Segments[segp->children[side]], seglistp, num_segs, ignore_list, num_ignore_segs); + } +} + +// ------------------------------------------------------------------------------------------------ +// Sets Been_visited[n] if n is reachable from segp +void create_group_list(segment *segp, short *seglistp, int *num_segs, short *ignore_list, int num_ignore_segs) +{ + int i; + + for (i=0; isegnum = %i\n", objnum, Objects[objnum].segnum, new_obj_id, new_segment_id, Objects[new_obj_id].segnum)); + } + objnum = Objects[objnum].next; + } + } + + // Now, for each segment in segment_ids, correct its children numbers by translating through new_segment_ids + // and correct its vertex numbers by translating through new_vertex_ids + for (s=0; schildren[sidenum]; + if (IS_CHILD(seg)) { + for (ss=0; ssverts[v]]) { + sp->verts[v] = new_vertex_ids[sp->verts[v]]; + } + } + } // end for (s=0... + + // Now, copy new_segment_ids into segment_ids + for (s=0; schildren[base_side])) { + editor_status("Error -- unable to copy group, base_seg:base_side must be free."); + return 1; + } + + if (num_groups == MAX_GROUPS) { + x = MessageBox( -2, -2, 2, "Warning: You have reached the MAXIMUM group number limit. Continue?", "No", "Yes" ); + if (x==1) + return 0; + } + + if (num_groups < MAX_GROUPS) { + num_groups++; + new_current_group = num_groups-1; + } else + new_current_group = 0; + + Assert(current_group >= 0); + + // Find groupsegp index + for (s=0;sverts[v]] = 1; + else { + for (v=0; v<=Highest_vertex_index; v++) + in_vertex_list[v] = 0; + + for (s=0; schildren[c])) { + if (!in_group(segp->children[c], new_current_group)) { + mprintf((0, "2: Breaking connection at seg:side = %i:%i\n", segp-Segments, c)); + segp->children[c] = -1; + validate_segment_side(segp,c); // we have converted a connection to a side so validate the segment + } + } + } + + copy_uvs_seg_to_seg(&New_segment, Groupsegp[new_current_group]); + + // Now do the copy + // First, xlate all vertices so center of group_seg:group_side is at origin + compute_center_point_on_side(&srcv,group_seg,group_side); + for (v=0; v<=Highest_vertex_index; v++) + if (in_vertex_list[v]) + vm_vec_sub2(&Vertices[v],&srcv); + + // Now, translate all object positions. + for (s=0; schildren[base_side])) + if (base_seg->children[base_side] != group_seg-Segments) { + editor_status("Error -- unable to move group, base_seg:base_side must be free or point to group_seg."); + return 1; + } + +// // See if any vertices in base_seg are contained in any vertex in group_list +// for (v=0; vverts[v]) { +// editor_status("Error -- unable to move group, it shares a vertex with destination segment."); +// return 1; +// } + + for (v=0; v<=Highest_vertex_index; v++) { + in_vertex_list[v] = 0; + out_vertex_list[v] = 0; + } + + // Make a list of all vertices in group. + for (s=0; sverts[vv] == v) + sp->verts[vv] = new_vertex_id; + } + } + + for (s=0;schildren[c])) + { + csegp = &Segments[segp->children[c]]; + if (csegp->group != current_group) + { + for (d=0; dchildren[d])) + { + dsegp = &Segments[csegp->children[d]]; + if (dsegp->group == current_group) + { + csegp->children[d] = -1; + validate_segment_side(csegp,d); // we have converted a connection to a side so validate the segment + } + } + segp->children[c] = -1; + validate_segment_side(segp,c); // we have converted a connection to a side so validate the segment + } + } + } + + copy_uvs_seg_to_seg(&New_segment, Groupsegp[current_group]); + + // Now do the move + // First, xlate all vertices so center of group_seg:group_side is at origin + compute_center_point_on_side(&srcv,group_seg,group_side); + for (v=0; v<=Highest_vertex_index; v++) + if (in_vertex_list[v]) + vm_vec_sub2(&Vertices[v],&srcv); + + // Now, move all object positions. + for (s=0; schildren[(int) Side_opposite[Curside]])) { + // -- I don't understand this, MK, 01/25/94: if (Cursegp->children[Curside] != group_seg-Segments) { + editor_status("Error -- unable to rotate group, Cursegp:Side_opposite[Curside] cannot be free."); + return 1; + } + + current_group_save = current_group; + current_group = ROT_GROUP; + Groupsegp[ROT_GROUP] = Cursegp; + + save_selected_segs(&n_selected_segs_save, selected_segs_save); + GroupList[ROT_GROUP].num_segments = 0; + newseg = Cursegp - Segments; + newseg_side = Side_opposite[Curside]; + + // Create list of segments to rotate. + // Sever connection between first seg to rotate and its connection on Side_opposite[Curside]. + child_save = Cursegp->children[newseg_side]; // save connection we are about to sever + Cursegp->children[newseg_side] = -1; // sever connection + create_group_list(Cursegp, GroupList[ROT_GROUP].segments, &GroupList[ROT_GROUP].num_segments, Selected_segs, 0); // create list of segments in group + //mprintf((0, "NumSegs = %d\n", GroupList[ROT_GROUP].num_segments)); + Cursegp->children[newseg_side] = child_save; // restore severed connection + GroupList[ROT_GROUP].segments[0] = newseg; + + baseseg = Segments[newseg].children[newseg_side]; + if (!IS_CHILD(baseseg)) { + editor_status("Error -- unable to rotate segment, side opposite curside is not attached."); + restore_selected_segs(n_selected_segs_save,selected_segs_save); + current_group = current_group_save; + return 1; + } + + baseseg_side = find_connect_side(&Segments[newseg], &Segments[baseseg]); + + med_extract_matrix_from_segment(&Segments[newseg],&tm1); + tm1 = vmd_identity_matrix; + vm_angles_2_matrix(&tm2,pbh); + vm_matrix_x_matrix(&orient_matrix,&tm1,&tm2); + + Segments[baseseg].children[baseseg_side] = -1; + Segments[newseg].children[newseg_side] = -1; + + if (!med_move_group(1, &Segments[baseseg], baseseg_side, &Segments[newseg], newseg_side, &orient_matrix, 0)) { + Cursegp = &Segments[newseg]; + med_create_new_segment_from_cursegp(); +// validate_selected_segments(); + med_propagate_tmaps_to_segments(&Segments[baseseg], &Segments[newseg], 1); + med_propagate_tmaps_to_back_side(&Segments[newseg], Curside, 1); + } + + restore_selected_segs(n_selected_segs_save,selected_segs_save); + current_group = current_group_save; + + return 1; +} + +// ----------------------------------------------------------------------------- +// Attach segment in the new-fangled way, which is by using the CopyGroup code. +int RotateSegmentNew(vms_angvec *pbh) +{ + int rval; + + autosave_mine(mine_filename); + + rval = rotate_segment_new(pbh); + + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + warn_if_concave_segment(Cursegp); + + return rval; +} + +static char current_tmap_list[MAX_TEXTURES][13]; + +// ----------------------------------------------------------------------------- +// Save mine will: +// 1. Write file info, header info, editor info, vertex data, segment data, +// and new_segment in that order, marking their file offset. +// 2. Go through all the fields and fill in the offset, size, and sizeof +// values in the headers. +int med_save_group( char *filename, short *vertex_ids, short *segment_ids, int num_vertices, int num_segments) +{ + FILE * SaveFile; + int header_offset, editor_offset, vertex_offset, segment_offset, texture_offset; + char ErrorMessage[100]; + int i, j, k; + int segnum; + segment tseg; + vms_vector tvert; + int found; + + SaveFile = fopen( filename, "wb" ); + if (!SaveFile) + { + sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename ); + MessageBox( -2, -2, 1, ErrorMessage, "Ok" ); + return 1; + } + + //===================== SAVE FILE INFO ======================== + + group_fileinfo.fileinfo_version = MINE_VERSION; + group_fileinfo.fileinfo_sizeof = sizeof(group_fileinfo); + group_fileinfo.header_offset = -1; + group_fileinfo.header_size = sizeof(group_header); + group_fileinfo.editor_offset = -1; + group_fileinfo.editor_size = sizeof(group_editor); + group_fileinfo.vertex_offset = -1; + group_fileinfo.vertex_howmany = num_vertices; + group_fileinfo.vertex_sizeof = sizeof(vms_vector); + group_fileinfo.segment_offset = -1; + group_fileinfo.segment_howmany = num_segments; + group_fileinfo.segment_sizeof = sizeof(segment); + group_fileinfo.texture_offset = -1; + group_fileinfo.texture_howmany = 0; + group_fileinfo.texture_sizeof = 13; // num characters in a name + + // Write the fileinfo + fwrite( &group_fileinfo, sizeof(group_fileinfo), 1, SaveFile ); + + //===================== SAVE HEADER INFO ======================== + + group_header.num_vertices = num_vertices; + group_header.num_segments = num_segments; + + // Write the editor info + header_offset = ftell(SaveFile); + fwrite( &group_header, sizeof(group_header), 1, SaveFile ); + + //===================== SAVE EDITOR INFO ========================== + group_editor.newsegment_offset = -1; // To be written + group_editor.newsegment_size = sizeof(segment); + // Next 3 vars added 10/07 by JAS + if (Groupsegp[current_group]) { + segnum = Groupsegp[current_group]-Segments; + for (i=0;i -1 ) + { + if (cfseek( LoadFile,group_fileinfo.header_offset, SEEK_SET )) + Error( "Error seeking to header_offset in group.c" ); + + if (cfread( &group_header, group_fileinfo.header_size,1,LoadFile )!=1) + Error( "Error reading group_header in group.c" ); + } + + //===================== READ EDITOR INFO ========================== + + // Set default values + group_editor.current_seg = 0; + group_editor.newsegment_offset = -1; // To be written + group_editor.newsegment_size = sizeof(segment); + group_editor.Groupsegp = -1; + group_editor.Groupside = 0; + + if (group_fileinfo.editor_offset > -1 ) + { + if (cfseek( LoadFile,group_fileinfo.editor_offset, SEEK_SET )) + Error( "Error seeking to editor_offset in group.c" ); + + if (cfread( &group_editor, group_fileinfo.editor_size,1,LoadFile )!=1) + Error( "Error reading group_editor in group.c" ); + + } + + //===================== READ VERTEX INFO ========================== + + if ( (group_fileinfo.vertex_offset > -1) && (group_fileinfo.vertex_howmany > 0)) + { + if (cfseek( LoadFile,group_fileinfo.vertex_offset, SEEK_SET )) + Error( "Error seeking to vertex_offset in group.c" ); + + for (i=0;i -1) && (group_fileinfo.segment_howmany > 0)) + { + if (cfseek( LoadFile,group_fileinfo.segment_offset, SEEK_SET )) + Error( "Error seeking to segment_offset in group.c" ); + + for (i=0;i -1) && (group_fileinfo.texture_howmany > 0)) + { + if (cfseek( LoadFile, group_fileinfo.texture_offset, SEEK_SET )) + Error( "Error seeking to texture_offset in gamemine.c" ); + + for (i=0; i< group_fileinfo.texture_howmany; i++ ) + { + if (cfread( &old_tmap_list[i], group_fileinfo.texture_sizeof, 1, LoadFile )!=1) + Error( "Error reading old_tmap_list[i] in gamemine.c" ); + } + } + + //=============== GENERATE TEXTURE TRANSLATION TABLE =============== + + translate = 0; + + Assert (NumTextures < MAX_TEXTURES); +{ + hashtable ht; + + hashtable_init( &ht, NumTextures ); + + // Remove all the file extensions in the textures list + + for (i=0;igroup == current_group) { + + Cursegp->group = -1; + delete_segment_from_group( Cursegp-Segments, current_group ); + + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Segment Ungrouped from Group %d.", current_group); + + return 1; + } else + return 0; +} + +int GroupSegment( void ) +{ + if (Cursegp->group == -1) { + + Cursegp->group = current_group; + add_segment_to_group( Cursegp-Segments, current_group ); + + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Segment Added to Group %d.", current_group); + + return 1; + } else + return 0; +} + +int Degroup( void ) +{ + int i; + +// GroupList[current_group].num_segments = 0; +// Groupsegp[current_group] = 0; + + if (num_groups==0) return 0; + + for (i=0; i num_groups-1) current_group--; + + if (num_groups == 0) + current_group = -1; + + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Group UNgrouped."); + + return 1; +} + +void NextGroup( void ) +{ + + if (num_groups > 0) + { + current_group++; + if (current_group >= num_groups ) current_group = 0; + + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + } + else editor_status("No Next Group\n"); +} + +void PrevGroup( void ) +{ + if (num_groups > 0) + { + current_group--; + if (current_group < 0 ) current_group = num_groups-1; + + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + } + else editor_status("No Previous Group\n"); +} + +// Returns: +// 0 = successfully selected +// 1 = bad group number +int select_group( int num ) +{ + if ((num>=0) && (numchildren[Groupside[current_group]]; + if (attach_seg != -1) { + int i; + + for (i=0; ichildren[Groupside[current_group]]); + return 1; + } + } + + med_compress_mine(); + + if (!med_copy_group(0, Cursegp, Curside, Groupsegp[current_group], Groupside[current_group], &vmd_identity_matrix)) { + autosave_mine(mine_filename); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Group copied."); + return 0; + } else + return 1; +} + + +// ----------------------------------------------------------------------------- +int RotateGroup(void) +{ + + if (!Groupsegp[current_group]) { + editor_status("Error -- Cannot rotate group, no group segment."); + return 1; + } + + Group_orientation[current_group]++; + if ((Group_orientation[current_group] <0) || (Group_orientation[current_group] >4)) + Group_orientation[current_group]=0; + + med_compress_mine(); + + if (!med_move_group(0, Cursegp, Curside, Groupsegp[current_group], Groupside[current_group], + &vmd_identity_matrix, Group_orientation[current_group])) + { + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Group rotated."); + return 0; + } + else + return 1; +} + + +// ----------------------------------------------------------------------------- +// Creates a group from all segments connected to marked segment. +int SubtractFromGroup(void) +{ + int x, s, original_group; + short *gp; + int cur_num_segs; + + if (!Markedsegp) { + editor_status("Error -- Cannot create group, no marked segment."); + return 1; + } + + med_compress_mine(); + autosave_mine(mine_filename); + + if (num_groups == MAX_GROUPS) { + x = MessageBox( -2, -2, 2, "Warning: You are about to wipe out a group.", "ARGH! NO!", "No problemo." ); + if (x==1) return 0; + } + + if (current_group == -1) { + editor_status("Error -- No current group. Cannot subtract."); + return 1; + } + + original_group = current_group; + + current_group = (current_group + 1) % MAX_GROUPS; + +// if (num_groups < MAX_GROUPS) { +// current_group = num_groups; +// num_groups++; +// } else +// current_group = 0; + + // mprintf((0, "Old group: ")); + // for (s=0; s num_groups-1) current_group--; + + if (num_groups==0) + current_group = -1; + + strcpy(undo_status[Autosave_count], "Delete Group UNDONE."); + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Group deleted."); + // warn_if_concave_segments(); // This could be faster -- just check if deleted segment was concave, warn accordingly + + return 1; + +} + + +int MarkGroupSegment( void ) +{ + if ((Cursegp->group != -1) && (Cursegp->group == current_group)) + { + autosave_mine(mine_filename); + Groupsegp[current_group] = Cursegp; + Groupside[current_group] = Curside; + editor_status("Group Segment Marked."); + Update_flags |= UF_ED_STATE_CHANGED; + strcpy(undo_status[Autosave_count], "Mark Group Segment UNDONE."); + mine_changed = 1; + return 1; + } + else return 0; +} diff --git a/main/editor/info.c b/main/editor/info.c new file mode 100644 index 00000000..3d7c3c23 --- /dev/null +++ b/main/editor/info.c @@ -0,0 +1,492 @@ +/* +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/info.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Print debugging info in ui. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:18 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:34 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.42 1995/02/22 15:12:50 allender + * remove anonymous unions from object structure + * + * Revision 1.41 1994/12/08 13:59:39 matt + * *** empty log message *** + * + * Revision 1.40 1994/09/30 00:38:30 mike + * Fix some diagnostic messages + * + * Revision 1.39 1994/09/29 20:13:12 mike + * Clean up some text, prevent it from writing outside canvas. + * + * Revision 1.38 1994/09/29 09:32:17 mike + * Fix text clipping problem in UI keypad info text. + * + * Revision 1.37 1994/09/25 23:42:20 matt + * Took out references to obsolete constants + * + * Revision 1.36 1994/08/25 21:57:05 mike + * IS_CHILD stuff. + * + * Revision 1.35 1994/08/23 16:39:50 mike + * mode replaced by behavior in ai_info. + * + * Revision 1.34 1994/07/18 10:45:23 mike + * Fix erase window in texture pads after adding more click-boxes. + * + * Revision 1.33 1994/07/15 12:34:10 mike + * Remove use of AIM_FOLLOW_PATH_CIRCULAR. + * + * Revision 1.32 1994/06/17 17:13:46 yuan + * Fixed text so it doesn't overflow screen + * + * Revision 1.31 1994/06/01 17:22:31 matt + * Set font color before drawing info; got rid of superfluous %d + * + * Revision 1.30 1994/05/29 23:40:29 matt + * Killed reference to now-unused movement type + * + * Revision 1.29 1994/05/29 22:52:32 matt + * Deleted unused stuff + * + * Revision 1.28 1994/05/27 10:34:16 yuan + * Added new Dialog boxes for Walls and Triggers. + * + * Revision 1.27 1994/05/17 10:34:35 matt + * Changed Num_objects to num_objects, since it's not really global anymore + * + * Revision 1.26 1994/05/14 17:17:59 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.25 1994/05/12 14:47:07 mike + * Adjust for Ai_states killed, replaced by field in object structure. + * + * Revision 1.24 1994/05/06 12:52:11 yuan + * Adding some gamesave checks... + * + * Revision 1.23 1994/05/03 19:21:28 matt + * Removed reference to robot flythrough mode, which doesn't exist anymore + * + * Revision 1.22 1994/05/03 11:03:06 mike + * Customize text for segment sizing keypad. + * + * Revision 1.21 1994/04/29 15:05:40 yuan + * More info added... + * + * Revision 1.20 1994/04/22 17:45:58 john + * MAde top 2 bits of paste-ons pick the + * orientation of the bitmap. + * + * Revision 1.19 1994/04/20 17:29:30 yuan + * Added tmap_num info. + * + * Revision 1.18 1994/04/13 19:12:55 mike + * Fix font color problems in keypads. + * + * Revision 1.17 1994/04/13 13:26:37 mike + * Kill a mprintf. + * + * Revision 1.16 1994/04/13 13:24:44 mike + * Separate info display, customize for each keypad. + * + * Revision 1.15 1994/03/19 17:21:31 yuan + * Wall system implemented until specific features need to be added... + * (Needs to be hammered on though.) + * + * Revision 1.14 1994/02/22 18:13:13 yuan + * Added tmap number field. + * + * Revision 1.13 1994/02/17 09:46:27 matt + * Removed include of slew.h + * + * Revision 1.12 1994/02/16 19:58:56 yuan + * Added type to info + * + * Revision 1.11 1994/02/16 16:48:08 yuan + * Added Curside. + * + * Revision 1.10 1994/02/03 17:26:43 yuan + * Fixed formatting of vertex numbering. + * + * Revision 1.9 1994/01/31 12:17:06 yuan + * Make sure Num_segments, etc. are drawn. + * + * Revision 1.8 1994/01/22 13:43:12 yuan + * Cosmetic fixes. + * + * Revision 1.7 1994/01/21 12:14:59 yuan + * Fixed cosmetic problem + * + * Revision 1.6 1994/01/21 12:01:03 yuan + * Added segment and vertex info + * + * Revision 1.5 1994/01/20 11:28:11 john + * *** empty log message *** + * + * Revision 1.4 1994/01/19 10:44:42 john + * *** empty log message *** + * + * Revision 1.3 1994/01/19 10:32:36 john + * *** empty log message *** + * + * Revision 1.2 1994/01/19 09:34:31 john + * First version. + * + * Revision 1.1 1994/01/19 09:30:43 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: info.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include "inferno.h" +#include "segment.h" +#include "gr.h" +#include "ui.h" +#include "editor.h" + +#include "mono.h" +#include "error.h" +#include "textures.h" +#include "object.h" +#include "ai.h" + +#include "texpage.h" // Textue selection paging stuff +#include "objpage.h" // Object selection paging stuff + +#include "wall.h" +#include "switch.h" + +int init_info; + +#ifdef DO_MEMINFO +struct meminfo { + int LargestBlockAvail; + int MaxUnlockedPage; + int LargestLockablePage; + int LinAddrSpace; + int NumFreePagesAvail; + int NumPhysicalPagesFree; + int TotalPhysicalPages; + int FreeLinAddrSpace; + int SizeOfPageFile; + int Reserved[3]; +} MemInfo; + +#define DPMI_INT 0x31 + +void read_mem_info() +{ + union REGS regs; + struct SREGS sregs; + + regs.x.eax = 0x00000500; + memset( &sregs, 0, sizeof(sregs) ); + sregs.es = FP_SEG( &MemInfo ); + regs.x.edi = FP_OFF( &MemInfo ); + + int386x( DPMI_INT, ®s, ®s, &sregs ); +} +#endif + +char * get_object_type(int num, char *name) +{ + switch (num) { + case OBJ_NONE: strcpy(name, "OBJ_NONE "); break; + case OBJ_WALL: strcpy(name, "OBJ_WALL "); break; + case OBJ_FIREBALL: strcpy(name, "OBJ_FIREBALL"); break; + case OBJ_ROBOT: strcpy(name, "OBJ_ROBOT "); break; + case OBJ_HOSTAGE: strcpy(name, "OBJ_HOSTAGE "); break; + case OBJ_PLAYER: strcpy(name, "OBJ_PLAYER "); break; + case OBJ_WEAPON: strcpy(name, "OBJ_WEAPON "); break; + case OBJ_CAMERA: strcpy(name, "OBJ_CAMERA "); break; + case OBJ_POWERUP: strcpy(name, "OBJ_POWERUP "); break; + default: strcpy(name, " (unknown) "); break; + } + + return name; +} + +char * get_control_type(int num, char *name) +{ + switch (num) { + case CT_NONE: strcpy(name, "CT_NONE "); break; + case CT_AI: strcpy(name, "CT_AI "); break; + case CT_EXPLOSION: strcpy(name, "CT_EXPLOSION "); break; + //case CT_MULTIPLAYER: strcpy(name, "CT_MULTIPLAYER"); break; + case CT_FLYING: strcpy(name, "CT_FLYING "); break; + case CT_SLEW: strcpy(name, "CT_SLEW "); break; + case CT_FLYTHROUGH: strcpy(name, "CT_FLYTHROUGH "); break; + //case CT_DEMO: strcpy(name, "CT_DEMO "); break; + //case CT_ROBOT_FLYTHROUGH: strcpy(name, "CT_FLYTHROUGH "); break; + case CT_WEAPON: strcpy(name, "CT_WEAPON "); break; + default: strcpy(name, " (unknown) "); break; + } + return name; +} + +char * get_movement_type(int num, char *name) +{ + switch (num) { + case MT_NONE: strcpy(name, "MT_NONE "); break; + case MT_PHYSICS: strcpy(name, "MT_PHYSICS "); break; + //case MT_MULTIPLAYER: strcpy(name, "MT_MULTIPLAYER"); break; + default: strcpy(name, " (unknown) "); break; + } + return name; +} + +char * get_ai_behavior(int num, char *name) +{ +#define AIB_STILL 0x80 +#define AIB_NORMAL 0x81 +#define AIB_HIDE 0x82 +#define AIB_RUN_FROM 0x83 +#define AIB_FOLLOW_PATH 0x84 + + switch (num) { + case AIB_STILL: strcpy(name, "STILL "); break; + case AIB_NORMAL: strcpy(name, "NORMAL "); break; + case AIB_HIDE: strcpy(name, "HIDE "); break; + case AIB_RUN_FROM: strcpy(name, "RUN_FROM "); break; + case AIB_FOLLOW_PATH: strcpy(name, "FOLLOW_PATH "); break; + default: strcpy(name, " (unknown) "); break; + } + return name; +} + +// --------------------------------------------------------------------------------------------------- +void info_display_object_placement(int show_all) +{ + static int old_Cur_object_index; + static int old_type; + static int old_movement_type; + static int old_control_type; + static int old_mode; + + char name[30]; + + if (init_info | show_all) { + old_Cur_object_index = -2; + old_type = -2; + old_movement_type = -2; + old_control_type = -2; + old_mode = -2; + } + + if ( ( Cur_object_index != old_Cur_object_index) || + ( Objects[Cur_object_index].type != old_type) || + ( Objects[Cur_object_index].movement_type != old_movement_type) || + ( Objects[Cur_object_index].control_type != old_control_type) || + ( Objects[Cur_object_index].ctype.ai_info.behavior != old_mode) ) { + + gr_uprintf( 0, 0, "Object id: %4d\n", Cur_object_index); + gr_uprintf( 0, 16, "Type: %s\n", get_object_type(Objects[Cur_object_index].type , name)); + gr_uprintf( 0, 32, "Movmnt: %s\n", get_movement_type(Objects[Cur_object_index].movement_type, name)); + gr_uprintf( 0, 48, "Cntrl: %s\n", get_control_type(Objects[Cur_object_index].control_type, name)); + gr_uprintf( 0, 64, "Mode: %s\n", get_ai_behavior(Objects[Cur_object_index].ctype.ai_info.behavior, name)); + + old_Cur_object_index = Cur_object_index; + old_type = Objects[Cur_object_index].type; + old_movement_type = Objects[Cur_object_index].movement_type; + old_mode = Objects[Cur_object_index].control_type; + old_mode = Objects[Cur_object_index].ctype.ai_info.behavior; + } + +} + +// --------------------------------------------------------------------------------------------------- +void info_display_segsize(int show_all) +{ + static int old_SegSizeMode; + + char name[30]; + + if (init_info | show_all) { + old_SegSizeMode = -2; + } + + if (old_SegSizeMode != SegSizeMode ) { + switch (SegSizeMode) { + case SEGSIZEMODE_FREE: strcpy(name, "free "); break; + case SEGSIZEMODE_ALL: strcpy(name, "all "); break; + case SEGSIZEMODE_CURSIDE: strcpy(name, "curside"); break; + case SEGSIZEMODE_EDGE: strcpy(name, "edge "); break; + case SEGSIZEMODE_VERTEX: strcpy(name, "vertex "); break; + default: + Error("Illegal value for SegSizeMode in info.c/info_display_segsize\n"); + } + + gr_uprintf( 0, 0, "Mode: %s\n", name); + + old_SegSizeMode = SegSizeMode; + } + +} + +extern int num_objects; + +// --------------------------------------------------------------------------------------------------- +void info_display_default(int show_all) +{ + static int old_Num_segments = -1; + static int old_Num_vertices = -1; + static int old_Num_objects = -1; + static int old_Cursegp_num = -1; + static int old_Curside = -1; + static int old_Cursegp_num_for_verts = -1; + static int old_CurrentTexture = -1; + static int old_Num_walls = -1; + static int old_Num_triggers = -1; + + if (init_info | show_all) { + init_info = 0; + old_Num_segments = -1; + old_Num_vertices = -1; + old_Num_objects = -1; + old_Cursegp_num = -1; + old_Cursegp_num_for_verts = -1; + old_Curside = -1; + old_CurrentTexture = -1; + old_Num_walls = -1; + old_Num_triggers = -1; + } + + gr_set_fontcolor(CBLACK,CWHITE); + + //--------------- Number of segments ---------------- + + if ( old_Num_segments != Num_segments ) { + gr_uprintf( 0, 0, "Segments: %4d/%4d", Num_segments, MAX_SEGMENTS ); + old_Num_segments = Num_segments; + } + + //---------------- Number of vertics ----------------- + + if ( old_Num_vertices != Num_vertices ) { + gr_uprintf( 0, 16, "Vertices: %4d/%4d", Num_vertices, MAX_VERTICES ); + old_Num_vertices = Num_vertices; + } + + //---------------- Number of objects ----------------- + + if ( old_Num_objects != num_objects ) { + gr_uprintf( 0, 32, "Objs: %3d/%3d", num_objects, MAX_OBJECTS ); + old_Num_objects = num_objects; + } + + //--------------- Current_segment_number ------------- + //--------------- Current_side_number ------------- + + if (( old_Cursegp_num != Cursegp-Segments ) || ( old_Curside != Curside )) { + gr_uprintf( 0, 48, "Cursegp/side: %3d/%1d", Cursegp-Segments, Curside); + gr_uprintf( 0, 128, " tmap1,2,o: %3d/%3dx%1d", Cursegp->sides[Curside].tmap_num, Cursegp->sides[Curside].tmap_num2 & 0x3FFF, (Cursegp->sides[Curside].tmap_num2 >> 14) & 3); + old_Cursegp_num = Cursegp-Segments; + old_Curside = Curside; + } + + //--------------- Current_vertex_numbers ------------- + + if ( old_Cursegp_num_for_verts != Cursegp-Segments ) { + + gr_uprintf( 0, 64, "{%3d,%3d,%3d,%3d,", Cursegp->verts[0],Cursegp->verts[1], + Cursegp->verts[2],Cursegp->verts[3] ); + gr_uprintf( 0, 80," %3d,%3d,%3d,%3d}", Cursegp->verts[4],Cursegp->verts[5], + Cursegp->verts[6],Cursegp->verts[7] ); + old_Cursegp_num_for_verts = Cursegp-Segments; + } + + //--------------- Num walls/links/triggers ------------------------- + + if ( old_Num_walls != Num_walls ) { +// gr_uprintf( 0, 96, "Walls/Links %d/%d", Num_walls, Num_links ); + gr_uprintf( 0, 96, "Walls %3d", Num_walls ); + old_Num_walls = Num_walls; + } + + //--------------- Num triggers ---------------------- + + if ( old_Num_triggers != Num_triggers ) { + gr_uprintf( 0, 112, "Num_triggers %2d", Num_triggers ); + old_Num_triggers = Num_triggers; + } + + //--------------- Current texture number ------------- + + if ( old_CurrentTexture != CurrentTexture ) { + gr_uprintf( 0, 144, "Tex/Light: %3d %5.2f", CurrentTexture, f2fl(TmapInfo[CurrentTexture].lighting)); + old_CurrentTexture = CurrentTexture; + } + +} + +// ------------------------------------------------------------------------------------ +void clear_pad_display(void) +{ + gr_clear_canvas(CWHITE); + gr_set_fontcolor( CBLACK, CWHITE ); +} + +// ------------------------------------------------------------------------------------ +void info_display_all( UI_WINDOW * wnd ) +{ + static int old_padnum = -1; + int padnum,show_all = 0; + grs_canvas *save_canvas = grd_curcanv; + + wnd++; //kill warning + + grd_curcanv = Pad_text_canvas; + + padnum = ui_pad_get_current(); + Assert(padnum <= MAX_PAD_ID); + + if (padnum != old_padnum) { + clear_pad_display(); + old_padnum = padnum; + show_all = 1; + } + + switch (padnum) { + case OBJECT_PAD_ID: // Object placement + info_display_object_placement(show_all); + break; + case SEGSIZE_PAD_ID: // Segment sizing + info_display_segsize(show_all); + break; + default: + info_display_default(show_all); + break; + } + grd_curcanv = save_canvas; +} + diff --git a/main/editor/info.h b/main/editor/info.h new file mode 100644 index 00000000..d283981f --- /dev/null +++ b/main/editor/info.h @@ -0,0 +1,47 @@ +/* +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/info.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Header for info.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:36 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:32 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.2 1994/05/14 17:18:17 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.1 1994/05/14 16:30:39 matt + * Initial revision + * + * + */ + + + +#ifndef _INFO_H +#define _INFO_H + +void info_display_all( UI_WINDOW * wnd ); + +extern int init_info; + +#endif diff --git a/main/editor/kbuild.c b/main/editor/kbuild.c new file mode 100644 index 00000000..738ecefb --- /dev/null +++ b/main/editor/kbuild.c @@ -0,0 +1,284 @@ +/* +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/kbuild.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions for building parts of mines. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:19 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:43 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.20 1995/02/22 11:00:47 yuan + * prototype include. + * + * Revision 1.19 1995/02/22 10:59:01 yuan + * Save sloppy mine before punching. + * + * Revision 1.18 1994/08/25 21:57:56 mike + * IS_CHILD stuff. + * + * Revision 1.17 1994/05/16 12:00:52 mike + * Call med_combine_duplicate_vertices before various build functions. + * + * Revision 1.16 1994/05/09 23:34:31 mike + * Punch all sloppy sides in a group. + * + * Revision 1.15 1994/02/16 15:23:06 yuan + * Checking in for editor make. + * + * Revision 1.14 1994/01/21 12:01:31 yuan + * Added clearer editor_status messages (sloppy joint vs. joint) + * + * Revision 1.13 1994/01/14 11:59:52 yuan + * New function in build menu. + * "Punch" through walls to force a joint formation with + * closest segment:side, if the closest segment:side allows + * a connection. + * + * Revision 1.12 1994/01/07 17:45:05 yuan + * Just changed some tabs and formatting I believe. + * + * Revision 1.11 1993/12/06 19:33:36 yuan + * Fixed autosave stuff so that undo restores Cursegp and + * Markedsegp + * + * Revision 1.10 1993/12/02 12:39:15 matt + * Removed extra includes + * + * Revision 1.9 1993/11/12 14:31:31 yuan + * Added warn_if_concave_segments. + * + * Revision 1.8 1993/11/11 17:12:45 yuan + * Fixed display of messages, so that concave segment + * warning doesn't wipe them out immediately. + * + * Revision 1.7 1993/11/09 12:09:28 mike + * Remove extern for mine_filename, put it in editor.h + * + * Revision 1.6 1993/11/08 19:14:06 yuan + * Added Undo command (not working yet) + * + * Revision 1.5 1993/11/05 17:32:36 john + * added funcs + * ., + * + * Revision 1.4 1993/11/01 16:53:51 mike + * Add CreateAdjacentJointsSegment and CreateAdjacentJointsAll + * + * Revision 1.3 1993/11/01 11:24:59 mike + * Add CreateJointAdjacent + * + * Revision 1.2 1993/10/29 19:13:11 yuan + * Added diagnostic messages + * + * Revision 1.1 1993/10/13 18:53:27 john + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: kbuild.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include + +#include "inferno.h" +#include "editor/editor.h" +#include "gameseg.h" +#include "gamesave.h" +#include "mono.h" + +// ---------- Create a bridge segment between current segment/side and marked segment/side ---------- +int CreateBridge() +{ + if (!med_form_bridge_segment(Cursegp,Curside,Markedsegp,Markedside)) { + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + autosave_mine(mine_filename); + diagnostic_message("Bridge segment formed."); + strcpy(undo_status[Autosave_count], "Bridge segment UNDONE."); + warn_if_concave_segments(); + } + return 1; +} + + + +// ---------- Form a joint between current segment:side and marked segment:side, modifying marked segment ---------- +int FormJoint() +{ + if (!Markedsegp) + diagnostic_message("Marked segment not set -- unable to form joint."); + else { + if (!med_form_joint(Cursegp,Curside,Markedsegp,Markedside)) { + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + autosave_mine(mine_filename); + diagnostic_message("Joint formed."); + strcpy(undo_status[Autosave_count], "Joint undone."); + warn_if_concave_segments(); + } + } + + return 1; + +} + +// ---------- Create a bridge segment between current segment:side adjacent segment:side ---------- +int CreateAdjacentJoint() +{ + int adj_side; + segment *adj_sp; + + if (med_find_adjacent_segment_side(Cursegp, Curside, &adj_sp, &adj_side)) { + if (Cursegp->children[Curside] != adj_sp-Segments) { + med_form_joint(Cursegp,Curside,adj_sp,adj_side); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + autosave_mine(mine_filename); + diagnostic_message("Joint segment formed."); + strcpy(undo_status[Autosave_count], "Joint segment undone."); + warn_if_concave_segments(); + } else + editor_status("Attempted to form joint through connected side -- joint segment not formed (you bozo)."); + } else + editor_status("Could not find adjacent segment -- joint segment not formed."); + + return 1; +} + +// ---------- Create a bridge segment between current segment:side adjacent segment:side ---------- +int CreateSloppyAdjacentJoint() +{ + int adj_side; + segment *adj_sp; + + save_level("SLOPPY.LVL"); + + if (med_find_closest_threshold_segment_side(Cursegp, Curside, &adj_sp, &adj_side, 20*F1_0)) { + if (Cursegp->children[Curside] != adj_sp-Segments) { + if (!med_form_joint(Cursegp,Curside,adj_sp,adj_side)) + { + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + autosave_mine(mine_filename); + diagnostic_message("Sloppy Joint segment formed."); + strcpy(undo_status[Autosave_count], "Sloppy Joint segment undone."); + warn_if_concave_segments(); + } + else editor_status("Couldn't form sloppy joint.\n"); + } else + editor_status("Attempted to form sloppy joint through connected side -- joint segment not formed (you bozo)."); + } else + editor_status("Could not find close threshold segment -- joint segment not formed."); + + return 1; +} + + +// -------------- Create all sloppy joints within CurrentGroup ------------------ +int CreateSloppyAdjacentJointsGroup() +{ + int adj_side; + segment *adj_sp; + int num_segs = GroupList[current_group].num_segments; + short *segs = GroupList[current_group].segments; + segment *segp; + int done_been_a_change = 0; + int segind, sidenum; + + for (segind=0; segindchildren[sidenum])) + if (med_find_closest_threshold_segment_side(segp, sidenum, &adj_sp, &adj_side, 5*F1_0)) { + if (adj_sp->group == segp->group) { + if (segp->children[sidenum] != adj_sp-Segments) + if (!med_form_joint(segp, sidenum, adj_sp,adj_side)) + done_been_a_change = 1; + } + } + } + + if (done_been_a_change) { + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + autosave_mine(mine_filename); + diagnostic_message("Sloppy Joint segment formed."); + strcpy(undo_status[Autosave_count], "Sloppy Joint segment undone."); + warn_if_concave_segments(); + } + + return 1; +} + + +// ---------- Create a bridge segment between current segment and all adjacent segment:side ---------- +int CreateAdjacentJointsSegment() +{ + int adj_side,s; + segment *adj_sp; + + med_combine_duplicate_vertices(Vertex_active); + + for (s=0; schildren[s] != adj_sp-Segments) + { + med_form_joint(Cursegp,s,adj_sp,adj_side); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + autosave_mine(mine_filename); + diagnostic_message("Adjacent Joint segment formed."); + strcpy(undo_status[Autosave_count], "Adjacent Joint segment UNDONE."); + warn_if_concave_segments(); + } + } + + return 1; +} + +// ---------- Create a bridge segment between all segment:side and all adjacent segment:side ---------- +int CreateAdjacentJointsAll() +{ + int adj_side,seg,s; + segment *adj_sp; + + med_combine_duplicate_vertices(Vertex_active); + + for (seg=0; seg<=Highest_segment_index; seg++) + for (s=0; s + +#include "inferno.h" +#include "editor.h" +#include "kdefs.h" + +static fix r1scale, r4scale; +static int curve; + +int InitCurve() +{ + curve = 0; + return 1; +} + +int GenerateCurve() +{ + if ( (Markedsegp != 0) && !IS_CHILD(Markedsegp->children[Markedside])) { + r1scale = r4scale = F1_0*20; + autosave_mine( mine_filename ); + diagnostic_message("Curve Generated."); + Update_flags |= UF_WORLD_CHANGED; + curve = generate_curve(r1scale, r4scale); + mine_changed = 1; + if (curve == 1) { + strcpy(undo_status[Autosave_count], "Curve Generation UNDONE.\n"); + } + if (curve == 0) diagnostic_message("Cannot generate curve -- check Current segment."); + } + else diagnostic_message("Cannot generate curve -- check Marked segment."); + warn_if_concave_segments(); + + return 1; +} + +int DecreaseR4() +{ + if (curve) { + Update_flags |= UF_WORLD_CHANGED; + delete_curve(); + r4scale -= F1_0; + generate_curve(r1scale, r4scale); + diagnostic_message("R4 vector decreased."); + mine_changed = 1; + warn_if_concave_segments(); + } + return 1; +} + +int IncreaseR4() +{ + if (curve) { + Update_flags |= UF_WORLD_CHANGED; + delete_curve(); + r4scale += F1_0; + generate_curve(r1scale, r4scale); + diagnostic_message("R4 vector increased."); + mine_changed = 1; + warn_if_concave_segments(); + } + return 1; +} + +int DecreaseR1() +{ + if (curve) { + Update_flags |= UF_WORLD_CHANGED; + delete_curve(); + r1scale -= F1_0; + generate_curve(r1scale, r4scale); + diagnostic_message("R1 vector decreased."); + mine_changed = 1; + warn_if_concave_segments(); + } + return 1; +} + +int IncreaseR1() +{ + if (curve) { + Update_flags |= UF_WORLD_CHANGED; + delete_curve(); + r1scale += F1_0; + generate_curve(r1scale, r4scale); + diagnostic_message("R1 vector increased."); + mine_changed = 1; + warn_if_concave_segments(); + } + return 1; +} + +int DeleteCurve() +{ +// fix_bogus_uvs_all(); +set_average_light_on_curside(); + + if (curve) { + Update_flags |= UF_WORLD_CHANGED; + delete_curve(); + curve = 0; + mine_changed = 1; + diagnostic_message("Curve Deleted."); + warn_if_concave_segments(); + } + return 1; +} + +int SetCurve() +{ + if (curve) curve = 0; + //autosave_mine( mine_filename ); + //strcpy(undo_status[Autosave_count], "Curve Generation UNDONE.\n"); + return 1; +} + diff --git a/main/editor/kfuncs.c b/main/editor/kfuncs.c new file mode 100644 index 00000000..a5a75958 --- /dev/null +++ b/main/editor/kfuncs.c @@ -0,0 +1,498 @@ +/* +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/kfuncs.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * . + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:23 donut + * Import of d1x 1.37 source. + * + * Revision 2.1 1995/03/08 16:07:23 yuan + * Added segment sizing default functions. + * + * Revision 2.0 1995/02/27 11:34:45 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.112 1995/01/12 12:10:31 yuan + * Added coop object capability. + * + * Revision 1.111 1994/11/27 23:17:16 matt + * Made changes for new mprintf calling convention + * + * Revision 1.110 1994/11/23 12:17:22 mike + * bind retmap functions. + * + * Revision 1.109 1994/11/19 15:20:54 mike + * rip out unused code and data. + * + * Revision 1.108 1994/11/17 11:39:02 matt + * Ripped out code to load old mines + * + * Revision 1.107 1994/10/27 10:06:12 mike + * kill macro stuff. + * + * Revision 1.106 1994/10/18 15:31:43 mike + * Bind mine correction function to test keypad, key=1. + * + * Revision 1.105 1994/09/26 23:22:06 matt + * Added functions to keep player's starting position from getting messed up + * + * Revision 1.104 1994/09/24 14:15:41 mike + * Custom colored object support. + * + * Revision 1.103 1994/09/23 18:03:54 yuan + * Finished wall checking code. + * + * Revision 1.102 1994/09/22 19:03:52 mike + * Test function test_shortpos on ctrl-keypad3 + * + * Revision 1.101 1994/09/20 14:35:56 mike + * Bind functions to keypad 2, 3. + * + * Revision 1.100 1994/09/15 22:58:10 matt + * Made new objects be oriented to their segment + * Added keypad function to flip an object upside-down + * + * Revision 1.99 1994/09/14 16:50:50 yuan + * Added load mine only function + * + * Revision 1.98 1994/08/25 21:57:52 mike + * IS_CHILD stuff. + * + * Revision 1.97 1994/08/16 18:10:52 yuan + * Maded C place you in the center of a segment. + * + * Revision 1.96 1994/08/15 17:48:01 yuan + * Added external walls. + * + * Revision 1.95 1994/08/13 17:32:38 mike + * test function. + * + * Revision 1.94 1994/08/05 21:17:57 matt + * Allow two doors to be linked together + * + * Revision 1.93 1994/08/05 18:18:52 matt + * Made object rotation have 4x resolution, and SHIFT+rotate do old resolution. + * + * Revision 1.92 1994/08/03 10:31:06 mike + * Add texture map propagation without uv assignment. + * + * Revision 1.91 1994/08/02 14:17:00 mike + * Clean up dialog boxes, add one for Matt. + * + * Revision 1.90 1994/07/30 17:04:47 mike + * Bind key for max_depth on path testing. + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: kfuncs.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include + +#include "inferno.h" +#include "func.h" +#include "editor/kdefs.h" +#include "segment.h" +#include "editor/editor.h" +#include "error.h" +#include "slew.h" +#include "mono.h" +#include "gamesave.h" +#include "editor/eobject.h" +#include "editor/medwall.h" + +// Test function prototypes (replace Test1, 2 and 3 with whatever function +// you wish to test.) +extern void test_create_path(); +extern void test_create_all_paths(); +extern void test_create_path_many(); +extern void create_all_paths(); +extern void test_create_all_anchors(); +// extern void make_curside_bottom_side(); +extern void move_object_to_mouse_click(); +extern void test_create_n_segment_path(); + +extern void set_all_modes_to_hover(void); + +extern void check_for_overlapping_segments(void); +extern void init_replacements(); + +extern void do_replacements(void); +extern void do_replacements_all(void); + +int Test1() +{ +// { int i; +// for (i=Highest_segment_index+1; i +#include + +#include "inferno.h" +#include "editor.h" +#include "ui.h" +#include "game.h" +#include "gamesave.h" +#include "gameseq.h" + +char game_filename[128] = "*.LVL"; + +extern void checkforext( char * f, char *ext ); + +void checkforgamext( char * f ) +{ + int i; + + for (i=1; ipos; + Perm_player_orient = ConsoleObject->orient; + Perm_player_segnum = ConsoleObject->segnum; + + editor_status("Player initial position set"); + return 0; +} + +// Save game +// returns 1 if successful +// returns 0 if unsuccessful +int SaveGameData() +{ + char Message[200]; + + if (gamestate_not_restored) { + sprintf( Message, "Game State has not been restored...\nContinue?\n"); + if (MessageBox( -2, -2, 2, Message, "NO", "Yes" )==1) + return 0; + } + + if (ui_get_filename( game_filename, "*.LVL", "SAVE GAME" )) { + int saved_flag; + vms_vector save_pos = ConsoleObject->pos; + vms_matrix save_orient = ConsoleObject->orient; + int save_segnum = ConsoleObject->segnum; + + checkforgamext(game_filename); + + if (Perm_player_segnum > Highest_segment_index) + Perm_player_segnum = -1; + + if (Perm_player_segnum!=-1) { + if (get_seg_masks(&Perm_player_position,Perm_player_segnum,0).centermask==0) { + ConsoleObject->pos = Perm_player_position; + obj_relink(ConsoleObject-Objects,Perm_player_segnum); + ConsoleObject->orient = Perm_player_orient; + } + else + Perm_player_segnum=-1; //position was bogus + } + saved_flag=save_level(game_filename); + if (Perm_player_segnum!=-1) { + int found_save_segnum; + + if (save_segnum > Highest_segment_index) + save_segnum = 0; + + ConsoleObject->pos = save_pos; + found_save_segnum = find_point_seg(&save_pos,save_segnum); + if (found_save_segnum == -1) { + compute_segment_center(&save_pos, &(Segments[save_segnum])); + found_save_segnum = save_segnum; + } + + obj_relink(ConsoleObject-Objects,found_save_segnum); + ConsoleObject->orient = save_orient; + } + if (saved_flag) + return 0; + mine_changed = 0; + } + return 1; +} + +// returns 1 if successful +// returns 0 if unsuccessful +int LoadGameData() +{ +if (SafetyCheck()) { + if (ui_get_filename( game_filename, "*.LVL", "LOAD GAME" )) + { + checkforgamext(game_filename); + if (load_level(game_filename)) + return 0; + Current_level_num = 0; //not a real level + gamestate_not_restored = 0; + Update_flags = UF_WORLD_CHANGED; + Perm_player_position = ConsoleObject->pos; + Perm_player_orient = ConsoleObject->orient; + Perm_player_segnum = ConsoleObject->segnum; + } + } + return 1; +} + +//called whenever a new mine is created, so new mine doesn't get name +//of last saved mine as default +void ResetFilename() +{ + strcpy(game_filename,"*.LVL"); +} + diff --git a/main/editor/kgroup.c b/main/editor/kgroup.c new file mode 100644 index 00000000..ce9c3233 --- /dev/null +++ b/main/editor/kgroup.c @@ -0,0 +1,13 @@ +/* +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. +*/ + diff --git a/main/editor/khelp.c b/main/editor/khelp.c new file mode 100644 index 00000000..6fec3663 --- /dev/null +++ b/main/editor/khelp.c @@ -0,0 +1,177 @@ +/* +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/khelp.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions for showing help. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:26 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:27 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.5 1993/12/02 12:39:30 matt + * Removed extra includes + * + * Revision 1.4 1993/11/05 17:32:57 john + * added funcs + * ., + * + * Revision 1.3 1993/11/03 13:42:41 yuan + * Updated help commands + * + * Revision 1.2 1993/10/22 19:48:07 yuan + * added ctrl-shift-keypad comment in help. + * + * Revision 1.1 1993/10/13 18:53:16 john + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: khelp.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include "inferno.h" +#include "editor.h" + +#include "ui.h" + +static char MainHelpText[] = "\nMED General Functions\n\n" \ +"SPACEBAR Full Redraw\n" \ +"BACKSPACE Drop into debugger\n\n" \ +"A Attach a segment\n" \ +"D Delete current segment\n\n" \ +"F Toggle to game\n" \ +"G or S Go to game (Toggle screen)\n\n" \ +"ALT-C Create new mine\n" \ +"ALT-S Save mine\n" \ +"ALT-L Load mine\n"\ +"ESC Exit editor\n"\ +"ALT-Q/CTRL-Q/SHIFT-Q also Exit editor\n"; + +static char SegmentHelpText[] = "MED Segment Functions\n\n" \ +"ALT-B Create Bridge from current to marked segment\n" \ +"ALT-E Exchange current and marked segments\n" \ +"ALT-J Create Joint between current and marked segments\n" \ +"ALT-SHIFT-J Create Joint on current side and adjacent segments\n" \ +"ALT-CTRL-J Create Joint on current segment and adjacent segments\n" \ +"ALT-CTRL-SHIFT-J Create Joints on all adjacent segments\n" \ +"ALT-M Mark current segment and side\n" \ +"ALT-N Create default segment for New_segment\n" \ +"CTRL-A Toggle - Draw all segments/Draw connected segments\n" \ +"CTRL-C Clear selected list\n" \ +"CTRL-D Toggle display of coordinate axes\n" \ +"CTRL-S Advance to segment through Curside\n" \ +"ALT-T Assign Texture to current side\n" \ +"CTRL-P Propogate Textures\n" \ +"CTRL-SHIFT-P Propogate Textures on Selected segments\n" \ +"CTRL-SHIFT-S Advance to segment opposite Curside\n" \ +"CTRL-F Select next side\n" \ +"CTRL-SHIFT-F Select previous side\n"; + +static char KeyPadHelpText[] = "MED KeyPad Functions\n\n" \ + +"SHIFT-KEYPAD FUNCTIONS (Change direction vector of segment)\n" \ +"----------------------\n" \ +"(7) 8 Decrease Pitch (9)\n" \ +" 4 Decrease Heading (5) 6 Increase Heading\n" \ +" 1 Decrease Bank 2 Increase Pitch 3 Increase Bank\n\n" \ + +"CTRL-KEYPAD FUNCTIONS (Change size/shape of segment)\n" \ +"---------------------\n" \ +"(7) 8 Increase Length 9 Increase Height\n" \ +" 4 Decrease Width (5) 6 Increase Width\n" \ +"(1) 2 Decrease Length 3 Decrease Height\n"\ +"\nIn addition, CTRL-SHIFT-KEYPAD Changes size at x5 rate as above\n"; + + +char ViewHelpText[] = "MED View Changing Functions\n\n" \ +"ALT-V Change to orthogonal view (1,2,3)\n" \ +"CTRL-V Toggle view to current segment\n" \ +"MINUS (-) Zoom in\n" \ +"EQUAL (=) Zoom out\n" \ +"SHIFT-MINUS Decrease viewer distance\n" \ +"SHIFT-EQUAL Increase viewer distance\n" \ +"\n* Holding the Ctrl key and moving the mouse will change\n" \ +"the viewer's orientation in the main window."; + +//"CTRL-MINUS Decreases drawing depth\n" +//"CTRL-EQUAL Increases drawing depth\n" + +static char GameHelpText[] = "MED Game Screen Functions\n\n" \ +"KEYPAD FUNCTIONS (Moves in game screen)\n" \ +"----------------\n" \ +"(7) 8 Move Forward (9)\n" \ +" 4 Decrease Heading 5 Complete Stop 6 Increase Heading\n" \ +" 1 Decrease Bank 2 Move Backward 3 Increase Bank\n\n" \ +"[ Decreases Pitch\n" \ +"] Increases Pitch\n" \ +"C Set Player from Current segment\n" \ +"L Toggle Lock Step\n" \ +"O Toggle Outline Mode\n" \ +"SHIFT-C Set PLayer from Current segment-1\n" \ +"SHIFT-L Toggle Lighting effect\n" \ +"NUMLOCK Reset orientation\n" \ +"PAD DIVIDE (/) Game Zoom out\n" \ +"PAD MULTIPLY (*) Game Zoom In\n"; + +static char CurveHelpText[] = "MED Curve Generation Functions\n\n" \ +"ALT-F10 Generate curve\n" \ +"F8 Delete curve\n" \ +"F11 'Set' curve\n" \ +"F9 Decrease r1 vector\n" \ +"SHIFT-F9 Increase r1 vector\n" \ +"F10 Decrease r4 vector\n" \ +"SHIFT-F10 Increase r4 vector\n"; + +static char MacrosHelpText[] = "MED Macros Functions\n\n" \ +"CTRL-INSERT Play fast\n" \ +"CTRL-DELETE Play normal\n" \ +"CTRL-HOME Record all\n" \ +"CTRL-END Record keys\n" \ +"CTRL-PAGEUP Save Macro\n" \ +"CTRL-PAGEDOWN Load Macro\n"; + +int DoHelp() +{ + int help_key = 2; + int more_key = 2; + while (help_key > 1) + { + help_key = MessageBox( -2, -2, 5, MainHelpText, "Ok", "Segment", "Keypad", "View", "More"); + if (help_key == 2) + MessageBox( -2, -2, 1, SegmentHelpText, "Ok" ); + if (help_key == 3) + MessageBox( -2, -2, 1, KeyPadHelpText, "Ok" ); + if (help_key == 4) + MessageBox( -2, -2, 1, ViewHelpText, "Ok" ); + if (help_key == 5) { + more_key = MessageBox( -2, -2, 4, MainHelpText, "Back", "Curve", "Macro", "Game"); + if (more_key == 2) + MessageBox( -2, -2, 1, CurveHelpText, "Ok" ); + if (help_key == 3) + MessageBox( -2, -2, 1, MacrosHelpText, "Ok" ); + if (help_key == 4) + MessageBox( -2, -2, 1, GameHelpText, "Ok" ); + } + } + return 1; +} diff --git a/main/editor/kmine.c b/main/editor/kmine.c new file mode 100644 index 00000000..72424b2c --- /dev/null +++ b/main/editor/kmine.c @@ -0,0 +1,462 @@ +/* +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/kmine.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions to change entire mines. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:28 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:22 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.53 1995/02/22 15:04:52 allender + * remove anonymous unions from vecmat stuff + * + * Revision 1.52 1994/11/27 23:17:13 matt + * Made changes for new mprintf calling convention + * + * Revision 1.51 1994/11/17 14:48:05 mike + * validation functions moved from editor to game. + * + * Revision 1.50 1994/11/17 11:38:49 matt + * Ripped out code to load old mines + * + * Revision 1.49 1994/10/08 17:10:22 matt + * Correctly set current_level_num when loading/creating mine in editor + * + * Revision 1.48 1994/10/03 11:30:45 matt + * Fixed problem with permanant player position when creating a new mine + * + * Revision 1.47 1994/09/29 17:42:19 matt + * Cleaned up game_mode a little + * + * Revision 1.46 1994/08/18 10:48:21 john + * Cleaned up game sequencing. + * + * Revision 1.45 1994/08/09 16:05:36 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.44 1994/07/22 12:37:06 matt + * Cleaned up editor/game interactions some more. + * + * Revision 1.43 1994/07/21 17:26:50 matt + * When new mine created, the default save filename is now reset + * + * Revision 1.42 1994/06/08 14:29:25 matt + * Took out support for old mine versions + * + * Revision 1.41 1994/06/03 12:28:04 yuan + * Fixed game restore state. + * + * Revision 1.40 1994/05/19 12:10:29 matt + * Use new vecmat macros and globals + * + * Revision 1.39 1994/05/14 17:17:56 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.38 1994/05/12 14:47:47 mike + * New previous mine structure and object structure. + * + * Revision 1.37 1994/05/06 12:52:12 yuan + * Adding some gamesave checks... + * + * Revision 1.36 1994/05/05 20:37:02 yuan + * Added gamesave checks when entering and leaving the game. + * + * Removed Load Game Save Game functions... + * Now there is only Load/Save Mine... (equivalent to old Load/Save Game) + * + * Revision 1.35 1994/04/27 22:57:54 matt + * Made sit mine load from path of sit file + * + * Revision 1.34 1994/04/21 18:29:55 matt + * Don't use same variable for mine filename & sit filename + * + * Revision 1.33 1994/04/21 18:21:43 matt + * Strip path from mine filename in sit file + * + * Revision 1.32 1994/04/18 10:54:35 mike + * Add situation save/load + * + * Revision 1.31 1994/02/16 16:47:54 yuan + * Removed temp.min. + * + * Revision 1.30 1994/02/16 15:22:51 yuan + * Checking in for editor make. + * + * Revision 1.29 1994/02/09 15:04:23 yuan + * brought back save ability + * + * Revision 1.28 1994/02/08 12:42:45 yuan + * fixed log. + * + * Revision 1.27 1994/02/08 12:41:47 yuan + * Crippled save mine function from demo version. + * + * Revision 1.26 1994/01/13 13:26:05 yuan + * Added med_compress_mine when creating new mine or + * when loading mine + * + * Revision 1.25 1994/01/11 12:03:23 yuan + * Fixed so that when old mine implementation not in, + * message is displayed when you try to load an old mine + * + * Revision 1.24 1994/01/11 11:47:57 yuan + * *** empty log message *** + * + * Revision 1.23 1994/01/05 09:59:56 yuan + * Added load old mine funciton + * + * Revision 1.22 1993/12/16 15:58:08 john + * moved texture selection page to texpage.c + * , + * + * Revision 1.21 1993/12/10 14:48:55 mike + * Kill orthogonal views. + * + * Revision 1.20 1993/12/03 16:44:06 yuan + * Changed some 0.0 return values to 0 + * + * + * Revision 1.19 1993/12/02 12:39:34 matt + * Removed extra includes + * + * Revision 1.18 1993/11/17 13:14:48 yuan + * Moved Save Group to group.c + * + * Revision 1.17 1993/11/16 17:25:48 yuan + * Unworking group function added... + * + * Revision 1.16 1993/11/15 14:46:25 john + * Changed Menu to MenuX + * + * Revision 1.15 1993/11/08 19:13:45 yuan + * Added Undo command (not working yet) + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: kmine.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include + +#include "error.h" + +#include "inferno.h" +#include "editor.h" +#include "ui.h" +#include "texpage.h" // For texpage_goto_first +#include "segment.h" +#include "mono.h" +#include "kdefs.h" +#include "info.h" +#include "game.h" +#include "gameseq.h" + +#include "nocfile.h" + +#include "object.h" + +#define MINESAVE_CRIPPLED 0 + +char mine_filename[128] = "*.MIN"; +char sit_filename[128] = "*.SIT"; + +#define MAX_NAME_LENGTH 128 + +// See if filename f contains an extent. If not, add extent ext. +void checkforext( char * f, char *ext ) +{ + int i; + + for (i=1; isegnum); +//@@ +//@@ cfclose( LoadFile ); +//@@ +//@@ ConsoleObject->pos = pos; +//@@ ConsoleObject->orient.m1 = mat[0]; ConsoleObject->orient.m2 = mat[1]; ConsoleObject->orient.m3 = mat[2]; +//@@ ConsoleObject->orient.m4 = mat[3]; ConsoleObject->orient.m5 = mat[4]; ConsoleObject->orient.m6 = mat[5]; +//@@ ConsoleObject->orient.m7 = mat[6]; ConsoleObject->orient.m8 = mat[7]; ConsoleObject->orient.m9 = mat[8]; +//@@ +//@@ return 0; +} + +// ----------------------------------------------------------------------------- +int med_save_situation(char * filename) +{ + CFILE * SaveFile; + char mine_name[MAX_NAME_LENGTH]; + + SaveFile = cfopen( filename, "wt" ); + if (!SaveFile) { + char ErrorMessage[200]; + + sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename ); + MessageBox( -2, -2, 1, ErrorMessage, "Ok" ); + return 1; + } + + // Write mine name. +// strcpy(mine_name, filename); +#ifndef __LINUX__ +_splitpath(filename,NULL,NULL,mine_name,NULL); +#endif + set_extension(mine_name, "min"); + fprintf(SaveFile, "%s\n", mine_name); + + // Write player position. + fprintf(SaveFile, "%x %x %x\n",(unsigned int) ConsoleObject->pos.x,(unsigned int) ConsoleObject->pos.y,(unsigned int) ConsoleObject->pos.z); + + // Write player orientation. + fprintf(SaveFile, "%8x %8x %8x\n",(unsigned int) ConsoleObject->orient.rvec.x,(unsigned int) ConsoleObject->orient.rvec.y,(unsigned int) ConsoleObject->orient.rvec.z); + fprintf(SaveFile, "%8x %8x %8x\n",(unsigned int) ConsoleObject->orient.uvec.x,(unsigned int) ConsoleObject->orient.uvec.y,(unsigned int) ConsoleObject->orient.uvec.z); + fprintf(SaveFile, "%8x %8x %8x\n",(unsigned int) ConsoleObject->orient.fvec.x,(unsigned int) ConsoleObject->orient.fvec.y,(unsigned int) ConsoleObject->orient.fvec.z); + fprintf(SaveFile, "%i\n", ConsoleObject->segnum); + + mprintf((0, "Save Position = %8x %8x %8x\n", ConsoleObject->pos.x, ConsoleObject->pos.y, ConsoleObject->pos.z)); + mprintf((0, "\n")); + + mprintf((0, "%8x %8x %8x\n", ConsoleObject->orient.rvec.x, ConsoleObject->orient.rvec.y, ConsoleObject->orient.rvec.z)); + mprintf((0, "%8x %8x %8x\n", ConsoleObject->orient.uvec.x, ConsoleObject->orient.uvec.y, ConsoleObject->orient.uvec.z)); + mprintf((0, "%8x %8x %8x\n", ConsoleObject->orient.fvec.x, ConsoleObject->orient.fvec.y, ConsoleObject->orient.fvec.z)); + mprintf((0, "\n")); + + cfclose( SaveFile); + + return 1; +} + +// ----------------------------------------------------------------------------- +int SaveSituation(void) +{ + if (ui_get_filename( sit_filename, "*.SIT", "Save Situation" )) { + set_extension(sit_filename, "MIN"); + if (med_save_mine(sit_filename)) { + mprintf((0, "Unable to save mine in SaveSituation.\n")); + return 0; + } + + set_extension(sit_filename, "SIT"); + if (med_save_situation(sit_filename)) + return 0; + } + + return 1; +} + +// ----------------------------------------------------------------------------- +// Load a situation file which consists of x,y,z, orientation matrix, mine name. +int LoadSituation(void) +{ + if (SafetyCheck()) { + if (ui_get_filename( sit_filename, "*.sit", "Load Situation" )) { + checkforext(sit_filename, "SIT"); + if (med_load_situation(sit_filename)) + return 0; + // set_view_target_from_segment(Cursegp); + Update_flags = UF_WORLD_CHANGED; + // SetPlayerFromCurseg(); + med_compress_mine(); + init_info = 1; + mine_changed = 0; + } + } + + return 1; +} + diff --git a/main/editor/ksegmove.c b/main/editor/ksegmove.c new file mode 100644 index 00000000..078aa222 --- /dev/null +++ b/main/editor/ksegmove.c @@ -0,0 +1,116 @@ +/* +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/ksegmove.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions for moving segments. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:29 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:33:37 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.5 1993/12/02 12:39:36 matt + * Removed extra includes + * + * Revision 1.4 1993/11/12 16:40:23 mike + * Use rotate_segment_new in place of med_rotate_segment_ang. + * + * Revision 1.3 1993/11/05 17:32:54 john + * added funcs + * ., + * + * Revision 1.2 1993/10/26 11:28:41 mike + * Write common routine SegOrientCommon so all movement can pass + * through the same routine to check for concavity, among other things. + * + * Revision 1.1 1993/10/13 18:53:21 john + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: ksegmove.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +//#include +//#include +//#include +//#include + +#include "inferno.h" +#include "editor.h" + +// -- old -- int SegOrientCommon(fixang *ang, fix val) +// -- old -- { +// -- old -- *ang += val; +// -- old -- med_rotate_segment_ang(Cursegp,&Seg_orientation); +// -- old -- Update_flags |= UF_WORLD_CHANGED; +// -- old -- mine_changed = 1; +// -- old -- warn_if_concave_segment(Cursegp); +// -- old -- return 1; +// -- old -- } + +int SegOrientCommon(fixang *ang, fix val) +{ + Seg_orientation.p = 0; + Seg_orientation.b = 0; + Seg_orientation.h = 0; + + *ang += val; + rotate_segment_new(&Seg_orientation); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + warn_if_concave_segment(Cursegp); + return 1; +} + +// ---------- segment orientation control ---------- + +int DecreaseHeading() +{ + // decrease heading + return SegOrientCommon(&Seg_orientation.h,-512); +} + +int IncreaseHeading() +{ + return SegOrientCommon(&Seg_orientation.h,+512); +} + +int DecreasePitch() +{ + return SegOrientCommon(&Seg_orientation.p,-512); +} + +int IncreasePitch() +{ + return SegOrientCommon(&Seg_orientation.p,+512); +} + +int DecreaseBank() +{ + return SegOrientCommon(&Seg_orientation.b,-512); +} + +int IncreaseBank() +{ + return SegOrientCommon(&Seg_orientation.b,+512); +} diff --git a/main/editor/ksegsel.c b/main/editor/ksegsel.c new file mode 100644 index 00000000..19b0e4f7 --- /dev/null +++ b/main/editor/ksegsel.c @@ -0,0 +1,255 @@ +/* +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/ksegsel.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions for selecting segments + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:30 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:33 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.12 1994/08/25 21:57:02 mike + * IS_CHILD stuff. + * + * Revision 1.11 1994/05/23 14:48:35 mike + * make current segment be add segment. + * + * Revision 1.10 1993/12/06 19:33:43 yuan + * Fixed autosave stuff so that undo restores Cursegp and + * Markedsegp + * + * Revision 1.9 1993/12/02 12:39:37 matt + * Removed extra includes + * + * Revision 1.8 1993/11/12 13:08:17 yuan + * Fixed warning for concave segment so it appears after any + * "less important" diagnostic messages. + * + * Revision 1.7 1993/11/05 17:32:49 john + * added funcs + * ., + * + * Revision 1.6 1993/11/01 09:53:18 mike + * Write functions get_next_segment and get_previous_segment. + * + * Revision 1.5 1993/10/31 18:06:56 mike + * Only set_view_target_from_segment if in that mode. + * + * Revision 1.4 1993/10/28 15:01:09 matt + * Mucked with update flags + * + * Revision 1.3 1993/10/14 18:07:47 mike + * Change use of CONNECTIVITY to MAX_SIDES_PER_SEGMENT + * + * Revision 1.2 1993/10/14 11:47:34 john + * *** empty log message *** + * + * Revision 1.1 1993/10/13 18:53:39 john + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: ksegsel.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include + +#include "inferno.h" +#include "editor/editor.h" + + +// --------------------------------------------------------------------------------------- +// Select previous segment. +// If there is a connection on the side opposite to the current side, then choose that segment. +// If there is no connecting segment on the opposite face, try any segment. +void get_previous_segment(int curseg_num, int curside,int *newseg_num, int *newside) +{ + int s; + + *newseg_num = curseg_num; + + if (IS_CHILD(Segments[curseg_num].children[(int)Side_opposite[curside]])) + *newseg_num = Segments[curseg_num].children[(int)Side_opposite[curside]]; + else // no segment on opposite face, connect to anything + for (s=0; s= MAX_SIDES_PER_SEGMENT) + Curside = 0; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +int SelectPrevSide() +{ + if (--Curside < 0) + Curside = MAX_SIDES_PER_SEGMENT-1; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +// ---------- Copy current segment and side to marked segment and side ---------- + +int CopySegToMarked() +{ + autosave_mine(mine_filename); + strcpy(undo_status[Autosave_count], "Mark Segment UNDONE."); + Markedsegp = Cursegp; + Markedside = Curside; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +// ---------- select absolute face on segment ---------- + +int SelectBottom() +{ + Curside = WBOTTOM; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +int SelectFront() +{ + Curside = WFRONT; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +int SelectTop() +{ + Curside = WTOP; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +int SelectBack() +{ + Curside = WBACK; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +int SelectLeft() +{ + Curside = WLEFT; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + +int SelectRight() +{ + Curside = WRIGHT; + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + return 1; +} + diff --git a/main/editor/ksegsize.c b/main/editor/ksegsize.c new file mode 100644 index 00000000..ccc41d9a --- /dev/null +++ b/main/editor/ksegsize.c @@ -0,0 +1,493 @@ +/* +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/ksegsize.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Functions for sizing segments + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:32 donut + * Import of d1x 1.37 source. + * + * Revision 2.1 1995/03/08 16:07:21 yuan + * Added segment sizing default functions. + * + * Revision 2.0 1995/02/27 11:35:46 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.15 1994/11/17 14:47:42 mike + * validation functions moved from editor to game. + * + * Revision 1.14 1994/08/25 21:57:45 mike + * IS_CHILD stuff. + * + * Revision 1.13 1994/07/18 10:44:43 mike + * Fix uv propagation after segment sizing. + * + * Revision 1.12 1994/05/04 19:16:34 mike + * *** empty log message *** + * + * Revision 1.11 1994/05/03 18:31:00 mike + * Add PerturbCurside. + * + * Revision 1.10 1994/05/03 11:05:14 mike + * Overhaul segment sizing system to allow sizing of non-free vertices, + * and also sizing of vertices on a side, edge or a single vertex. + * + * Revision 1.9 1993/12/12 17:16:00 mike + * Kill some mprintf code. + * + * + * Revision 1.8 1993/12/10 11:10:53 mike + * Fix bugs in tmap propagation in segment sizing. + * + * Revision 1.7 1993/12/06 13:25:30 mike + * Fix bug in setting size of New_segment after segment scale. + * + * Revision 1.6 1993/11/17 18:57:52 mike + * Change scaling to be additive. + * + * Revision 1.5 1993/11/12 16:52:57 mike + * *** empty log message *** + * + * Revision 1.4 1993/11/05 17:32:47 john + * added funcs + * ., + * + * Revision 1.3 1993/10/19 11:22:11 matt + * Removed extra includes + * + * Revision 1.2 1993/10/17 14:17:52 mike + * Add big scale changes for segment. + * + * Revision 1.1 1993/10/13 18:53:01 john + * Initial revision + * + * + */ + +#ifdef RCS +static char rcsid[] = "$Id: ksegsize.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include + +#include "inferno.h" +#include "editor.h" +#include "mono.h" +#include "error.h" +#include "segment.h" +#include "gameseg.h" + +#define XDIM 0 +#define YDIM 1 +#define ZDIM 2 + +#define MAX_MODIFIED_VERTICES 32 +int Modified_vertices[MAX_MODIFIED_VERTICES]; +int Modified_vertex_index = 0; + +// ------------------------------------------------------------------------------------------ +void validate_modified_segments(void) +{ + int v,w,v0,seg; + char modified_segments[MAX_SEGMENTS]; + + for (v=0; v<=Highest_segment_index; v++) + modified_segments[v] = 0; + + for (v=0; vx += fixmul(vp->x,scale_factor)/2; + vertp->y += fixmul(vp->y,scale_factor)/2; + vertp->z += fixmul(vp->z,scale_factor)/2; + + Assert(Modified_vertex_index < MAX_MODIFIED_VERTICES); + Modified_vertices[Modified_vertex_index++] = vertex_ind; +} + +// ------------------------------------------------------------------------------------------ +void scale_vert(segment *sp, int vertex_ind, vms_vector *vp, fix scale_factor) +{ + switch (SegSizeMode) { + case SEGSIZEMODE_FREE: + if (is_free_vertex(vertex_ind)) + scale_vert_aux(vertex_ind, vp, scale_factor); + break; + case SEGSIZEMODE_ALL: + scale_vert_aux(vertex_ind, vp, scale_factor); + break; + case SEGSIZEMODE_CURSIDE: { + int v; + for (v=0; v<4; v++) + if (sp->verts[Side_to_verts[Curside][v]] == vertex_ind) + scale_vert_aux(vertex_ind, vp, scale_factor); + break; + } + case SEGSIZEMODE_EDGE: { + int v; + + for (v=0; v<2; v++) + if (sp->verts[Side_to_verts[Curside][(Curedge+v)%4]] == vertex_ind) + scale_vert_aux(vertex_ind, vp, scale_factor); + break; + } + case SEGSIZEMODE_VERTEX: + if (sp->verts[Side_to_verts[Curside][Curvert]] == vertex_ind) + scale_vert_aux(vertex_ind, vp, scale_factor); + break; + default: + Error("Unsupported SegSizeMode in ksegsize.c/scale_vert = %i\n", SegSizeMode); + } + +} + +// ------------------------------------------------------------------------------------------ +void scale_free_verts(segment *sp, vms_vector *vp, int side, fix scale_factor) +{ + int v; + char *verts; + int vertex_ind; + + verts = Side_to_verts[side]; + + for (v=0; v<4; v++) { + vertex_ind = sp->verts[(int) verts[v]]; + if (SegSizeMode || is_free_vertex(vertex_ind)) + scale_vert(sp, vertex_ind, vp, scale_factor); + } + +} + + +// ----------------------------------------------------------------------------- +// Make segment *sp bigger in dimension dimension by amount amount. +void med_scale_segment_new(segment *sp, int dimension, fix amount) +{ + vms_matrix mat; + + Modified_vertex_index = 0; + + med_extract_matrix_from_segment(sp, &mat); + + switch (dimension) { + case XDIM: + scale_free_verts(sp, &mat.rvec, WLEFT, -amount); + scale_free_verts(sp, &mat.rvec, WRIGHT, +amount); + break; + case YDIM: + scale_free_verts(sp, &mat.uvec, WBOTTOM, -amount); + scale_free_verts(sp, &mat.uvec, WTOP, +amount); + break; + case ZDIM: + scale_free_verts(sp, &mat.fvec, WFRONT, -amount); + scale_free_verts(sp, &mat.fvec, WBACK, +amount); + break; + } + + validate_modified_segments(); +} + +// ------------------------------------------------------------------------------------------ +// Extract a vector from a segment. The vector goes from the start face to the end face. +// The point on each face is the average of the four points forming the face. +void extract_vector_from_segment_side(segment *sp, int side, vms_vector *vp, int vla, int vlb, int vra, int vrb) +{ + vms_vector v1, v2; + + vm_vec_sub(&v1,&Vertices[sp->verts[Side_to_verts[side][vra]]],&Vertices[sp->verts[Side_to_verts[side][vla]]]); + vm_vec_sub(&v2,&Vertices[sp->verts[Side_to_verts[side][vrb]]],&Vertices[sp->verts[Side_to_verts[side][vlb]]]); + vm_vec_add(vp, &v1, &v2); + + vm_vec_scale(vp, F1_0/2); +} + +// ------------------------------------------------------------------------------------------ +// Extract the right vector from segment *sp, return in *vp. +// The forward vector is defined to be the vector from the the center of the left face of the segment +// to the center of the right face of the segment. +void med_extract_right_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp) +{ + extract_vector_from_segment_side(sp, sidenum, vp, 3, 2, 0, 1); +} + +// ------------------------------------------------------------------------------------------ +// Extract the up vector from segment *sp, return in *vp. +// The forward vector is defined to be the vector from the the center of the bottom face of the segment +// to the center of the top face of the segment. +void med_extract_up_vector_from_segment_side(segment *sp, int sidenum, vms_vector *vp) +{ + extract_vector_from_segment_side(sp, sidenum, vp, 1, 2, 0, 3); +} + + +// ----------------------------------------------------------------------------- +// Increase the size of Cursegp in dimension dimension by amount +int segsize_common(int dimension, fix amount) +{ + int i; + int propagated[MAX_SIDES_PER_SEGMENT]; + vms_vector uvec, rvec, fvec, scalevec; + + Degenerate_segment_found = 0; + + med_scale_segment_new(Cursegp, dimension, amount); + + 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); + + if (Degenerate_segment_found) { + Degenerate_segment_found = 0; + // mprintf(0, "Applying scale would create degenerate segments. Aborting scale.\n"); + editor_status("Applying scale would create degenerate segments. Aborting scale."); + med_scale_segment_new(Cursegp, dimension, -amount); + return 1; + } + + med_create_new_segment(&scalevec); + + // For all segments to which Cursegp is connected, propagate tmap (uv coordinates) from the connected + // segment back to Cursegp. This will meaningfully propagate uv coordinates to all sides which havve + // an incident edge. It will also do some sides more than once. And it is probably just not what you want. + for (i=0; ichildren[i])) { + int s; + for (s=0; schildren[i]],Cursegp,1); + } + + // Now, for all sides that were not adjacent to another side, and therefore did not get tmaps + // propagated to them, treat as a back side. + for (i=0; i SEGSIZEMODE_MAX) + SegSizeMode = SEGSIZEMODE_MIN; + + return 1; +} + +// --------------------------------------------------------------------------- +int PerturbCursideCommon(fix amount) +{ + int saveSegSizeMode = SegSizeMode; + vms_vector fvec, rvec, uvec; + fix fmag, rmag, umag; + int v; + + SegSizeMode = SEGSIZEMODE_CURSIDE; + + Modified_vertex_index = 0; + + extract_forward_vector_from_segment(Cursegp, &fvec); + extract_right_vector_from_segment(Cursegp, &rvec); + extract_up_vector_from_segment(Cursegp, &uvec); + + fmag = vm_vec_mag(&fvec); + rmag = vm_vec_mag(&rvec); + umag = vm_vec_mag(&uvec); + + for (v=0; v<4; v++) { + vms_vector perturb_vec; + + perturb_vec.x = fixmul(rmag, d_rand()*2 - 32767); + perturb_vec.y = fixmul(umag, d_rand()*2 - 32767); + perturb_vec.z = fixmul(fmag, d_rand()*2 - 32767); + + scale_vert(Cursegp, Cursegp->verts[Side_to_verts[Curside][v]], &perturb_vec, amount); + } + +// validate_segment(Cursegp); +// if (SegSizeMode) { +// for (i=0; ichildren[i] != -1) +// validate_segment(&Segments[Cursegp->children[i]]); +// } + + validate_modified_segments(); + SegSizeMode = saveSegSizeMode; + + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + + return 1; +} + +// --------------------------------------------------------------------------- +int PerturbCurside(void) +{ + PerturbCursideCommon(F1_0/10); + + return 1; +} + +// --------------------------------------------------------------------------- +int PerturbCursideBig(void) +{ + PerturbCursideCommon(F1_0/2); + + return 1; +} diff --git a/main/editor/ktmap.c b/main/editor/ktmap.c new file mode 100644 index 00000000..8d2b3388 --- /dev/null +++ b/main/editor/ktmap.c @@ -0,0 +1,285 @@ +/* +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/ktmap.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Texture map key bindings. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:34 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:37 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.26 1994/08/25 21:57:12 mike + * IS_CHILD stuff. + * + * Revision 1.25 1994/08/03 10:32:41 mike + * Texture map stretching. + * + * Revision 1.24 1994/05/14 17:17:35 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.23 1994/04/28 10:48:38 yuan + * Fixed undo message for Clear Texture. + * + * Revision 1.22 1994/04/22 17:45:42 john + * MAde top 2 bits of paste-ons pick the + * orientation of the bitmap. + * + * Revision 1.21 1994/04/01 14:36:08 yuan + * Fixed propogate function so you can propogate and move. + * + * Revision 1.20 1994/03/19 17:22:08 yuan + * Wall system implemented until specific features need to be added... + * (Needs to be hammered on though.) + * + * Revision 1.19 1994/02/14 12:06:12 mike + * change segment data structure. + * + * Revision 1.18 1994/01/25 17:58:47 yuan + * Added ambient lighting, and also added fixing bogus segments + * functions to the editor... (they don't work fully... need to + * check out seguvs.c + * + * Revision 1.17 1994/01/24 11:54:52 yuan + * Checking everything in + * + * Revision 1.16 1994/01/18 16:05:57 yuan + * Added clear texture 2 function (shift 0) + * + * Revision 1.15 1994/01/18 10:15:01 yuan + * added texture stuff + * + * Revision 1.14 1993/12/06 19:33:57 yuan + * Fixed autosave stuff so that undo restores Cursegp and + * Markedsegp + * + * Revision 1.13 1993/12/02 12:39:39 matt + * Removed extra includes + * + * Revision 1.12 1993/11/28 17:31:34 mike + * Use new segment data structure. + * + * Revision 1.11 1993/11/12 16:38:37 mike + * Change call to med_propagate_tmaps_to_segments to include new uv_only_flag parameter. + * + * Revision 1.10 1993/11/11 15:53:30 yuan + * Fixed undo display message + * + * Revision 1.9 1993/11/08 19:13:46 yuan + * Added Undo command (not working yet) + * + * Revision 1.8 1993/11/05 17:32:48 john + * added funcs + * ., + * + * Revision 1.7 1993/11/02 10:31:08 mike + * Add PropagateTexturesSelected. + * + * Revision 1.6 1993/10/29 11:43:15 mike + * Write PropagateTextures + * + * Revision 1.5 1993/10/25 13:26:39 mike + * Force redraw whenever a texture map is assigned. + * + * Revision 1.4 1993/10/15 17:42:53 mike + * Make AssignTexture also assign texture maps to New_segment. + * + * Revision 1.3 1993/10/15 13:10:24 mike + * Adapt AssignTexture to new segment structure. + * + * Revision 1.2 1993/10/14 18:09:17 mike + * Debug code for AssignTexture and comment out code. + * + * Revision 1.1 1993/10/14 14:01:49 mike + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: ktmap.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include + +#include "inferno.h" +#include "editor.h" +#include "mono.h" +#include "kdefs.h" + +// Assign CurrentTexture to Curside in *Cursegp +int AssignTexture(void) +{ + autosave_mine( mine_filename ); + strcpy(undo_status[Autosave_count], "Assign Texture UNDONE."); + + Cursegp->sides[Curside].tmap_num = CurrentTexture; + + New_segment.sides[Curside].tmap_num = CurrentTexture; + +// propagate_light_intensity(Cursegp, Curside, CurrentTexture, 0); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// Assign CurrentTexture to Curside in *Cursegp +int AssignTexture2(void) +{ + int texnum, orient, ctexnum, newtexnum; + + autosave_mine( mine_filename ); + strcpy(undo_status[Autosave_count], "Assign Texture 2 UNDONE."); + + texnum = Cursegp->sides[Curside].tmap_num2 & 0x3FFF; + orient = ((Cursegp->sides[Curside].tmap_num2 & 0xC000) >> 14) & 3; + ctexnum = CurrentTexture; + + if ( ctexnum == texnum ) { + orient = (orient+1) & 3; + newtexnum = (orient<<14) | texnum; + } else { + newtexnum = ctexnum; + } + + Cursegp->sides[Curside].tmap_num2 = newtexnum; + New_segment.sides[Curside].tmap_num2 = newtexnum; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int ClearTexture2(void) +{ + autosave_mine( mine_filename ); + strcpy(undo_status[Autosave_count], "Clear Texture 2 UNDONE."); + + Cursegp->sides[Curside].tmap_num2 = 0; + + New_segment.sides[Curside].tmap_num2 = 0; + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + + +// -------------------------------------------------------------------------------------------------- +// Propagate textures from Cursegp through Curside. +// If uv_flag !0, then only propagate uv coordinates (if 0, then propagate textures as well) +// If move_flag !0, then move forward to new segment after propagation, else don't +int propagate_textures_common(int uv_flag, int move_flag) +{ + autosave_mine( mine_filename ); + strcpy(undo_status[Autosave_count], "Propogate Textures UNDONE."); + + if (IS_CHILD(Cursegp->children[Curside])) + med_propagate_tmaps_to_segments(Cursegp, &Segments[Cursegp->children[Curside]], uv_flag); + + if (move_flag) + SelectCurrentSegForward(); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// Propagate texture maps from current segment, through current side +int PropagateTextures(void) +{ + return propagate_textures_common(0, 0); +} + +// Propagate texture maps from current segment, through current side +int PropagateTexturesUVs(void) +{ + return propagate_textures_common(-1, 0); +} + +// Propagate texture maps from current segment, through current side +// And move to that segment. +int PropagateTexturesMove(void) +{ + return propagate_textures_common(0, 1); +} + +// Propagate uv coordinate from current segment, through current side +// And move to that segment. +int PropagateTexturesMoveUVs(void) +{ + return propagate_textures_common(-1, 1); +} + + +// ------------------------------------------------------------------------------------- +int is_selected_segment(int segnum) +{ + int i; + + for (i=0; ichildren[side])) { + while ((!Been_visited[sp->children[side]]) && is_selected_segment(sp->children[side])) { + med_propagate_tmaps_to_segments(sp,&Segments[sp->children[side]],0); + pts_aux(&Segments[sp->children[side]]); + } + } + } +} + +// ------------------------------------------------------------------------------------- +// Propagate texture maps from current segment recursively exploring all children, to all segments in Selected_list +// until a segment not in Selected_list is reached. +int PropagateTexturesSelected(void) +{ + int i; + + autosave_mine( mine_filename ); + strcpy(undo_status[Autosave_count], "Propogate Textures Selected UNDONE."); + + for (i=0; iev_zoom = fixmul(current_view->ev_zoom,62259); + current_view->ev_changed = 1; + return 1; +} + +int ZoomOut() +{ + if (!current_view) return 0.0; + + current_view->ev_zoom = fixmul(current_view->ev_zoom,68985); + current_view->ev_changed = 1; + return 1; +} + +// ---------- distance-of-viewer control on current window ---------- +int MoveCloser() +{ + if (!current_view) return 0.0; + + current_view->ev_dist = fixmul(current_view->ev_dist,62259); + current_view->ev_changed = 1; + return 1; +} + +int MoveAway() +{ + if (!current_view) return 0.0; + + current_view->ev_dist = fixmul(current_view->ev_dist,68985); + current_view->ev_changed = 1; + return 1; +} + +// ---------- Toggle chase mode. ---------- + +int ToggleChaseMode() +{ + Funky_chase_mode = !Funky_chase_mode; + set_view_target_from_segment(Cursegp); + if (Funky_chase_mode == 1) { + diagnostic_message("Chase mode ON."); + } + if (Funky_chase_mode == 0) { + diagnostic_message("Chase mode OFF."); + } + return Funky_chase_mode; +} + diff --git a/main/editor/macro.c b/main/editor/macro.c new file mode 100644 index 00000000..2c4cd4db --- /dev/null +++ b/main/editor/macro.c @@ -0,0 +1,226 @@ +/* +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/macro.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Routines for recording/playing/saving macros + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:35 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:09 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.12 1993/11/15 14:46:37 john + * Changed Menu to MenuX + * + * Revision 1.11 1993/11/05 17:32:44 john + * added funcs + * ., + * + * Revision 1.10 1993/10/28 16:23:20 john + * *** empty log message *** + * + * Revision 1.9 1993/10/28 13:03:12 john + * .. + * + * Revision 1.8 1993/10/25 16:02:35 john + * *** empty log message *** + * + * Revision 1.7 1993/10/22 13:35:29 john + * *** empty log message *** + * + * Revision 1.6 1993/10/21 17:10:09 john + * Fixed bug w/ load macro. + * + * Revision 1.5 1993/10/19 12:58:47 john + * *** empty log message *** + * + * Revision 1.4 1993/10/19 12:55:02 john + * *** empty log message *** + * + * Revision 1.3 1993/10/19 12:49:49 john + * made EventBuffer dynamic, use ReadFile, WriteFile + * + * Revision 1.2 1993/10/15 17:42:20 john + * *** empty log message *** + * + * Revision 1.1 1993/10/15 17:28:06 john + * Initial revision + * + * + */ + + +#pragma off (unreferenced) +static char rcsid[] = "$Id: macro.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#pragma on (unreferenced) + +#include +#include +#include +#include +#include + +#include "inferno.h" +#include "segment.h" +#include "editor.h" + +#include "gr.h" +#include "ui.h" +#include "key.h" +#include "fix.h" +#include "mono.h" +#include "3d.h" +#include "mouse.h" +#include "bm.h" +#include "error.h" +#include "medlisp.h" +#include "cflib.h" + +#include "kdefs.h" + +#include "u_mem.h" + +#define MAX_NUM_EVENTS 10000 + +UI_EVENT * RecordBuffer; + +int MacroNumEvents = 0; +int MacroStatus = 0; + +static char filename[128] = "*.MIN"; + +int MacroRecordAll() +{ + if ( MacroStatus== UI_STATUS_NORMAL ) + { + if (RecordBuffer) free( RecordBuffer ); + MALLOC( RecordBuffer, UI_EVENT, MAX_NUM_EVENTS ); + ui_record_events( MAX_NUM_EVENTS, RecordBuffer, UI_RECORD_MOUSE | UI_RECORD_KEYS ); + MacroStatus = UI_STATUS_RECORDING; + } + return 1; +} + +int MacroRecordKeys() +{ + if ( MacroStatus== UI_STATUS_NORMAL ) + { + if (RecordBuffer) free( RecordBuffer ); + MALLOC( RecordBuffer, UI_EVENT, MAX_NUM_EVENTS ); + ui_record_events( MAX_NUM_EVENTS, RecordBuffer, UI_RECORD_KEYS ); + MacroStatus = UI_STATUS_RECORDING; + } + return 1; +} + +int MacroPlayNormal() +{ + if (MacroStatus== UI_STATUS_NORMAL && MacroNumEvents > 0 && RecordBuffer ) + { + ui_set_playback_speed( 1 ); + ui_play_events_realtime(MacroNumEvents, RecordBuffer); + MacroStatus = UI_STATUS_PLAYING; + } + return 1; +} + +int MacroPlayFast() +{ + if (MacroStatus== UI_STATUS_NORMAL && MacroNumEvents > 0 && RecordBuffer ) + { + ui_mouse_hide(); + ui_play_events_fast(MacroNumEvents, RecordBuffer); + MacroStatus = UI_STATUS_FASTPLAY; + } + return 1; +} + +int MacroSave() +{ + + if (MacroNumEvents < 1 ) + { + MessageBox( -2, -2, 1, "No macro has been defined to save!", "Oops" ); + return 1; + } + + if (ui_get_filename( filename, "*.MAC", "SAVE MACRO" )) { + RecordBuffer[0].type = 7; + RecordBuffer[0].frame = 0; + RecordBuffer[0].data = MacroNumEvents; + WriteFile( filename, RecordBuffer, sizeof(UI_EVENT)*MacroNumEvents ); + } + return 1; +} + +int MacroLoad() +{ + int length; + + if (ui_get_filename( filename, "*.MAC", "LOAD MACRO" )) { + if (RecordBuffer) free( RecordBuffer ); + RecordBuffer = (UI_EVENT *)ReadFile( filename, &length ); + MacroNumEvents = RecordBuffer[0].data; + } + return 1; +} + +void macro_free_buffer() +{ + if ( RecordBuffer ) + free(RecordBuffer); +} + +int MacroMenu() +{ + int x; + char * MenuItems[] = { "Play fast", + "Play normal", + "Record all", + "Record keys", + "Save macro", + "Load macro" }; + + x = MenuX( -1, -1, 6, MenuItems ); + + switch( x ) + { + case 1: + MacroPlayFast(); + break; + case 2: + MacroPlayNormal(); + break; + case 3: + MacroRecordAll(); + break; + case 4: + MacroRecordKeys(); + break; + case 5: // Save + MacroSave(); + break; + case 6: // Load + MacroLoad(); + break; + } + return 1; +} + diff --git a/main/editor/macro.h b/main/editor/macro.h new file mode 100644 index 00000000..972ce136 --- /dev/null +++ b/main/editor/macro.h @@ -0,0 +1,45 @@ +/* +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/macro.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Header for macro.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:38 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:32 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.2 1994/05/14 17:18:19 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.1 1994/05/14 16:38:50 matt + * Initial revision + * + * + */ + + + +#ifndef _MACRO_H +#define _MACRO_H + +void macro_free_buffer(void); + +#endif diff --git a/main/editor/meddraw.c b/main/editor/meddraw.c new file mode 100644 index 00000000..168b1d58 --- /dev/null +++ b/main/editor/meddraw.c @@ -0,0 +1,1069 @@ +/* +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/meddraw.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Med drawing functions. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:50 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:42 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.34 1994/11/09 11:46:30 matt + * Don't draw non-existant special segments + * + * Revision 1.33 1994/10/27 10:06:38 mike + * adapt to no inverse table. + * + * Revision 1.32 1994/10/17 18:06:23 john + * Made net player objects draw in dark green. + * + * Revision 1.31 1994/09/26 16:44:33 yuan + * Colored special segments. + * + * Revision 1.30 1994/09/01 17:02:41 matt + * Redraw pointer after world draw + * + * Revision 1.29 1994/08/25 21:56:21 mike + * IS_CHILD stuff. + * + * Revision 1.28 1994/08/11 18:59:46 mike + * Adapt to new int (vs short) version of gameseg functions. + * + * Revision 1.27 1994/08/09 16:06:03 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.26 1994/07/25 00:03:05 matt + * Various changes to accomodate new 3d, which no longer takes point numbers + * as parms, and now only takes pointers to points. + * + * Revision 1.25 1994/07/09 17:38:13 mike + * comment out mprintf(0, "\n"); + * + * Revision 1.24 1994/07/07 19:34:47 matt + * These changes are mostly Mike's, but I fixed a little bug that caused + * some edges to think they were never used. + * + * Revision 1.23 1994/07/06 16:36:18 mike + * Optionally only draw segment lines which are in only one segment. + * + * Revision 1.22 1994/05/27 10:34:28 yuan + * Added new Dialog boxes for Walls and Triggers. + * + * Revision 1.21 1994/05/14 18:00:56 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.20 1994/05/09 23:35:21 mike + * Change order of drawing found and selected segments. + * + * Revision 1.19 1994/05/05 12:55:38 yuan + * Fixed a bunch of group bugs. + * + * Revision 1.18 1994/05/04 13:07:52 matt + * Made current edge draw in green in wire-frame window + * Also, moved a bunch of color constants here from editor.h + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: meddraw.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#ifdef __MSDOS__ +#include +#endif + +#include "inferno.h" +#include "segment.h" +#include "segpoint.h" +#include "gameseg.h" +#include "gr.h" +#include "ui.h" +#include "editor/editor.h" + +#include "wall.h" +#include "switch.h" + +#include "key.h" +#include "mono.h" +#include "error.h" +#include "medlisp.h" +#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 "fuelcen.h" + +// Colors used in editor for indicating various kinds of segments. +#define SELECT_COLOR BM_XRGB( 63/2 , 41/2 , 0/2) +#define FOUND_COLOR BM_XRGB( 0/2 , 30/2 , 45/2) +#define WARNING_COLOR BM_XRGB( 63/2 , 0/2 , 0/2) +#define AXIS_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) +#define PLAINSEG_COLOR BM_XRGB( 45/2 , 45/2 , 45/2) +#define MARKEDSEG_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) +#define MARKEDSIDE_COLOR BM_XRGB( 0/2 , 63/2 , 63/2) +#define CURSEG_COLOR BM_XRGB( 63/2 , 63/2 , 63/2) +#define CURSIDE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) +#define CUREDGE_COLOR BM_XRGB( 0 , 63/2 , 0 ) +#define GROUPSEG_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) +#define GROUPSIDE_COLOR BM_XRGB( 63/2 , 0/2 , 45/2) +#define GROUP_COLOR BM_XRGB( 0/2 , 45/2 , 0/2) +#define ROBOT_COLOR BM_XRGB( 31 , 0 , 0 ) +#define PLAYER_COLOR BM_XRGB( 0 , 0 , 31 ) + +#define DOUBLE_BUFFER 1 + +int Search_mode=0; //if true, searching for segments at given x,y +int Search_x,Search_y; +int Automap_test=0; // Set to 1 to show wireframe in automap mode. + +void draw_seg_objects(segment *seg) +{ + int objnum; + + for (objnum=seg->objects;objnum!=-1;objnum=Objects[objnum].next) { + object *obj = &Objects[objnum]; + g3s_point sphere_point; + + if ((obj->type==OBJ_PLAYER) && (objnum > 0 )) + gr_setcolor(BM_XRGB( 0, 25, 0 )); + else + gr_setcolor(obj==ConsoleObject?PLAYER_COLOR:ROBOT_COLOR); + + g3_rotate_point(&sphere_point,&obj->pos); + + g3_draw_sphere(&sphere_point,obj->size); + } + +} + +void draw_line(int pnum0,int pnum1) +{ + g3_draw_line(&Segment_points[pnum0],&Segment_points[pnum1]); +} + +// ---------------------------------------------------------------------------- +void draw_segment(segment *seg) +{ + short *svp; + int nv; + g3s_codes cc; + + if (seg->segnum == -1) //this segment doesn't exitst + return; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) { //all off screen? + int i; + + for (i=0;i<4;i++) draw_line(svp[i],svp[i+4]); + + for (i=0;i<3;i++) { + draw_line(svp[i] ,svp[i+1]); + draw_line(svp[i+4],svp[i+4+1]); + } + + draw_line(svp[0],svp[3]); + draw_line(svp[0+4],svp[3+4]); + + } + +} + +//for looking for segment under a mouse click +void check_segment(segment *seg) +{ + short *svp; + int nv; + g3s_codes cc; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) { //all off screen? + int fn; + + gr_setcolor(0); + gr_pixel(Search_x,Search_y); //set our search pixel to color zero + gr_setcolor(1); //and render in color one + + for (fn=0;fn<6;fn++) { + g3s_point *vert_list[4]; + + vert_list[0] = &Segment_points[seg->verts[Side_to_verts[fn][0]]]; + vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][1]]]; + vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][2]]]; + g3_check_and_draw_poly(3,vert_list,NULL,NULL); + + vert_list[1] = &Segment_points[seg->verts[Side_to_verts[fn][2]]]; + vert_list[2] = &Segment_points[seg->verts[Side_to_verts[fn][3]]]; + g3_check_and_draw_poly(3,vert_list,NULL,NULL); + + } + + if (gr_ugpixel(&grd_curcanv->cv_bitmap,Search_x,Search_y) == 1) + { + if (N_found_segs < MAX_FOUND_SEGS) + Found_segs[N_found_segs++] = SEG_PTR_2_NUM(seg); + else + Warning("Found too many segs! (limit=%d)",MAX_FOUND_SEGS); + } + } +} + +// ---------------------------------------------------------------------------- +void draw_seg_side(segment *seg,int side) +{ + short *svp; + int nv; + g3s_codes cc; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) { //all off screen? + int i; + + for (i=0;i<3;i++) + draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][i+1]]); + + draw_line(svp[Side_to_verts[side][i]],svp[Side_to_verts[side][0]]); + + } +} + +void draw_side_edge(segment *seg,int side,int edge) +{ + short *svp; + int nv; + g3s_codes cc; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) //on screen? + draw_line(svp[Side_to_verts[side][edge]],svp[Side_to_verts[side][(edge+1)%4]]); +} + +int Show_triangulations=0; + +//edge types - lower number types have precedence +#define ET_FACING 0 //this edge on a facing face +#define ET_NOTFACING 1 //this edge on a non-facing face +#define ET_NOTUSED 2 //no face uses this edge +#define ET_NOTEXTANT 3 //would exist if side were triangulated + +#define ET_EMPTY 255 //this entry in array is empty + +//colors for those types +//int edge_colors[] = {BM_RGB(45/2,45/2,45/2), +// BM_RGB(45/3,45/3,45/3), //BM_RGB(0,0,45), // +// BM_RGB(45/4,45/4,45/4)}; //BM_RGB(0,45,0)}; // + +int edge_colors[] = { 54, 59, 64 }; + + +typedef struct seg_edge { + union { + struct {short v0,v1;} __pack__ n; + long vv; + }v; + ushort type; + ubyte face_count, backface_count; +} seg_edge; + +#define MAX_EDGES (MAX_VERTICES*4) + +seg_edge edge_list[MAX_EDGES]; + +short used_list[MAX_EDGES]; //which entries in edge_list have been used +int n_used; + +int edge_list_size; //set each frame + +#define HASH(a,b) ((a*5+b) % edge_list_size) + +//define edge numberings +short edges[] = { + 0*8+1, // edge 0 + 0*8+3, // edge 1 + 0*8+4, // edge 2 + 1*8+2, // edge 3 + 1*8+5, // edge 4 + 2*8+3, // edge 5 + 2*8+6, // edge 6 + 3*8+7, // edge 7 + 4*8+5, // edge 8 + 4*8+7, // edge 9 + 5*8+6, // edge 10 + 6*8+7, // edge 11 + + 0*8+5, // right cross + 0*8+7, // top cross + 1*8+3, // front cross + 2*8+5, // bottom cross + 2*8+7, // left cross + 4*8+6, // back cross + +//crosses going the other way + + 1*8+4, // other right cross + 3*8+4, // other top cross + 0*8+2, // other front cross + 1*8+6, // other bottom cross + 3*8+6, // other left cross + 5*8+7, // other back cross +}; + +#define N_NORMAL_EDGES 12 //the normal edges of a box +#define N_EXTRA_EDGES 12 //ones created by triangulation +#define N_EDGES_PER_SEGMENT (N_NORMAL_EDGES+N_EXTRA_EDGES) + +#define swap(a,b) do {int t; t=(a); (a)=(b); (b)=t;} while (0) + +//given two vertex numbers on a segment (range 0..7), tell what edge number it is +int find_edge_num(int v0,int v1) +{ + int i; + short vv; + short *edgep = edges; + + if (v0 > v1) swap(v0,v1); + + vv = v0*8+v1; + +// for (i=0;i v1) swap(v0,v1); + + found = find_edge(v0,v1,&e); + + if (found == -1) { + e->v.n.v0 = v0; + e->v.n.v1 = v1; + e->type = type; + used_list[n_used] = e-edge_list; + if (type == ET_FACING) + edge_list[used_list[n_used]].face_count++; + else if (type == ET_NOTFACING) + edge_list[used_list[n_used]].backface_count++; +//mprintf(0, "Facing count = %i, Not facing count = %i\n", edge_list[used_list[n_used]].face_count, edge_list[used_list[n_used]].backface_count); + n_used++; + } else { + if (type < e->type) + e->type = type; + if (type == ET_FACING) + edge_list[found].face_count++; + else if (type == ET_NOTFACING) + edge_list[found].backface_count++; +//mprintf(0, "Facing count = %i, Not facing count = %i\n", edge_list[found].face_count, edge_list[found].backface_count); + } +} + +//adds a segment's edges to the edge list +void add_edges(segment *seg) +{ + short *svp; + int nv; + g3s_codes cc; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) { //all off screen? + int i,sn,fn,vn; + int flag; + ubyte edge_flags[N_EDGES_PER_SEGMENT]; + + for (i=0;isides[sn]; + int num_faces, num_vertices; + int vertex_list[6]; + + create_all_vertex_lists(&num_faces, vertex_list, seg-Segments, sn); + if (num_faces == 1) + num_vertices = 4; + else + num_vertices = 3; + + for (fn=0; fnverts[vertex_list[fn*3]]],&sidep->normals[fn])) + flag = ET_NOTFACING; + else + flag = ET_FACING; + + v0 = &vertex_list[fn*3]; + + for (vn=0; vnverts[edges[i]/8],seg->verts[edges[i]&7],edge_flags[i]); + + + } +} + +// ---------------------------------------------------------------------------- +void draw_trigger_side(segment *seg,int side) +{ + short *svp; + int nv; + g3s_codes cc; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) { //all off screen? + // Draw diagonals + draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]); + //g3_draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]); + } +} + +// ---------------------------------------------------------------------------- +void draw_wall_side(segment *seg,int side) +{ + short *svp; + int nv; + g3s_codes cc; + + med_get_vertex_list(seg,&nv,&svp); // set nv = number of vertices, svp = pointer to vertex indices + cc=rotate_list(nv,svp); + + if (! cc.and) { //all off screen? + // Draw diagonals + draw_line(svp[Side_to_verts[side][0]],svp[Side_to_verts[side][2]]); + draw_line(svp[Side_to_verts[side][1]],svp[Side_to_verts[side][3]]); + + } +} + +#define WALL_BLASTABLE_COLOR BM_XRGB( 31/2 , 0/2 , 0/2) // RED +#define WALL_DOOR_COLOR BM_XRGB( 0/2 , 0/2 , 31/2) // DARK BLUE +#define WALL_DOOR_LOCKED_COLOR BM_XRGB( 0/2 , 0/2 , 63/2) // BLUE +#define WALL_AUTO_DOOR_COLOR BM_XRGB( 0/2 , 31/2 , 0/2) // DARK GREEN +#define WALL_AUTO_DOOR_LOCKED_COLOR BM_XRGB( 0/2 , 63/2 , 0/2) // GREEN +#define WALL_ILLUSION_COLOR BM_XRGB( 63/2 , 0/2 , 63/2) // PURPLE + +#define TRIGGER_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW +#define TRIGGER_DAMAGE_COLOR BM_XRGB( 63/2 , 63/2 , 0/2) // YELLOW + +// ---------------------------------------------------------------------------------------------------------------- +// Draws special walls (for now these are just removable walls.) +void draw_special_wall( segment *seg, int side ) +{ + gr_setcolor(PLAINSEG_COLOR); + + if (Walls[seg->sides[side].wall_num].type == WALL_BLASTABLE) + gr_setcolor(WALL_BLASTABLE_COLOR); + if (Walls[seg->sides[side].wall_num].type == WALL_DOOR) + gr_setcolor(WALL_DOOR_COLOR); + if (Walls[seg->sides[side].wall_num].type == WALL_ILLUSION) + gr_setcolor(GROUPSIDE_COLOR); + if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED) + gr_setcolor(WALL_DOOR_LOCKED_COLOR); + if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO) + gr_setcolor(WALL_AUTO_DOOR_COLOR); + if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_LOCKED) + if (Walls[seg->sides[side].wall_num].flags & WALL_DOOR_AUTO) + gr_setcolor(WALL_AUTO_DOOR_LOCKED_COLOR); + if (Walls[seg->sides[side].wall_num].type == WALL_OPEN) + gr_setcolor(PLAINSEG_COLOR); + + draw_wall_side(seg,side); + + if (Walls[seg->sides[side].wall_num].trigger != -1) { + int trigger_num; + + trigger_num = Walls[seg->sides[side].wall_num].trigger; + + gr_setcolor(TRIGGER_COLOR); + draw_trigger_side(seg,side); + } + + + gr_setcolor(PLAINSEG_COLOR); +} + + +// ---------------------------------------------------------------------------------------------------------------- +// Recursively parse mine structure, drawing segments. +void draw_mine_sub(int segnum,int depth) +{ + segment *mine_ptr; + + if (Been_visited[segnum]) return; // If segment already drawn, return. + + Been_visited[segnum] = 1; // Say that this segment has been drawn. + + mine_ptr = &Segments[segnum]; + + // If this segment is active, process it, else skip it. + + if (mine_ptr->segnum != -1) { + int side; + + if (Search_mode) check_segment(mine_ptr); + else add_edges(mine_ptr); //add this segments edges to list + + if (depth != 0) { + for (side=0; sidechildren[side])) { + if (mine_ptr->sides[side].wall_num != -1) + draw_special_wall(mine_ptr, side); + draw_mine_sub(mine_ptr->children[side],depth-1); + } + } + } + } +} + +void draw_mine_edges(int automap_flag) +{ + int i,type; + seg_edge *e; + + for (type=ET_NOTUSED;type>=ET_FACING;type--) { + gr_setcolor(edge_colors[type]); + for (i=0;itype == type) + if ((!automap_flag) || (e->face_count == 1)) + draw_line(e->v.n.v0,e->v.n.v1); + } + } +} + +//draws an entire mine +void draw_mine(segment *mine_ptr,int depth) +{ + int i; + + // clear visited list + for (i=0; i<=Highest_segment_index; i++) + Been_visited[i] = 0; + + edge_list_size = min(Num_vertices*4,MAX_EDGES); //make maybe smaller than max + + // clear edge list + for (i=0; i -1) { + gr_setcolor(GROUP_COLOR); + for (s=0; scanvas ) { +// CurrentBigCanvas ^= 1; +// +// gr_set_current_canvas( BigCanvas[CurrentBigCanvas] ); +// +// } else { + gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0, + screen_canvas->cv_bitmap.bm_w,screen_canvas->cv_bitmap.bm_h); + + gr_set_current_canvas(&temp_canvas); +// } +#else + gr_set_current_canvas(screen_canvas); +#endif + + //mprintf(0, "\n"); + + ui_mouse_hide(); + + //g3_set_points(Segment_points,Vertices); + + viewer_position = v->ev_matrix.fvec; + vm_vec_scale(&viewer_position,-v->ev_dist); + + vm_vec_add2(&viewer_position,&Ed_view_target); + + gr_clear_canvas(0); + g3_start_frame(); + g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom); + + render_start_frame(); + + gr_setcolor(PLAINSEG_COLOR); + + // Draw all segments or only connected segments. + // We might want to draw all segments if we have broken the mine into pieces. + if (Draw_all_segments) + draw_mine_all(Segments, Automap_test); + else + draw_mine(mine_ptr,depth); + + // Draw the found segments + if (!Automap_test) { + draw_warning_segments(); + draw_group_segments(); + draw_found_segments(); + draw_selected_segments(); + draw_special_segments(); + + // Highlight group segment and side. + if (current_group > -1) + if (Groupsegp[current_group]) { + gr_setcolor(GROUPSEG_COLOR); + draw_segment(Groupsegp[current_group]); + + gr_setcolor(GROUPSIDE_COLOR); + draw_seg_side(Groupsegp[current_group],Groupside[current_group]); + } + + // Highlight marked segment and side. + if (Markedsegp) { + gr_setcolor(MARKEDSEG_COLOR); + draw_segment(Markedsegp); + + gr_setcolor(MARKEDSIDE_COLOR); + draw_seg_side(Markedsegp,Markedside); + } + + // Highlight current segment and current side. + gr_setcolor(CURSEG_COLOR); + draw_segment(Cursegp); + + gr_setcolor(CURSIDE_COLOR); + draw_seg_side(Cursegp,Curside); + + gr_setcolor(CUREDGE_COLOR); + draw_side_edge(Cursegp,Curside,Curedge); + + // Draw coordinate axes if we are rendering the large view. + if (Show_axes_flag) + if (screen_canvas == LargeViewBox->canvas) + draw_coordinate_axes(); + + // Label the window + gr_set_fontcolor((v==current_view)?CRED:CWHITE, -1 ); + if ( screen_canvas == LargeViewBox->canvas ) { + gr_ustring( 5, 5, "USER VIEW" ); + switch (Large_view_index) { + case 0: gr_ustring( 85, 5, "-- TOP"); break; + case 1: gr_ustring( 85, 5, "-- FRONT"); break; + case 2: gr_ustring( 85, 5, "-- RIGHT"); break; + } + } else +#if ORTHO_VIEWS + else if ( screen_canvas == TopViewBox->canvas ) + gr_ustring( 5, 5, "TOP" ); + else if ( screen_canvas == FrontViewBox->canvas ) + gr_ustring( 5, 5, "FRONT" ); + else if ( screen_canvas == RightViewBox->canvas ) + gr_ustring( 5, 5, "RIGHT" ); +#else + Error("Ortho views have been removed, what gives?\n"); +#endif + + } + + g3_end_frame(); + +#if DOUBLE_BUFFER +// if ( screen_canvas == LargeViewBox->canvas ) { +// if (BigCanvasFirstTime) { +// BigCanvasFirstTime = 0; +// gr_set_current_canvas( screen_canvas ); +// gr_ubitmap( 0, 0, &BigCanvas[CurrentBigCanvas]->cv_bitmap ); +// } else { +// gr_vesa_update( &BigCanvas[CurrentBigCanvas]->cv_bitmap, &screen_canvas->cv_bitmap, &BigCanvas[CurrentBigCanvas ^ 1]->cv_bitmap ); +// } +// } else { + gr_set_current_canvas( screen_canvas ); + gr_ubitmap( 0, 0, &temp_canvas.cv_bitmap ); +// } + +#endif + + ui_mouse_show(); + +} + +//find the segments that render at a given screen x,y +//parms other than x,y are like draw_world +//fills in globals N_found_segs & Found_segs +void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth) +{ + vms_vector viewer_position; + +#if DOUBLE_BUFFER + grs_canvas temp_canvas; + + gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0, + screen_canvas->cv_bitmap.bm_w,screen_canvas->cv_bitmap.bm_h); + + gr_set_current_canvas(&temp_canvas); +#else + gr_set_current_canvas(screen_canvas); +#endif + + ui_mouse_hide(); + + //g3_set_points(Segment_points,Vertices); + + viewer_position = v->ev_matrix.fvec; + vm_vec_scale(&viewer_position,-v->ev_dist); + + vm_vec_add(&viewer_position,&viewer_position,&Ed_view_target); + + g3_start_frame(); + g3_set_view_matrix(&viewer_position,&v->ev_matrix,v->ev_zoom); + + render_start_frame(); + + gr_setcolor(0); + gr_pixel(x,y); + gr_setcolor(1); + + Search_mode = -1; + N_found_segs = 0; + Search_x = x; Search_y = y; + + if (Draw_all_segments) + draw_mine_all(Segments, 0); + else + draw_mine(mine_ptr,depth); + + g3_end_frame(); + + Search_mode = 0; + +} + +void meddraw_init_views( grs_canvas * canvas) +{ + Views[0]->ev_canv = canvas; +#if ORTHO_VIEWS + Views[1]->ev_canv = TopViewBox->canvas; + Views[2]->ev_canv = FrontViewBox->canvas; + Views[3]->ev_canv = RightViewBox->canvas; +#endif +} diff --git a/main/editor/meddraw.h b/main/editor/meddraw.h new file mode 100644 index 00000000..1a0090da --- /dev/null +++ b/main/editor/meddraw.h @@ -0,0 +1,55 @@ +/* +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/meddraw.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Defnts for med drawing stuff + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:38 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:12 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.3 1994/07/06 16:36:54 mike + * Prototype for draw_mine_all. + * + * Revision 1.2 1993/12/17 12:05:09 john + * Took stuff out of med.c; moved into medsel.c, meddraw.c, medmisc.c + * + * Revision 1.1 1993/12/17 08:55:14 john + * Initial revision + * + * + */ + + + +#ifndef _MEDDRAW_H +#define _MEDDRAW_H + + +void meddraw_init_views( grs_canvas * canvas); +void draw_world(grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth); +void find_segments(short x,short y,grs_canvas *screen_canvas,editor_view *v,segment *mine_ptr,int depth); + +// segp = pointer to segments array, probably always Segments. +// automap_flag = 1 if this render is for the automap, else 0 (for editor) +extern void draw_mine_all(segment *segp, int automap_flag); + +#endif diff --git a/main/editor/medlisp.h b/main/editor/medlisp.h new file mode 100644 index 00000000..bb15e7d5 --- /dev/null +++ b/main/editor/medlisp.h @@ -0,0 +1,18 @@ +/* +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. +*/ +int medlisp_init(); +void medlisp_go(); +void medlisp_do_string( char * s, int length, int show_results ); +void medlisp_close(); +int medlisp_attach_function( char * LispFuncName, double (* Cfunction)(void), int NumArgs ); +extern double medlisp_args[]; diff --git a/main/editor/medmisc.c b/main/editor/medmisc.c new file mode 100644 index 00000000..164fbad4 --- /dev/null +++ b/main/editor/medmisc.c @@ -0,0 +1,693 @@ +/* +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/medmisc.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Miscellaneous functions stripped out of med.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:51 donut + * Import of d1x 1.37 source. + * + * Revision 2.1 1995/03/06 15:20:50 john + * New screen mode method. + * + * Revision 2.0 1995/02/27 11:36:40 john + * Version 2.0. Ansi-fied. + * + * Revision 1.31 1994/11/27 23:17:20 matt + * Made changes for new mprintf calling convention + * + * Revision 1.30 1994/11/17 14:48:11 mike + * validation functions moved from editor to game. + * + * Revision 1.29 1994/08/25 21:56:15 mike + * IS_CHILD stuff. + * + * Revision 1.28 1994/08/09 16:06:00 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.27 1994/07/21 17:25:43 matt + * Took out unused func medlisp_create_new_mine() and its prototype + * + * Revision 1.26 1994/07/21 13:27:01 matt + * Cleaned up render code and added error checking + * + * Revision 1.25 1994/07/20 15:32:52 matt + * Added func to call g3_point_2_vec() for texture-mapped window + * + * Revision 1.24 1994/07/15 15:26:53 yuan + * Fixed warning + * + * Revision 1.23 1994/07/14 14:45:16 yuan + * Added function to set default segment and attach. + * + * Revision 1.22 1994/07/14 09:46:34 yuan + * Make E attach segment as well as make default. + * + * + * Revision 1.21 1994/07/11 18:39:17 john + * Reversed y axis roll. + * + * Revision 1.20 1994/07/06 16:36:32 mike + * Add hook for game to render wireframe view: draw_world_from_game. + * + * Revision 1.19 1994/06/24 14:08:31 john + * Changed calling params for render_frame. + * + * Revision 1.18 1994/06/23 15:54:02 matt + * Finished hacking in 3d rendering in big window + * + * Revision 1.17 1994/06/22 00:32:56 matt + * New version, without all the errors of the last version. Sorry. + * + * Revision 1.15 1994/05/23 14:48:54 mike + * make current segment be add segment. + * + * Revision 1.14 1994/05/19 12:09:35 matt + * Use new vecmat macros and globals + * + * Revision 1.13 1994/05/14 17:17:55 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.12 1994/05/09 23:35:06 mike + * Add ClearFoundList, which is probably no longer being called. + * + * Revision 1.11 1994/05/04 14:11:40 mike + * Increase render depth from 4 to 6 by default. + * + * Revision 1.10 1994/04/27 21:00:25 matt + * Made texture-mapped window redraw when editor state variables (such as + * current object) have changed. + * + * Revision 1.9 1994/03/31 12:03:38 matt + * Cleaned up includes + * + * Revision 1.8 1994/02/17 11:31:21 matt + * Changes in object system + * + * Revision 1.7 1994/02/11 11:05:14 yuan + * Make chase mode unsettable... Gives a warning on the mono. + * + * Revision 1.6 1994/01/21 17:37:24 matt + * Moved code from render_frame() to caller, making code cleaner + * + * Revision 1.5 1994/01/11 18:12:43 yuan + * compress_mines removed. Now it is called within + * the gamesave.min save whenever we go into the game. + * + * Revision 1.4 1994/01/05 10:54:15 john + * New object code by John + * + * Revision 1.3 1993/12/29 16:15:27 mike + * Kill scale field from segment struct. + * + * Revision 1.2 1993/12/17 12:05:00 john + * Took stuff out of med.c; moved into medsel.c, meddraw.c, medmisc.c + * + * Revision 1.1 1993/12/17 08:35:47 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: medmisc.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#ifdef __MSDOS__ +#include +#endif + +#include "gr.h" +#include "ui.h" +#include "3d.h" + +#include "u_mem.h" +#include "error.h" +#include "mono.h" +#include "key.h" +#include "func.h" + +#include "inferno.h" +#include "editor/editor.h" +#include "segment.h" + +#include "render.h" +#include "screens.h" +#include "object.h" + +#include "texpage.h" // For texpage_goto_first +#include "meddraw.h" // For draw_World +#include "game.h" + +//return 2d distance, i.e, sqrt(x*x + y*y) +#ifdef __WATCOMC__ +long dist_2d(long x,long y); + +#pragma aux dist_2d parm [eax] [ebx] value [eax] modify [ecx edx] = \ + "imul eax" \ + "xchg ebx,eax" \ + "mov ecx,edx" \ + "imul eax" \ + "add eax,ebx" \ + "adc edx,ecx" \ + "call quad_sqrt"; +#else +#include +long dist_2d(long x,long y) { + return (long)sqrt((double)x * (double)x + (double)y * (double)y); +} +#endif + +// Given mouse movement in dx, dy, returns a 3x3 rotation matrix in RotMat. +// Taken from Graphics Gems III, page 51, "The Rolling Ball" + +void GetMouseRotation( int idx, int idy, vms_matrix * RotMat ) +{ + fix dr, cos_theta, sin_theta, denom, cos_theta1; + fix Radius = i2f(100); + fix dx,dy; + fix dxdr,dydr; + + idy *= -1; + + dx = i2f(idx); dy = i2f(idy); + + dr = dist_2d(dx,dy); + + denom = dist_2d(Radius,dr); + + cos_theta = fixdiv(Radius,denom); + sin_theta = fixdiv(dr,denom); + + cos_theta1 = f1_0 - cos_theta; + + dxdr = fixdiv(dx,dr); + dydr = fixdiv(dy,dr); + + RotMat->rvec.x = cos_theta + fixmul(fixmul(dydr,dydr),cos_theta1); + RotMat->uvec.x = - fixmul(fixmul(dxdr,dydr),cos_theta1); + RotMat->fvec.x = fixmul(dxdr,sin_theta); + + RotMat->rvec.y = RotMat->uvec.x; + RotMat->uvec.y = cos_theta + fixmul(fixmul(dxdr,dxdr),cos_theta1); + RotMat->fvec.y = fixmul(dydr,sin_theta); + + RotMat->rvec.z = -RotMat->fvec.x; + RotMat->uvec.z = -RotMat->fvec.y; + RotMat->fvec.z = cos_theta; + +} + +int Gameview_lockstep; //if set, view is locked to Curseg + +int ToggleLockstep() +{ + Gameview_lockstep = !Gameview_lockstep; + if (Gameview_lockstep == 0) { + if (last_keypress != KEY_L) + diagnostic_message("[L] - Lock mode OFF"); + else + diagnostic_message("Lock mode OFF"); + } + if (Gameview_lockstep) { + if (last_keypress != KEY_L) + diagnostic_message("[L] Lock mode ON"); + else + diagnostic_message("Lock mode ON"); + + Cursegp = &Segments[ConsoleObject->segnum]; + med_create_new_segment_from_cursegp(); + set_view_target_from_segment(Cursegp); + Update_flags = UF_ED_STATE_CHANGED; + } + return Gameview_lockstep; +} + +int medlisp_delete_segment(void) +{ + if (!med_delete_segment(Cursegp)) { + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + autosave_mine(mine_filename); + strcpy(undo_status[Autosave_count], "Delete Segment UNDONE."); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Segment deleted."); + warn_if_concave_segments(); // This could be faster -- just check if deleted segment was concave, warn accordingly + } + + return 1; +} + +int medlisp_scale_segment(void) +{ + vms_matrix rotmat; + vms_vector scale; + + scale.x = fl2f((float) func_get_param(0)); + scale.y = fl2f((float) func_get_param(1)); + scale.z = fl2f((float) func_get_param(2)); + med_create_new_segment(&scale); + med_rotate_segment(Cursegp,vm_angles_2_matrix(&rotmat,&Seg_orientation)); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + + return 1; +} + +int medlisp_rotate_segment(void) +{ + vms_matrix rotmat; + + Seg_orientation.p = func_get_param(0); + Seg_orientation.b = func_get_param(1); + Seg_orientation.h = func_get_param(2); + med_rotate_segment(Cursegp,vm_angles_2_matrix(&rotmat,&Seg_orientation)); + Update_flags |= UF_WORLD_CHANGED | UF_VIEWPOINT_MOVED; + mine_changed = 1; + return 1; +} + +int ToggleLockViewToCursegp(void) +{ + Lock_view_to_cursegp = !Lock_view_to_cursegp; + Update_flags = UF_ED_STATE_CHANGED; + if (Lock_view_to_cursegp) { + if (last_keypress != KEY_V+KEY_CTRLED) + diagnostic_message("[ctrl-V] View locked to Cursegp."); + else + diagnostic_message("View locked to Cursegp."); + set_view_target_from_segment(Cursegp); + } else { + if (last_keypress != KEY_V+KEY_CTRLED) + diagnostic_message("[ctrl-V] View not locked to Cursegp."); + else + diagnostic_message("View not locked to Cursegp."); + } + return Lock_view_to_cursegp; +} + +int ToggleDrawAllSegments() +{ + Draw_all_segments = !Draw_all_segments; + Update_flags = UF_ED_STATE_CHANGED; + if (Draw_all_segments == 1) { + if (last_keypress != KEY_A+KEY_CTRLED) + diagnostic_message("[ctrl-A] Draw all segments ON."); + else + diagnostic_message("Draw all segments ON."); + } + if (Draw_all_segments == 0) { + if (last_keypress != KEY_A+KEY_CTRLED) + diagnostic_message("[ctrl-A] Draw all segments OFF."); + else + diagnostic_message("Draw all segments OFF."); + } + return Draw_all_segments; +} + +int Big_depth=6; + +int IncreaseDrawDepth(void) +{ + Big_depth++; + Update_flags = UF_ED_STATE_CHANGED; + return 1; +} + +int DecreaseDrawDepth(void) +{ + if (Big_depth > 1) { + Big_depth--; + Update_flags = UF_ED_STATE_CHANGED; + } + return 1; +} + + +int ToggleCoordAxes() +{ + // Toggle display of coordinate axes. + Show_axes_flag = !Show_axes_flag; + LargeView.ev_changed = 1; + if (Show_axes_flag == 1) { + if (last_keypress != KEY_D+KEY_CTRLED) + diagnostic_message("[ctrl-D] Coordinate axes ON."); + else + diagnostic_message("Coordinate axes ON."); + } + if (Show_axes_flag == 0) { + if (last_keypress != KEY_D+KEY_CTRLED) + diagnostic_message("[ctrl-D] Coordinate axes OFF."); + else + diagnostic_message("Coordinate axes OFF."); + } + return Show_axes_flag; +} + +int med_keypad_goto_prev() +{ + ui_pad_goto_prev(); + return 0; +} + +int med_keypad_goto_next() +{ + ui_pad_goto_next(); + return 0; +} + +int med_keypad_goto() +{ + ui_pad_goto(func_get_param(0)); + return 0; +} + +int render_3d_in_big_window=0; + +int medlisp_update_screen() +{ + int vn; + +if (!render_3d_in_big_window) + for (vn=0;vnev_changed || (Update_flags & (UF_WORLD_CHANGED|UF_VIEWPOINT_MOVED|UF_ED_STATE_CHANGED))) { + draw_world(Views[vn]->ev_canv,Views[vn],Cursegp,Big_depth); + Views[vn]->ev_changed = 0; + } + + if (Update_flags & (UF_WORLD_CHANGED|UF_GAME_VIEW_CHANGED|UF_ED_STATE_CHANGED)) { + grs_canvas temp_canvas; + grs_canvas *render_canv,*show_canv; + + if (render_3d_in_big_window) { + + gr_init_sub_canvas(&temp_canvas,canv_offscreen,0,0, + LargeView.ev_canv->cv_bitmap.bm_w,LargeView.ev_canv->cv_bitmap.bm_h); + + render_canv = &temp_canvas; + show_canv = LargeView.ev_canv; + + } + else { + render_canv = VR_offscreen_buffer; + show_canv = Canv_editor_game; + } + + gr_set_current_canvas(render_canv); + render_frame(0); + + Assert(render_canv->cv_bitmap.bm_w == show_canv->cv_bitmap.bm_w && + render_canv->cv_bitmap.bm_h == show_canv->cv_bitmap.bm_h); + + ui_mouse_hide(); + gr_bm_ubitblt(show_canv->cv_bitmap.bm_w,show_canv->cv_bitmap.bm_h, + 0,0,0,0,&render_canv->cv_bitmap,&show_canv->cv_bitmap); + ui_mouse_show(); + } + + Update_flags=UF_NONE; //clear flags + + return 1; +} + +void med_point_2_vec(grs_canvas *canv,vms_vector *v,short sx,short sy) +{ + gr_set_current_canvas(canv); + + g3_start_frame(); + g3_set_view_matrix(&Viewer->pos,&Viewer->orient,Render_zoom); + + g3_point_2_vec(v,sx,sy); + + g3_end_frame(); +} + + + +void draw_world_from_game(void) +{ + if (ModeFlag == 2) + draw_world(Views[0]->ev_canv,Views[0],Cursegp,Big_depth); +} + +int UndoCommand() +{ int u; + + u = undo(); + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + if (u == 0) { + if (Autosave_count==9) diagnostic_message(undo_status[0]); + else + diagnostic_message(undo_status[Autosave_count+1]); + } + else + if (u == 1) diagnostic_message("Can't Undo."); + else + if (u == 2) diagnostic_message("Can't Undo - Autosave OFF"); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + warn_if_concave_segments(); + return 1; +} + + +int ToggleAutosave() +{ + Autosave_flag = !Autosave_flag; + if (Autosave_flag == 1) + diagnostic_message("Autosave ON."); + else + diagnostic_message("Autosave OFF."); + return Autosave_flag; +} + + +int AttachSegment() +{ + if (med_attach_segment(Cursegp, &New_segment, Curside, AttachSide)==4) // Used to be WBACK instead of Curside + diagnostic_message("Cannot attach segment - already a connection on current side."); + else { + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + vm_angvec_make(&Seg_orientation,0,0,0); + Curside = WBACK; + Update_flags |= UF_WORLD_CHANGED; + autosave_mine(mine_filename); + strcpy(undo_status[Autosave_count], "Attach Segment UNDONE.\n"); + mine_changed = 1; + warn_if_concave_segment(Cursegp); + } + return 1; +} + +int ForceTotalRedraw() +{ + Update_flags = UF_ALL; + return 1; +} + + +#if ORTHO_VIEWS +int SyncLargeView() +{ + // Make large view be same as one of the orthogonal views. + Large_view_index = (Large_view_index + 1) % 3; // keep in 0,1,2 for top, front, right + switch (Large_view_index) { + case 0: LargeView.ev_matrix = TopView.ev_matrix; break; + case 1: LargeView.ev_matrix = FrontView.ev_matrix; break; + case 2: LargeView.ev_matrix = RightView.ev_matrix; break; + } + Update_flags |= UF_VIEWPOINT_MOVED; + return 1; +} +#endif + +int DeleteCurSegment() +{ + // Delete current segment. + med_delete_segment(Cursegp); + autosave_mine(mine_filename); + strcpy(undo_status[Autosave_count], "Delete segment UNDONE."); + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + Update_flags |= UF_WORLD_CHANGED; + mine_changed = 1; + diagnostic_message("Segment deleted."); + warn_if_concave_segments(); // This could be faster -- just check if deleted segment was concave, warn accordingly + + return 1; +} + +int CreateDefaultNewSegment() +{ + // Create a default segment for New_segment. + vms_vector tempvec; + med_create_new_segment(vm_vec_make(&tempvec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); + mine_changed = 1; + + return 1; +} + +int CreateDefaultNewSegmentandAttach() +{ + CreateDefaultNewSegment(); + AttachSegment(); + + return 1; +} + +int ExchangeMarkandCurseg() +{ + // If Markedsegp != Cursegp, and Markedsegp->segnum != -1, exchange Markedsegp and Cursegp + if (Markedsegp) + if (Markedsegp->segnum != -1) { + segment *tempsegp; + int tempside; + tempsegp = Markedsegp; Markedsegp = Cursegp; Cursegp = tempsegp; + tempside = Markedside; Markedside = Curside; Curside = tempside; + med_create_new_segment_from_cursegp(); + Update_flags |= UF_ED_STATE_CHANGED; + mine_changed = 1; + } + return 1; +} + +int medlisp_add_segment() +{ + AttachSegment(); +//segment *ocursegp = Cursegp; +// med_attach_segment(Cursegp, &New_segment, Curside, WFRONT); // Used to be WBACK instead of Curside +//med_propagate_tmaps_to_segments(ocursegp,Cursegp); +// set_view_target_from_segment(Cursegp); +//// while (!vm_angvec_make(&Seg_orientation,0,0,0)); +// Curside = WBACK; + + return 1; +} + + +int ClearSelectedList(void) +{ + N_selected_segs = 0; + Update_flags |= UF_WORLD_CHANGED; + + diagnostic_message("Selected list cleared."); + + return 1; +} + + +int ClearFoundList(void) +{ + N_found_segs = 0; + Update_flags |= UF_WORLD_CHANGED; + + diagnostic_message("Found list cleared."); + + return 1; +} + + + + +// --------------------------------------------------------------------------------------------------- +// Do chase mode. +// View current segment (Cursegp) from the previous segment. +void set_chase_matrix(segment *sp) +{ + int v; + vms_vector forvec = ZERO_VECTOR, upvec; + vms_vector tv = ZERO_VECTOR; + segment *psp; + + // move back two segments, if possible, else move back one, if possible, else use current + if (IS_CHILD(sp->children[WFRONT])) { + psp = &Segments[sp->children[WFRONT]]; + if (IS_CHILD(psp->children[WFRONT])) + psp = &Segments[psp->children[WFRONT]]; + } else + psp = sp; + + for (v=0; vverts[v]]); + vm_vec_scale(&forvec,F1_0/MAX_VERTICES_PER_SEGMENT); + + for (v=0; vverts[v]]); + vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT); + + Ed_view_target = forvec; + + vm_vec_sub2(&forvec,&tv); + + extract_up_vector_from_segment(psp,&upvec); + + if (!((forvec.x == 0) && (forvec.y == 0) && (forvec.z == 0))) + vm_vector_2_matrix(&LargeView.ev_matrix,&forvec,&upvec,NULL); +} + + + +// --------------------------------------------------------------------------------------------------- +void set_view_target_from_segment(segment *sp) +{ + vms_vector tv = ZERO_VECTOR; + int v; + + if (Funky_chase_mode) + { + mprintf((0, "Trying to set chase mode\n")); + //set_chase_matrix(sp); + } + else { + for (v=0; vverts[v]]); + + vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT); + + Ed_view_target = tv; + + } + Update_flags |= UF_VIEWPOINT_MOVED; + +} + + + + + + + + + + + + + + + + + diff --git a/main/editor/medmisc.h b/main/editor/medmisc.h new file mode 100644 index 00000000..ed6f51ef --- /dev/null +++ b/main/editor/medmisc.h @@ -0,0 +1,62 @@ +/* +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/medmisc.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Defn'tns for medmisc.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:39 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:40 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.3 1994/07/21 17:25:28 matt + * Took out unused func medlisp_create_new_mine() and its prototype + * + * Revision 1.2 1993/12/17 12:05:04 john + * Took stuff out of med.c; moved into medsel.c, meddraw.c, medmisc.c + * + * Revision 1.1 1993/12/17 08:45:23 john + * Initial revision + * + * + */ + + + +#ifndef _MEDMISC_H +#define _MEDMISC_H + +void GetMouseRotation( int idx, int idy, vms_matrix * RotMat ); +extern int Gameview_lockstep; //In medmisc.c +int ToggleLockstep(); +int medlisp_delete_segment(void); +int medlisp_scale_segment(void); +int medlisp_rotate_segment(void); +int ToggleLockViewToCursegp(void); +int ToggleDrawAllSegments(); +int IncreaseDrawDepth(void); +int DecreaseDrawDepth(void); +int ToggleCoordAxes(); +extern int Big_depth; +void set_chase_matrix(segment *sp); +void set_view_target_from_segment(segment *sp); + + +#endif diff --git a/main/editor/medrobot.c b/main/editor/medrobot.c new file mode 100644 index 00000000..ced25868 --- /dev/null +++ b/main/editor/medrobot.c @@ -0,0 +1,938 @@ +/* +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/medrobot.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Dialog box to edit robot properties. + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:56 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:59 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.46 1995/02/22 15:22:03 allender + * remove anonyous unions from object structure + * + * Revision 1.45 1994/11/27 23:17:32 matt + * Made changes for new mprintf calling convention + * + * Revision 1.44 1994/11/14 11:39:57 mike + * fix default robot behavior + * + * Revision 1.43 1994/11/02 16:18:47 matt + * Moved draw_model_picture() out of editor, and cleaned up code + * + * Revision 1.42 1994/10/10 17:23:23 mike + * Verify that not placing too many player objects. + * + * Revision 1.41 1994/10/09 22:04:38 mike + * Maybe improve, maybe not, robot selection in shift-R menu. + * + * Revision 1.40 1994/09/30 21:49:01 mike + * Fix stupid shift-R dialog bug which caused lots of mprintf and selecting of object and frustration. + * + * Revision 1.39 1994/09/30 11:51:33 mike + * Fix boolean logic on an error trap. + * + * Revision 1.38 1994/09/20 14:36:32 mike + * Clean up Robot dialog. + * + * Revision 1.37 1994/09/12 19:11:56 mike + * Fix stupid bugs in selecting objects. + * + * Revision 1.36 1994/09/01 17:05:51 matt + * Don't force redraw if object select fails + * + * Revision 1.35 1994/08/31 19:24:40 mike + * Fix hang bug when only objects in mine are not robots. + * + * Revision 1.34 1994/08/25 21:56:38 mike + * IS_CHILD stuff. + * + * Revision 1.33 1994/08/23 16:39:29 mike + * mode replaced by behavior in ai_info. + * + * Revision 1.32 1994/08/15 23:47:16 mike + * fix bugs. + * + * Revision 1.31 1994/08/13 17:32:45 mike + * set to still function. + * + * Revision 1.30 1994/08/09 16:06:02 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.29 1994/08/02 16:22:48 matt + * Finished object editor dialog + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: medrobot.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#ifndef __LINUX__ +#include +#include +#include +#endif +#include +#include + +#include "screens.h" +#include "inferno.h" +#include "segment.h" +#include "editor.h" + +#include "timer.h" +#include "objpage.h" +#include "fix.h" +#include "mono.h" +#include "error.h" +#include "kdefs.h" +#include "object.h" +#include "polyobj.h" +#include "game.h" +#include "powerup.h" +#include "ai.h" +#include "hostage.h" +#include "eobject.h" +#include "medwall.h" +#include "eswitch.h" +#include "ehostage.h" +#include "key.h" +#include "centers.h" +#include "bm.h" + +#define NUM_BOXES 6 // Number of boxes, AI modes + +int GoodyNextID(); +int GoodyPrevID(); +void robot_close_window(); +//------------------------------------------------------------------------- +// Variables for this module... +//------------------------------------------------------------------------- +static UI_WINDOW *MainWindow = NULL; +static UI_GADGET_USERBOX *RobotViewBox; +static UI_GADGET_USERBOX *ContainsViewBox; +static UI_GADGET_BUTTON *QuitButton; +static UI_GADGET_RADIO *InitialMode[NUM_BOXES]; + +static int old_object; +static fix Time; +static vms_angvec angles={0,0,0}, goody_angles={0,0,0}; + +//------------------------------------------------------------------------- +// Given a pointer to an object, returns a number that cooresponds to the +// object id as used in the objpage stuff. +//------------------------------------------------------------------------- +int get_object_id( object * obj ) +{ + int i; + int goal_type; + + switch( obj->type ) { + case OBJ_PLAYER: goal_type=OL_PLAYER; break; + case OBJ_ROBOT: goal_type=OL_ROBOT; break; + case OBJ_POWERUP: goal_type=OL_POWERUP; break; + case OBJ_CNTRLCEN: goal_type=OL_CONTROL_CENTER; break; + case OBJ_HOSTAGE: goal_type=OL_HOSTAGE; break; + case OBJ_CLUTTER: goal_type=OL_CLUTTER; break; + default: + Int3(); // Invalid object type + return -1; + } + + // Find first object with the same type as this + // one and then add the object id to that to find + // the offset into the list. + + for (i=0; i< Num_total_object_types; i++ ) { + if ( ObjType[i]==goal_type) + return obj->id + i; + } + return -1; +} + +void call_init_ai_object(object *objp, int behavior) +{ + int hide_segment; + + if (behavior == AIB_STATION) + hide_segment = Cursegp-Segments; + else { + if (Markedsegp != NULL) + hide_segment = Markedsegp-Segments; + else + hide_segment = Cursegp-Segments; + } + + mprintf((0, "Initializing AI object with hide segment = %i\n", hide_segment)); + init_ai_object(objp-Objects, behavior, hide_segment); + + if (behavior == AIB_STATION) { + int cseg, mseg; + + cseg = 0; + mseg = 0; + + if (Cursegp != NULL) + cseg = Cursegp-Segments; + + if (Markedsegp != NULL) { + mseg = Markedsegp-Segments; + } + + objp->ctype.ai_info.follow_path_start_seg = Cursegp-Segments; + objp->ctype.ai_info.follow_path_end_seg = Markedsegp-Segments; + } +} + +//------------------------------------------------------------------------- +// Called when user presses "Next Type" button. This only works for polygon +// objects and it just selects the next polygon model for the current object. +//------------------------------------------------------------------------- +int RobotNextType() +{ + if (Cur_object_index > -1 ) { + if ( Objects[Cur_object_index].type == OBJ_ROBOT ) { + object * obj = &Objects[Cur_object_index]; + obj->id++; + if (obj->id >= N_robot_types ) + obj->id = 0; + + //Set polygon-object-specific data + obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; + obj->rtype.pobj_info.subobj_flags = 0; + //set Physics info + obj->mtype.phys_info.flags |= (PF_LEVELLING); + obj->shields = Robot_info[obj->id].strength; + call_init_ai_object(obj, AIB_NORMAL); + + Cur_robot_type = obj->id; + } + } + Update_flags |= UF_WORLD_CHANGED; + return 1; +} + +//------------------------------------------------------------------------- +// Called when user presses "Prev Type" button. This only works for polygon +// objects and it just selects the prev polygon model for the current object. +//------------------------------------------------------------------------- +int RobotPrevType() +{ + if (Cur_object_index > -1 ) { + if ( Objects[Cur_object_index].type == OBJ_ROBOT ) { + object * obj = &Objects[Cur_object_index]; + if (obj->id == 0 ) + obj->id = N_robot_types-1; + else + obj->id--; + + //Set polygon-object-specific data + obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; + obj->rtype.pobj_info.subobj_flags = 0; + //set Physics info + obj->mtype.phys_info.flags |= (PF_LEVELLING); + obj->shields = Robot_info[obj->id].strength; + call_init_ai_object(obj, AIB_NORMAL); + + Cur_robot_type = obj->id; + } + } + Update_flags |= UF_WORLD_CHANGED; + return 1; +} + +//------------------------------------------------------------------------- +// Dummy function for Mike to write. +//------------------------------------------------------------------------- +int med_set_ai_path() +{ + mprintf( (0, "med-set-ai-path called -- it does nothing, paths automatically set!\n" )); + + return 1; +} + +// #define OBJ_NONE 255 //unused object +// #define OBJ_WALL 0 //A wall... not really an object, but used for collisions +// #define OBJ_FIREBALL 1 //a fireball, part of an explosion +// #define OBJ_ROBOT 2 //an evil enemy +// #define OBJ_HOSTAGE 3 //a hostage you need to rescue +// #define OBJ_PLAYER 4 //the player on the console +// #define OBJ_WEAPON 5 //a laser, missile, etc +// #define OBJ_CAMERA 6 //a camera to slew around with +// #define OBJ_POWERUP 7 //a powerup you can pick up +// #define OBJ_DEBRIS 8 //a piece of robot +// #define OBJ_CNTRLCEN 9 //the control center +// #define OBJ_FLARE 10 //the control center +// #define MAX_OBJECT_TYPES 11 + + +#define GOODY_TYPE_MAX MAX_OBJECT_TYPES +#define GOODY_X 6 +#define GOODY_Y 132 + +//#define GOODY_ID_MAX_ROBOT 6 +//#define GOODY_ID_MAX_POWERUP 9 +#define GOODY_COUNT_MAX 4 + +int Cur_goody_type = OBJ_POWERUP; +int Cur_goody_id = 0; +int Cur_goody_count = 0; + +void update_goody_info(void) +{ + if (Cur_object_index > -1 ) { + if ( Objects[Cur_object_index].type == OBJ_ROBOT ) { + object * obj = &Objects[Cur_object_index]; + + obj->contains_type = Cur_goody_type; + obj->contains_id = Cur_goody_id; + obj->contains_count = Cur_goody_count; + } + } +} + +// #define OBJ_WALL 0 //A wall... not really an object, but used for collisions +// #define OBJ_FIREBALL 1 //a fireball, part of an explosion +// #define OBJ_ROBOT 2 //an evil enemy +// #define OBJ_HOSTAGE 3 //a hostage you need to rescue +// #define OBJ_PLAYER 4 //the player on the console +// #define OBJ_WEAPON 5 //a laser, missile, etc +// #define OBJ_CAMERA 6 //a camera to slew around with +// #define OBJ_POWERUP 7 //a powerup you can pick up +// #define OBJ_DEBRIS 8 //a piece of robot +// #define OBJ_CNTRLCEN 9 //the control center +// #define OBJ_FLARE 10 //the control center +// #define MAX_OBJECT_TYPES 11 + + +int GoodyNextType() +{ + Cur_goody_type++; + while (!((Cur_goody_type == OBJ_ROBOT) || (Cur_goody_type == OBJ_POWERUP))) { + if (Cur_goody_type > GOODY_TYPE_MAX) + Cur_goody_type=0; + else + Cur_goody_type++; + } + + GoodyNextID(); + GoodyPrevID(); + + update_goody_info(); + return 1; +} + +int GoodyPrevType() +{ + Cur_goody_type--; + while (!((Cur_goody_type == OBJ_ROBOT) || (Cur_goody_type == OBJ_POWERUP))) { + if (Cur_goody_type < 0) + Cur_goody_type = GOODY_TYPE_MAX; + else + Cur_goody_type--; + } + + GoodyNextID(); + GoodyPrevID(); + + update_goody_info(); + return 1; +} + +int GoodyNextID() +{ + Cur_goody_id++; + if (Cur_goody_type == OBJ_ROBOT) { + if (Cur_goody_id >= N_robot_types) + Cur_goody_id=0; + } else { + if (Cur_goody_id >= N_powerup_types) + Cur_goody_id=0; + } + + update_goody_info(); + return 1; +} + +int GoodyPrevID() +{ + Cur_goody_id--; + if (Cur_goody_type == OBJ_ROBOT) { + if (Cur_goody_id < 0) + Cur_goody_id = N_robot_types-1; + } else { + if (Cur_goody_id < 0) + Cur_goody_id = N_powerup_types-1; + } + + update_goody_info(); + return 1; +} + +int GoodyNextCount() +{ + Cur_goody_count++; + if (Cur_goody_count > GOODY_COUNT_MAX) + Cur_goody_count=0; + + update_goody_info(); + return 1; +} + +int GoodyPrevCount() +{ + Cur_goody_count--; + if (Cur_goody_count < 0) + Cur_goody_count=GOODY_COUNT_MAX; + + update_goody_info(); + return 1; +} + +int is_legal_type(int the_type) +{ + return (the_type == OBJ_ROBOT) || (the_type == OBJ_CLUTTER); +} + +int is_legal_type_for_this_window(int objnum) +{ + if (objnum == -1) + return 1; + else + return is_legal_type(Objects[objnum].type); +} + +int LocalObjectSelectNextinSegment(void) +{ + int rval, first_obj; + + rval = ObjectSelectNextinSegment(); + first_obj = Cur_object_index; + + if (Cur_object_index != -1) { + while (!is_legal_type_for_this_window(Cur_object_index)) { + //mprintf((0, "Skipping object #%i of type %i\n", Cur_object_index, Objects[Cur_object_index].type)); + rval = ObjectSelectNextinSegment(); + if (first_obj == Cur_object_index) + break; + } + + Cur_goody_type = Objects[Cur_object_index].contains_type; + Cur_goody_id = Objects[Cur_object_index].contains_id; + if (Objects[Cur_object_index].contains_count < 0) + Objects[Cur_object_index].contains_count = 0; + Cur_goody_count = Objects[Cur_object_index].contains_count; + } + + if (Cur_object_index != first_obj) + set_view_target_from_segment(Cursegp); + + return rval; +} + +int LocalObjectSelectNextinMine(void) +{ + int rval, first_obj; + + rval = ObjectSelectNextInMine(); + + first_obj = Cur_object_index; + + if (Cur_object_index != -1) { + while (!is_legal_type_for_this_window(Cur_object_index)) { + //mprintf((0, "Skipping object #%i of type %i\n", Cur_object_index, Objects[Cur_object_index].type)); + ObjectSelectNextInMine(); + if (Cur_object_index == first_obj) + break; + } + + Cur_goody_type = Objects[Cur_object_index].contains_type; + Cur_goody_id = Objects[Cur_object_index].contains_id; + if (Objects[Cur_object_index].contains_count < 0) + Objects[Cur_object_index].contains_count = 0; + Cur_goody_count = Objects[Cur_object_index].contains_count; + } + + if (Cur_object_index != first_obj) + set_view_target_from_segment(Cursegp); + + return rval; +} + +int LocalObjectSelectPrevinMine(void) +{ + int rval, first_obj; + + rval = ObjectSelectPrevInMine(); + + first_obj = Cur_object_index; + + if (Cur_object_index != -1) { + while (!is_legal_type_for_this_window(Cur_object_index)) { + //mprintf((0, "Skipping object #%i of type %i\n", Cur_object_index, Objects[Cur_object_index].type)); + ObjectSelectPrevInMine(); + if (first_obj == Cur_object_index) + break; + } + + Cur_goody_type = Objects[Cur_object_index].contains_type; + Cur_goody_id = Objects[Cur_object_index].contains_id; + if (Objects[Cur_object_index].contains_count < 0) + Objects[Cur_object_index].contains_count = 0; + Cur_goody_count = Objects[Cur_object_index].contains_count; + } + + if (Cur_object_index != first_obj) + set_view_target_from_segment(Cursegp); + + return rval; +} + +int LocalObjectDelete(void) +{ + int rval; + + rval = ObjectDelete(); + + if (Cur_object_index != -1) { + Cur_goody_type = Objects[Cur_object_index].contains_type; + Cur_goody_id = Objects[Cur_object_index].contains_id; + Cur_goody_count = Objects[Cur_object_index].contains_count; + } + + set_view_target_from_segment(Cursegp); + + return rval; +} + +int LocalObjectPlaceObject(void) +{ + int rval; + + Cur_goody_count = 0; + + while (ObjType[Cur_robot_type] != OL_ROBOT) { // && (ObjType[Cur_robot_type] != OL_POWERUP)) { + Cur_robot_type++; + if (Cur_robot_type >= N_robot_types) + Cur_robot_type = 0; + } + + rval = ObjectPlaceObject(); + if (rval == -1) + return -1; + + Objects[Cur_object_index].contains_type = Cur_goody_type; + Objects[Cur_object_index].contains_id = Cur_goody_id; + Objects[Cur_object_index].contains_count = Cur_goody_count; + + set_view_target_from_segment(Cursegp); + + return rval; +} + +void close_all_windows(void) +{ + close_trigger_window(); + close_wall_window(); + close_centers_window(); + hostage_close_window(); + robot_close_window(); +} + + +//------------------------------------------------------------------------- +// Called from the editor... does one instance of the robot dialog box +//------------------------------------------------------------------------- +int do_robot_dialog() +{ + int i; + + // Only open 1 instance of this window... + if ( MainWindow != NULL ) return 0; + + // Close other windows + close_all_windows(); + Cur_goody_count = 0; + + // Open a window with a quit button + MainWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG ); + QuitButton = ui_add_gadget_button( MainWindow, 20, 286, 40, 32, "Done", NULL ); + + ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y-3, 25, 22, "<<", GoodyPrevType ); + ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y-3, 25, 22, ">>", GoodyNextType ); + + ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y+21, 25, 22, "<<", GoodyPrevID ); + ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y+21, 25, 22, ">>", GoodyNextID ); + + ui_add_gadget_button( MainWindow, GOODY_X+50, GOODY_Y+45, 25, 22, "<<", GoodyPrevCount ); + ui_add_gadget_button( MainWindow, GOODY_X+80, GOODY_Y+45, 25, 22, ">>", GoodyNextCount ); + + InitialMode[0] = ui_add_gadget_radio( MainWindow, 6, 58, 16, 16, 0, "Hover" ); + InitialMode[1] = ui_add_gadget_radio( MainWindow, 76, 58, 16, 16, 0, "Normal" ); + InitialMode[2] = ui_add_gadget_radio( MainWindow, 6, 78, 16, 16, 0, "(hide)" ); + InitialMode[3] = ui_add_gadget_radio( MainWindow, 76, 78, 16, 16, 0, "Avoid" ); + InitialMode[4] = ui_add_gadget_radio( MainWindow, 6, 98, 16, 16, 0, "Follow" ); + InitialMode[5] = ui_add_gadget_radio( MainWindow, 76, 98, 16, 16, 0, "Station" ); + + // The little box the robots will spin in. + RobotViewBox = ui_add_gadget_userbox( MainWindow,155, 5, 150, 125 ); + + // The little box the robots will spin in. + ContainsViewBox = ui_add_gadget_userbox( MainWindow,10, 202, 100, 80 ); + + // A bunch of buttons... + i = 135; + ui_add_gadget_button( MainWindow,190,i,53, 26, "<>", RobotNextType ); i += 29; + ui_add_gadget_button( MainWindow,190,i,110, 26, "Next in Seg", LocalObjectSelectNextinSegment ); i += 29; + + ui_add_gadget_button( MainWindow,190,i,53, 26, "<>Obj", LocalObjectSelectNextinMine ); i += 29; + + ui_add_gadget_button( MainWindow,190,i,110, 26, "Delete", LocalObjectDelete ); i += 29; + ui_add_gadget_button( MainWindow,190,i,110, 26, "Create New", LocalObjectPlaceObject ); i += 29; + ui_add_gadget_button( MainWindow,190,i,110, 26, "Set Path", med_set_ai_path ); + + Time = timer_get_fixed_seconds(); + + old_object = -2; // Set to some dummy value so everything works ok on the first frame. + + if ( Cur_object_index == -1 ) + LocalObjectSelectNextinMine(); + + return 1; + +} + +void robot_close_window() +{ + if ( MainWindow!=NULL ) { + ui_close_window( MainWindow ); + MainWindow = NULL; + } + +} + +#define STRING_LENGTH 8 + +void do_robot_window() +{ + int i; + fix DeltaTime, Temp; + int first_object_index; + + if ( MainWindow == NULL ) return; + + first_object_index = Cur_object_index; + while (!is_legal_type_for_this_window(Cur_object_index)) { + LocalObjectSelectNextinMine(); + if (first_object_index == Cur_object_index) { + break; + } + } + + //------------------------------------------------------------ + // Call the ui code.. + //------------------------------------------------------------ + ui_button_any_drawn = 0; + ui_window_do_gadgets(MainWindow); + + //------------------------------------------------------------ + // If we change objects, we need to reset the ui code for all + // of the radio buttons that control the ai mode. Also makes + // the current AI mode button be flagged as pressed down. + //------------------------------------------------------------ + if (old_object != Cur_object_index ) { + for ( i=0; i < NUM_BOXES; i++ ) { + InitialMode[i]->flag = 0; // Tells ui that this button isn't checked + InitialMode[i]->status = 1; // Tells ui to redraw button + } + if ( Cur_object_index > -1 ) { + int behavior = Objects[Cur_object_index].ctype.ai_info.behavior; + if ( !((behavior >= MIN_BEHAVIOR) && (behavior <= MAX_BEHAVIOR))) { + mprintf((0, "Object #%i behavior id (%i) out of bounds, setting to AIB_NORMAL.\n", Cur_object_index, behavior)); + Objects[Cur_object_index].ctype.ai_info.behavior = AIB_NORMAL; + behavior = AIB_NORMAL; + } + InitialMode[behavior - MIN_BEHAVIOR]->flag = 1; // Mark this button as checked + } + } + + //------------------------------------------------------------ + // If any of the radio buttons that control the mode are set, then + // update the cooresponding AI state. + //------------------------------------------------------------ + for ( i=0; i < NUM_BOXES; i++ ) { + if ( InitialMode[i]->flag == 1 ) + if (Objects[Cur_object_index].ctype.ai_info.behavior != MIN_BEHAVIOR+i) { + Objects[Cur_object_index].ctype.ai_info.behavior = MIN_BEHAVIOR+i; // Set the ai_state to the cooresponding radio button + call_init_ai_object(&Objects[Cur_object_index], MIN_BEHAVIOR+i); + } + } + + //------------------------------------------------------------ + // A simple frame time counter for spinning the objects... + //------------------------------------------------------------ + Temp = timer_get_fixed_seconds(); + DeltaTime = Temp - Time; + Time = Temp; + + //------------------------------------------------------------ + // Redraw the object in the little 64x64 box + //------------------------------------------------------------ + if (Cur_object_index > -1 ) { + int id; + gr_set_current_canvas( RobotViewBox->canvas ); + id = get_object_id(&Objects[Cur_object_index]); + if ( id > -1 ) + draw_robot_picture(id, &angles, -1 ); + else + gr_clear_canvas( CGREY ); + angles.h += fixmul(0x1000, DeltaTime ); + } else { + // no object, so just blank out + gr_set_current_canvas( RobotViewBox->canvas ); + gr_clear_canvas( CGREY ); + +// LocalObjectSelectNextInMine(); + } + + //------------------------------------------------------------ + // Redraw the contained object in the other little box + //------------------------------------------------------------ + if ((Cur_object_index > -1 ) && (Cur_goody_count > 0)) { + int id; + + gr_set_current_canvas( ContainsViewBox->canvas ); + id = Cur_goody_id; + if ( id > -1 ) { + int ol_type=0; + if (Cur_goody_type == OBJ_ROBOT) + ol_type = OL_ROBOT; + else if (Cur_goody_type == OBJ_POWERUP) + ol_type = OL_POWERUP; + else + Int3(); // Error? Unknown goody type! + + draw_robot_picture(id, &goody_angles, ol_type ); + } else + gr_clear_canvas( CGREY ); + goody_angles.h += fixmul(0x1000, DeltaTime ); + } else { + // no object, so just blank out + gr_set_current_canvas( ContainsViewBox->canvas ); + gr_clear_canvas( CGREY ); + +// LocalObjectSelectNextInMine(); + } + + //------------------------------------------------------------ + // If anything changes in the ui system, redraw all the text that + // identifies this robot. + //------------------------------------------------------------ + + if (ui_button_any_drawn || (old_object != Cur_object_index) ) { + int i; + char type_text[STRING_LENGTH+1],id_text[STRING_LENGTH+1]; + + if (Cur_object_index != -1) { + Cur_goody_type = Objects[Cur_object_index].contains_type; + Cur_goody_id = Objects[Cur_object_index].contains_id; + if (Objects[Cur_object_index].contains_count < 0) + Objects[Cur_object_index].contains_count = 0; + Cur_goody_count = Objects[Cur_object_index].contains_count; + } + + ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y, " Type:"); + ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y+24, " ID:"); + ui_wprintf_at( MainWindow, GOODY_X, GOODY_Y+48, "Count:"); + + for (i=0; i -1 ) { + int id = Objects[Cur_object_index].id; + char id_text[12]; + int i; + + for (i=0; ipressed || (last_keypress==KEY_ESC)) { + robot_close_window(); + return; + } + + old_object = Cur_object_index; +} + +// -------------------------------------------------------------------------------------------------------------------------- +#define NUM_MATT_THINGS 2 + +#define MATT_LEN 20 + +static UI_WINDOW *MattWindow = NULL; + +void object_close_window() +{ + if ( MattWindow!=NULL ) { + ui_close_window( MattWindow ); + MattWindow = NULL; + } + +} + + +UI_GADGET_INPUTBOX *Xtext, *Ytext, *Ztext; + +//------------------------------------------------------------------------- +// Called from the editor... does one instance of the object dialog box +//------------------------------------------------------------------------- +int do_object_dialog() +{ + char Xmessage[MATT_LEN], Ymessage[MATT_LEN], Zmessage[MATT_LEN]; + object *obj=&Objects[Cur_object_index]; + + if (obj->type == OBJ_ROBOT) //don't do this for robots + return 0; + + // Only open 1 instance of this window... + if ( MattWindow != NULL ) + return 0; + + Cur_goody_count = 0; + + // Open a window with a quit button + MattWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG ); + QuitButton = ui_add_gadget_button( MattWindow, 20, 286, 40, 32, "Done", NULL ); + + QuitButton->hotkey = KEY_ENTER; + + // These are the radio buttons for each mode + InitialMode[0] = ui_add_gadget_radio( MattWindow, 10, 50, 16, 16, 0, "None" ); + InitialMode[1] = ui_add_gadget_radio( MattWindow, 80, 50, 16, 16, 0, "Spinning" ); + + InitialMode[obj->movement_type == MT_SPINNING?1:0]->flag = 1; + + sprintf(Xmessage,"%.2f",f2fl(obj->mtype.spin_rate.x)); + sprintf(Ymessage,"%.2f",f2fl(obj->mtype.spin_rate.y)); + sprintf(Zmessage,"%.2f",f2fl(obj->mtype.spin_rate.z)); + + ui_wprintf_at( MattWindow, 10, 132,"&X:" ); + Xtext = ui_add_gadget_inputbox( MattWindow, 30, 132, MATT_LEN, MATT_LEN, Xmessage ); + + ui_wprintf_at( MattWindow, 10, 162,"&Y:" ); + Ytext = ui_add_gadget_inputbox( MattWindow, 30, 162, MATT_LEN, MATT_LEN, Ymessage ); + + ui_wprintf_at( MattWindow, 10, 192,"&Z:" ); + Ztext = ui_add_gadget_inputbox( MattWindow, 30, 192, MATT_LEN, MATT_LEN, Zmessage ); + + ui_gadget_calc_keys(MattWindow); + + MattWindow->keyboard_focus_gadget = (UI_GADGET *) InitialMode[0]; + + mprintf((0, "X = %08x, Y = %08x, Z = %08x\n", atoi(Xmessage), atoi(Ymessage), atoi(Zmessage))); + + return 1; + +} + +void do_object_window() +{ + object *obj=&Objects[Cur_object_index]; + + if ( MattWindow == NULL ) return; + + //------------------------------------------------------------ + // Call the ui code.. + //------------------------------------------------------------ + ui_button_any_drawn = 0; + ui_window_do_gadgets(MattWindow); + + + if ( QuitButton->pressed || (last_keypress==KEY_ESC)) { + + if (InitialMode[0]->flag) obj->movement_type = MT_NONE; + if (InitialMode[1]->flag) obj->movement_type = MT_SPINNING; + + obj->mtype.spin_rate.x = fl2f(atof(Xtext->text)); + obj->mtype.spin_rate.y = fl2f(atof(Ytext->text)); + obj->mtype.spin_rate.z = fl2f(atof(Ztext->text)); + + object_close_window(); + return; + } + + old_object = Cur_object_index; +} + +void set_all_modes_to_hover(void) +{ + int i; + + for (i=0; i<=Highest_object_index; i++) + if (Objects[i].control_type == CT_AI) + Objects[i].ctype.ai_info.behavior = AIB_STILL; +} + diff --git a/main/editor/medrobot.h b/main/editor/medrobot.h new file mode 100644 index 00000000..6dce7a42 --- /dev/null +++ b/main/editor/medrobot.h @@ -0,0 +1,56 @@ +/* +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/medrobot.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Header for robot.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:39 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:04 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.4 1994/08/02 14:17:56 mike + * Clean up dialog boxes. + * + * Revision 1.3 1994/07/21 19:34:58 yuan + * Fixed #include problem + * + * Revision 1.2 1994/04/27 21:01:16 matt + * Added prototypes for robot functions + * + * Revision 1.1 1994/04/27 20:28:59 matt + * Initial revision + * + * + */ + + + +#ifndef _MED_ROBOT_H +#define _MED_ROBOT_H + +extern void robot_close_window(); +extern void do_robot_window(); + +extern void object_close_window(); +extern void do_object_window(); + + +#endif diff --git a/main/editor/medsel.c b/main/editor/medsel.c new file mode 100644 index 00000000..3c5f2c94 --- /dev/null +++ b/main/editor/medsel.c @@ -0,0 +1,178 @@ +/* +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/medsel.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Routines stripped from med.c for segment selection + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:03:57 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:20 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.10 1994/08/09 16:05:59 john + * Added the ability to place players. Made old + * Player variable be ConsoleObject. + * + * Revision 1.9 1994/05/23 14:56:27 mike + * make current segment be add segment. + * + * Revision 1.8 1994/05/14 18:00:50 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.7 1994/03/31 12:03:33 matt + * Cleaned up includes + * + * Revision 1.6 1994/02/17 12:52:13 yuan + * Unbackdated + * y + * + * Revision 1.4 1994/02/17 09:46:53 matt + * Removed include of slew.h + * + * Revision 1.3 1994/01/05 10:54:23 john + * New object code by John + * + * Revision 1.2 1993/12/17 12:18:22 john + * Moved selection stuff out of med.c + * + * Revision 1.1 1993/12/17 09:29:34 john + * Initial revision + * + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: medsel.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#ifdef __MSDOS__ +#include +#endif + +#include "gr.h" +#include "ui.h" +#include "key.h" +#include "mono.h" +#include "error.h" +#include "u_mem.h" + +#include "inferno.h" +#include "editor.h" +#include "segment.h" +#include "object.h" + +typedef struct sort_element { + short segnum; + fix dist; +} sort_element; + +//compare the distance of two segments. slow, since it computes the +//distance each time +int segdist_cmp(sort_element *s0,sort_element *s1) +{ + return (s0->dist==s1->dist)?0:((s0->distdist)?-1:1); + +} + + +//find the distance between a segment and a point +fix compute_dist(segment *seg,vms_vector *pos) +{ + vms_vector delta; + + compute_segment_center(&delta,seg); + vm_vec_sub2(&delta,pos); + + return vm_vec_mag(&delta); + +} + +//sort a list of segments, in order of closeness to pos +void sort_seg_list(int n_segs,short *segnumlist,vms_vector *pos) +{ + int i; + sort_element *sortlist; + + sortlist = calloc(n_segs,sizeof(*sortlist)); + + for (i=0;ipos); + editor_status("%i element selected list sorted.",N_selected_segs); + + return 1; +} + +int SelectNextFoundSeg(void) +{ + if (++Found_seg_index >= N_found_segs) + Found_seg_index = 0; + + Cursegp = &Segments[Found_segs[Found_seg_index]]; + med_create_new_segment_from_cursegp(); + + Update_flags |= UF_WORLD_CHANGED; + + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + + editor_status("Curseg assigned to next found segment."); + + return 1; +} + +int SelectPreviousFoundSeg(void) +{ + if (Found_seg_index > 0) + Found_seg_index--; + else + Found_seg_index = N_found_segs-1; + + Cursegp = &Segments[Found_segs[Found_seg_index]]; + med_create_new_segment_from_cursegp(); + + Update_flags |= UF_WORLD_CHANGED; + + if (Lock_view_to_cursegp) + set_view_target_from_segment(Cursegp); + + editor_status("Curseg assigned to previous found segment."); + + return 1; +} + diff --git a/main/editor/medsel.h b/main/editor/medsel.h new file mode 100644 index 00000000..68d55c3a --- /dev/null +++ b/main/editor/medsel.h @@ -0,0 +1,45 @@ +/* +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/medsel.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * rountines stipped from med.c for segment selection + * + * $Log: not supported by cvs2svn $ + * Revision 1.1.1.1 1999/06/14 22:02:39 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:34:28 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.2 1993/12/17 12:18:35 john + * Moved selection stuff out of med.c + * + * Revision 1.1 1993/12/17 09:29:51 john + * Initial revision + * + * + */ + + + +#ifndef _MEDSEL_H +#define _MEDSEL_H + +extern void sort_seg_list(int n_segs,short *segnumlist,vms_vector *pos); + +#endif diff --git a/main/editor/medwall.c b/main/editor/medwall.c new file mode 100644 index 00000000..d2f5e3b3 --- /dev/null +++ b/main/editor/medwall.c @@ -0,0 +1,1568 @@ +/* +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.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * Created from version 1.11 of main\wall.c + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 2003/03/09 06:34:09 donut + * change byte typedef to sbyte to avoid conflict with win32 byte which is unsigned + * + * Revision 1.1.1.1 1999/06/14 22:04:04 donut + * Import of d1x 1.37 source. + * + * Revision 2.0 1995/02/27 11:35:47 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.71 1995/02/01 16:30:03 yuan + * Stabilizing triggers and matcens. + * + * Revision 1.70 1995/01/28 15:28:08 yuan + * Return proper bug description. + * + * Revision 1.69 1995/01/14 19:18:07 john + * First version of object paging. + * + * Revision 1.68 1995/01/12 12:10:44 yuan + * Added delete trigger function + * + * Revision 1.67 1994/11/29 16:51:53 yuan + * Fixed false bogus trigger info. + * + * Revision 1.66 1994/11/27 23:17:29 matt + * Made changes for new mprintf calling convention + * + * Revision 1.65 1994/11/15 11:59:42 john + * Changed timing for door to use fixed seconds instead of milliseconds. + * + * Revision 1.64 1994/11/03 10:41:17 yuan + * Made walls add whichever the previous type was. + * + * Revision 1.63 1994/10/13 13:14:59 yuan + * Fixed trigger removal bug. + * + * Revision 1.62 1994/10/07 17:43:39 yuan + * Make validate walls default to 1. + * + * Revision 1.61 1994/10/03 23:40:20 mike + * Fix hosedness in walls in group copying. + * + * Revision 1.60 1994/09/29 00:20:36 matt + * Took out reference to unused external wall type + * + * Revision 1.59 1994/09/28 17:32:24 mike + * Functions to copy walls withing groups. + * + * Revision 1.58 1994/09/28 13:40:46 yuan + * Fixed control center trigger bug. + * + * Revision 1.57 1994/09/24 12:41:52 matt + * Took out references to obsolete constants + * + * Revision 1.56 1994/09/23 18:03:55 yuan + * Finished wall checking code. + * + * Revision 1.55 1994/09/22 14:35:25 matt + * Made blastable walls work again + * + * Revision 1.54 1994/09/21 16:46:07 yuan + * Fixed bug that reset wall slot which was just deleted. + * + * Revision 1.53 1994/09/20 18:31:21 yuan + * Output right Wallnum + * + * Revision 1.52 1994/09/20 18:23:24 yuan + * Killed the BOGIFYING WALL DRAGON... + * + * There was a problem with triggers being created that had bogus + * pointers back to their segments. + * + * Revision 1.51 1994/09/20 11:13:11 yuan + * Delete all bogus walls when checking walls. + * + * Revision 1.50 1994/09/19 23:31:14 yuan + * Adding wall checking stuff. + * + * Revision 1.49 1994/09/13 21:11:20 matt + * Added wclips that use tmap1 instead of tmap2, saving lots of merging + * + * Revision 1.48 1994/09/10 13:32:08 matt + * Made exploding walls a type of blastable walls. + * Cleaned up blastable walls, making them tmap2 bitmaps. + * + * Revision 1.47 1994/09/10 09:47:47 yuan + * Added wall checking function. + * + * Revision 1.46 1994/08/26 14:14:56 yuan + * Fixed wall clip being set to -2 bug. + * + * Revision 1.45 1994/08/25 21:56:26 mike + * IS_CHILD stuff. + * + * Revision 1.44 1994/08/19 19:30:27 matt + * Added informative message if wall is already external when making it so. + * + * Revision 1.43 1994/08/17 11:13:46 matt + * Changed way external walls work + * + * Revision 1.42 1994/08/15 17:47:29 yuan + * Added external walls + * + * Revision 1.41 1994/08/05 21:18:09 matt + * Allow two doors to be linked together + * + * Revision 1.40 1994/08/02 14:18:06 mike + * Clean up dialog boxes. + * + * Revision 1.39 1994/08/01 11:04:33 yuan + * New materialization centers. + * + * Revision 1.38 1994/07/22 17:19:11 yuan + * Working on dialog box for refuel/repair/material/control centers. + * + * Revision 1.37 1994/07/20 17:35:33 yuan + * Added new gold key. + * + * Revision 1.36 1994/07/19 14:31:44 yuan + * Fixed keys bug. + * + * Revision 1.35 1994/07/18 15:58:31 yuan + * Hopefully prevent any "Adam door bombouts" + * + * Revision 1.34 1994/07/18 15:48:40 yuan + * Made minor cosmetic change. + * + * Revision 1.33 1994/07/15 16:09:22 yuan + * Error checking + * + * Revision 1.32 1994/07/14 16:47:05 yuan + * Fixed wall dialog for selected dooranims. + * + * Revision 1.31 1994/07/11 15:09:16 yuan + * Wall anim filenames stored in wclip structure. + * + * Revision 1.30 1994/07/06 10:56:01 john + * New structures for hostages. + * + * Revision 1.29 1994/07/01 16:35:54 yuan + * Added key system + * + * Revision 1.28 1994/06/21 18:50:12 john + * Made ESC key exit dialog. + * + * Revision 1.27 1994/06/20 22:29:59 yuan + * Fixed crazy runaway trigger bug that Adam found + * + * Revision 1.26 1994/06/01 15:50:25 yuan + * Added one more door... Needs to be set by bm.c in the future. + * + * Revision 1.25 1994/05/30 20:22:34 yuan + * New triggers. + * + * Revision 1.24 1994/05/27 10:34:31 yuan + * Added new Dialog boxes for Walls and Triggers. + * + * Revision 1.23 1994/05/25 18:08:45 yuan + * Revamping walls and triggers interface. + * Wall interface complete, but triggers are still in progress. + * + * Revision 1.22 1994/05/18 18:21:56 yuan + * Fixed delete segment and walls bug. + * + * Revision 1.21 1994/05/11 18:24:29 yuan + * Oops.. trigger not triggers.. + * + * Revision 1.20 1994/05/11 18:23:53 yuan + * Fixed trigger not set to -1 bug. + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: medwall.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include + +#include "editor/medwall.h" +#include "inferno.h" +#include "editor/editor.h" +#include "segment.h" +#include "error.h" +#include "gameseg.h" + +#include "textures.h" +#include "screens.h" +#include "switch.h" +#include "editor/eswitch.h" + +#include "texmerge.h" +#include "medrobot.h" +#include "timer.h" +#include "mono.h" +//#include "fuelcen.h" +#include "key.h" +#include "ehostage.h" +#include "centers.h" +#include "piggy.h" + +int wall_add_door_flag(sbyte flag); +int wall_add_to_side(segment *segp, int side, sbyte type); +int wall_remove_door_flag(sbyte flag); +//------------------------------------------------------------------------- +// Variables for this module... +//------------------------------------------------------------------------- +static UI_WINDOW *MainWindow = NULL; +static UI_GADGET_USERBOX *WallViewBox; +static UI_GADGET_BUTTON *QuitButton; +static UI_GADGET_CHECKBOX *DoorFlag[4]; +static UI_GADGET_RADIO *KeyFlag[4]; + +static int old_wall_num; +static fix Time; +static int framenum=0; +static int Current_door_type=1; + +typedef struct count_wall { + short wallnum; + short segnum,sidenum; +} count_wall; + +//--------------------------------------------------------------------- +// Add a wall (removable 2 sided) +int add_wall(segment *seg, short side) +{ + int Connectside; + segment *csegp; + + if (Num_walls < MAX_WALLS-2) + if (IS_CHILD(seg->children[side])) { + if (seg->sides[side].wall_num == -1) { + seg->sides[side].wall_num = Num_walls; + Num_walls++; + } + + csegp = &Segments[seg->children[side]]; + Connectside = find_connect_side(seg, csegp); + + if (csegp->sides[Connectside].wall_num == -1) { + csegp->sides[Connectside].wall_num = Num_walls; + Num_walls++; + } + + create_removable_wall( seg, side, CurrentTexture ); + create_removable_wall( csegp, Connectside, CurrentTexture ); + + return 1; + } + + return 0; +} + +int wall_assign_door(int door_type) +{ + int Connectside; + segment *csegp; + + if (Cursegp->sides[Curside].wall_num == -1) { + editor_status("Cannot assign door. No wall at Curside."); + return 0; + } + + if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR && Walls[Cursegp->sides[Curside].wall_num].type != WALL_BLASTABLE) { + editor_status("Cannot assign door. No door at Curside."); + return 0; + } + + Current_door_type = door_type; + + csegp = &Segments[Cursegp->children[Curside]]; + Connectside = find_connect_side(Cursegp, csegp); + + Walls[Cursegp->sides[Curside].wall_num].clip_num = door_type; + Walls[csegp->sides[Connectside].wall_num].clip_num = door_type; + + if (WallAnims[door_type].flags & WCF_TMAP1) { + Cursegp->sides[Curside].tmap_num = WallAnims[door_type].frames[0]; + csegp->sides[Connectside].tmap_num = WallAnims[door_type].frames[0]; + Cursegp->sides[Curside].tmap_num2 = 0; + csegp->sides[Connectside].tmap_num2 = 0; + } + else { + Cursegp->sides[Curside].tmap_num2 = WallAnims[door_type].frames[0]; + csegp->sides[Connectside].tmap_num2 = WallAnims[door_type].frames[0]; + } + + Update_flags |= UF_WORLD_CHANGED; + return 1; +} + +int wall_add_blastable() +{ + return wall_add_to_side(Cursegp, Curside, WALL_BLASTABLE); +} + +int wall_add_door() +{ + return wall_add_to_side(Cursegp, Curside, WALL_DOOR); +} + +int wall_add_closed_wall() +{ + return wall_add_to_side(Cursegp, Curside, WALL_CLOSED); +} + +int wall_add_external_wall() +{ + if (Cursegp->children[Curside] == -2) { + editor_status( "Wall is already external!" ); + return 1; + } + + if (IS_CHILD(Cursegp->children[Curside])) { + editor_status( "Cannot add external wall here - seg has children" ); + return 0; + } + + Cursegp->children[Curside] = -2; + + return 1; +} + +int wall_add_illusion() +{ + return wall_add_to_side(Cursegp, Curside, WALL_ILLUSION); +} + +int wall_lock_door() +{ + return wall_add_door_flag(WALL_DOOR_LOCKED); +} + +int wall_unlock_door() +{ + return wall_remove_door_flag(WALL_DOOR_LOCKED); +} + +int wall_automate_door() +{ + return wall_add_door_flag(WALL_DOOR_AUTO); +} + +int wall_deautomate_door() +{ + return wall_remove_door_flag(WALL_DOOR_AUTO); +} + +int GotoPrevWall() { + int current_wall; + + if (Cursegp->sides[Curside].wall_num < 0) + current_wall = Num_walls; + else + current_wall = Cursegp->sides[Curside].wall_num; + + current_wall--; + if (current_wall < 0) current_wall = Num_walls-1; + if (current_wall >= Num_walls) current_wall = Num_walls-1; + + if (Walls[current_wall].segnum == -1) { + mprintf((0, "Trying to goto wall at bogus segnum\n")); + return 0; + } + + if (Walls[current_wall].sidenum == -1) { + mprintf((0, "Trying to goto wall at bogus sidenum\n")); + return 0; + } + + Cursegp = &Segments[Walls[current_wall].segnum]; + Curside = Walls[current_wall].sidenum; + + return 1; +} + + +int GotoNextWall() { + int current_wall; + + current_wall = Cursegp->sides[Curside].wall_num; // It's ok to be -1 because it will immediately become 0 + + current_wall++; + + if (current_wall >= Num_walls) current_wall = 0; + if (current_wall < 0) current_wall = 0; + + if (Walls[current_wall].segnum == -1) { + mprintf((0, "Trying to goto wall at bogus segnum\n")); + return 0; + } + + if (Walls[current_wall].sidenum == -1) { + mprintf((0, "Trying to goto wall at bogus sidenum\n")); + return 0; + } + + Cursegp = &Segments[Walls[current_wall].segnum]; + Curside = Walls[current_wall].sidenum; + + return 1; +} + + +int PrevWall() { + int wall_type; + + if (Cursegp->sides[Curside].wall_num == -1) { + editor_status("Cannot assign new wall. No wall on curside."); + return 0; + } + + wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num; + + if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) { + + do { + + wall_type--; + + if (wall_type < 0) + wall_type = Num_wall_anims-1; + + if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num) + Error("Cannot find clip for door."); + + } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE); + + } + + else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) { + + do { + + wall_type--; + + if (wall_type < 0) + wall_type = Num_wall_anims-1; + + if (wall_type == Walls[Cursegp->sides[Curside].wall_num].clip_num) + Error("Cannot find clip for blastable wall."); + + } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE)); + + } + + wall_assign_door(wall_type); + + Update_flags |= UF_WORLD_CHANGED; + return 1; +} + +int NextWall() { + int wall_type; + + if (Cursegp->sides[Curside].wall_num == -1) { + editor_status("Cannot assign new wall. No wall on curside."); + return 0; + } + + wall_type = Walls[Cursegp->sides[Curside].wall_num].clip_num; + + if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) { + + do { + + wall_type++; + + if (wall_type >= Num_wall_anims) { + wall_type = 0; + if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1) + Error("Cannot find clip for door."); + } + + } while (WallAnims[wall_type].num_frames == -1 || WallAnims[wall_type].flags & WCF_BLASTABLE); + + } + else if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_BLASTABLE) { + + do { + + wall_type++; + + if (wall_type >= Num_wall_anims) { + wall_type = 0; + if (Walls[Cursegp->sides[Curside].wall_num].clip_num==-1) + Error("Cannot find clip for blastable wall."); + } + + } while (WallAnims[wall_type].num_frames == -1 || !(WallAnims[wall_type].flags & WCF_BLASTABLE)); + + } + + wall_assign_door(wall_type); + + Update_flags |= UF_WORLD_CHANGED; + return 1; + +} + +//------------------------------------------------------------------------- +// Called from the editor... does one instance of the wall dialog box +//------------------------------------------------------------------------- +int do_wall_dialog() +{ + int i; + + // Only open 1 instance of this window... + if ( MainWindow != NULL ) return 0; + + // Close other windows. + close_all_windows(); + + // Open a window with a quit button + MainWindow = ui_open_window( TMAPBOX_X+20, TMAPBOX_Y+20, 765-TMAPBOX_X, 545-TMAPBOX_Y, WIN_DIALOG ); + QuitButton = ui_add_gadget_button( MainWindow, 20, 252, 48, 40, "Done", NULL ); + + // These are the checkboxes for each door flag. + i = 80; + DoorFlag[0] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Locked" ); i += 24; + DoorFlag[1] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Auto" ); i += 24; + DoorFlag[2] = ui_add_gadget_checkbox( MainWindow, 22, i, 16, 16, 0, "Illusion OFF" ); i += 24; + + KeyFlag[0] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "NONE" ); i += 24; + KeyFlag[1] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Blue" ); i += 24; + KeyFlag[2] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Red" ); i += 24; + KeyFlag[3] = ui_add_gadget_radio( MainWindow, 22, i, 16, 16, 0, "Yellow" ); i += 24; + + // The little box the wall will appear in. + WallViewBox = ui_add_gadget_userbox( MainWindow, 155, 5, 64, 64 ); + + // A bunch of buttons... + i = 80; + ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Clip", PrevWall ); + ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Clip >>", NextWall );i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Blastable", wall_add_blastable ); i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Door", wall_add_door ); i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Illusory", wall_add_illusion); i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Add Closed Wall", wall_add_closed_wall ); i+=25; +// ui_add_gadget_button( MainWindow,155,i,140, 22, "Restore All Walls", wall_restore_all ); i += 25; + ui_add_gadget_button( MainWindow,155,i,70, 22, "<< Prev", GotoPrevWall ); + ui_add_gadget_button( MainWindow,155+70,i,70, 22, "Next >>", GotoNextWall );i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Remove Wall", wall_remove ); i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Trigger", bind_wall_to_trigger ); i += 25; + ui_add_gadget_button( MainWindow,155,i,140, 22, "Bind to Control", bind_wall_to_control_center ); i+=25; + + old_wall_num = -2; // Set to some dummy value so everything works ok on the first frame. + + return 1; +} + +void close_wall_window() +{ + if ( MainWindow!=NULL ) { + ui_close_window( MainWindow ); + MainWindow = NULL; + } +} + +void do_wall_window() +{ + int i; + sbyte type; + fix DeltaTime, Temp; + + if ( MainWindow == NULL ) return; + + //------------------------------------------------------------ + // Call the ui code.. + //------------------------------------------------------------ + ui_button_any_drawn = 0; + ui_window_do_gadgets(MainWindow); + + //------------------------------------------------------------ + // If we change walls, we need to reset the ui code for all + // of the checkboxes that control the wall flags. + //------------------------------------------------------------ + if (old_wall_num != Cursegp->sides[Curside].wall_num) { + for ( i=0; i < 3; i++ ) { + DoorFlag[i]->flag = 0; // Tells ui that this button isn't checked + DoorFlag[i]->status = 1; // Tells ui to redraw button + } + for ( i=0; i < 4; i++ ) { + KeyFlag[i]->flag = 0; // Tells ui that this button isn't checked + KeyFlag[i]->status = 1; // Tells ui to redraw button + } + + if ( Cursegp->sides[Curside].wall_num != -1) { + if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_DOOR_LOCKED) + DoorFlag[0]->flag = 1; // Mark this button as checked + if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_DOOR_AUTO) + DoorFlag[1]->flag = 1; // Mark this button as checked + if (Walls[Cursegp->sides[Curside].wall_num].flags & WALL_ILLUSION_OFF) + DoorFlag[2]->flag = 1; // Mark this button as checked + + if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_NONE) + KeyFlag[0]->flag = 1; + if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_BLUE) + KeyFlag[1]->flag = 1; + if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_RED) + KeyFlag[2]->flag = 1; + if (Walls[Cursegp->sides[Curside].wall_num].keys & KEY_GOLD) + KeyFlag[3]->flag = 1; + } + } + + //------------------------------------------------------------ + // If any of the checkboxes that control the wallflags are set, then + // update the corresponding wall flag. + //------------------------------------------------------------ + + if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_DOOR) { + if ( DoorFlag[0]->flag == 1 ) + Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_LOCKED; + else + Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_LOCKED; + if ( DoorFlag[1]->flag == 1 ) + Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_DOOR_AUTO; + else + Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_DOOR_AUTO; + + //------------------------------------------------------------ + // If any of the radio buttons that control the mode are set, then + // update the corresponding key. + //------------------------------------------------------------ + for ( i=0; i < 4; i++ ) { + if ( KeyFlag[i]->flag == 1 ) { + Walls[Cursegp->sides[Curside].wall_num].keys = 1<flag == 1) { + DoorFlag[i]->flag = 0; // Tells ui that this button isn't checked + DoorFlag[i]->status = 1; // Tells ui to redraw button + } + for ( i=0; i < 4; i++ ) { + if ( KeyFlag[i]->flag == 1 ) { + KeyFlag[i]->flag = 0; + KeyFlag[i]->status = 1; + } + } + } + + if (Walls[Cursegp->sides[Curside].wall_num].type == WALL_ILLUSION) { + if ( DoorFlag[2]->flag == 1 ) + Walls[Cursegp->sides[Curside].wall_num].flags |= WALL_ILLUSION_OFF; + else + Walls[Cursegp->sides[Curside].wall_num].flags &= ~WALL_ILLUSION_OFF; + } else + for ( i=2; i < 3; i++ ) + if (DoorFlag[i]->flag == 1) { + DoorFlag[i]->flag = 0; // Tells ui that this button isn't checked + DoorFlag[i]->status = 1; // Tells ui to redraw button + } + + //------------------------------------------------------------ + // A simple frame time counter for animating the walls... + //------------------------------------------------------------ + Temp = timer_get_fixed_seconds(); + DeltaTime = Temp - Time; + + //------------------------------------------------------------ + // Draw the wall in the little 64x64 box + //------------------------------------------------------------ + gr_set_current_canvas( WallViewBox->canvas ); + if (Cursegp->sides[Curside].wall_num != -1) { + type = Walls[Cursegp->sides[Curside].wall_num].type; + if ((type == WALL_DOOR) || (type == WALL_BLASTABLE)) { + if (DeltaTime > ((F1_0*200)/1000)) { + framenum++; + Time = Temp; + } + if (framenum >= WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].num_frames) + framenum=0; + PIGGY_PAGE_IN(Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[framenum]]); + gr_ubitmap(0,0, &GameBitmaps[Textures[WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].frames[framenum]].index]); + } else { + if (type == WALL_OPEN) + gr_clear_canvas( CBLACK ); + else { + if (Cursegp->sides[Curside].tmap_num2 > 0) + gr_ubitmap(0,0, texmerge_get_cached_bitmap( Cursegp->sides[Curside].tmap_num, Cursegp->sides[Curside].tmap_num2)); + else { + PIGGY_PAGE_IN(Textures[Cursegp->sides[Curside].tmap_num]); + gr_ubitmap(0,0, &GameBitmaps[Textures[Cursegp->sides[Curside].tmap_num].index]); + } + } + } + } else + gr_clear_canvas( CGREY ); + + //------------------------------------------------------------ + // If anything changes in the ui system, redraw all the text that + // identifies this wall. + //------------------------------------------------------------ + if (ui_button_any_drawn || (old_wall_num != Cursegp->sides[Curside].wall_num) ) { + if ( Cursegp->sides[Curside].wall_num > -1 ) { + ui_wprintf_at( MainWindow, 12, 6, "Wall: %d ", Cursegp->sides[Curside].wall_num); + switch (Walls[Cursegp->sides[Curside].wall_num].type) { + case WALL_NORMAL: + ui_wprintf_at( MainWindow, 12, 23, " Type: Normal " ); + break; + case WALL_BLASTABLE: + ui_wprintf_at( MainWindow, 12, 23, " Type: Blastable" ); + break; + case WALL_DOOR: + ui_wprintf_at( MainWindow, 12, 23, " Type: Door " ); + ui_wprintf_at( MainWindow, 223, 6, "%s", WallAnims[Walls[Cursegp->sides[Curside].wall_num].clip_num].filename); + break; + case WALL_ILLUSION: + ui_wprintf_at( MainWindow, 12, 23, " Type: Illusion " ); + break; + case WALL_OPEN: + ui_wprintf_at( MainWindow, 12, 23, " Type: Open " ); + break; + case WALL_CLOSED: + ui_wprintf_at( MainWindow, 12, 23, " Type: Closed " ); + break; + default: + ui_wprintf_at( MainWindow, 12, 23, " Type: Unknown " ); + break; + } + if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR) + ui_wprintf_at( MainWindow, 223, 6, " " ); + + ui_wprintf_at( MainWindow, 12, 40, " Clip: %d ", Walls[Cursegp->sides[Curside].wall_num].clip_num ); + ui_wprintf_at( MainWindow, 12, 57, " Trigger: %d ", Walls[Cursegp->sides[Curside].wall_num].trigger ); + } else { + ui_wprintf_at( MainWindow, 12, 6, "Wall: none "); + ui_wprintf_at( MainWindow, 12, 23, " Type: none "); + ui_wprintf_at( MainWindow, 12, 40, " Clip: none "); + ui_wprintf_at( MainWindow, 12, 57, " Trigger: none "); + } + Update_flags |= UF_WORLD_CHANGED; + } + if ( QuitButton->pressed || (last_keypress==KEY_ESC) ) { + close_wall_window(); + return; + } + + old_wall_num = Cursegp->sides[Curside].wall_num; +} + + +//--------------------------------------------------------------------- +// Restore all walls to original status (closed doors, repaired walls) +int wall_restore_all() +{ + int i, j; + int wall_num; + + for (i=0;i wall_num) + Segments[seg].sides[side].wall_num--; + + mprintf((0,"BOGUS WALL DELETED!!!!\n")); + + return 1; +} + + +//--------------------------------------------------------------------- +// Remove a specific side. +int wall_remove_side(segment *seg, short side) +{ + int Connectside; + segment *csegp; + int lower_wallnum; + int w, s, t, l, t1; + + if (IS_CHILD(seg->children[side]) && IS_CHILD(seg->sides[side].wall_num)) { + csegp = &Segments[seg->children[side]]; + Connectside = find_connect_side(seg, csegp); + + remove_trigger(seg, side); + remove_trigger(csegp, Connectside); + + // Remove walls 'wall_num' and connecting side 'wall_num' + // from Walls array. + lower_wallnum = seg->sides[side].wall_num; + if (csegp->sides[Connectside].wall_num < lower_wallnum) + lower_wallnum = csegp->sides[Connectside].wall_num; + + if (Walls[lower_wallnum].linked_wall != -1) + Walls[Walls[lower_wallnum].linked_wall].linked_wall = -1; + if (Walls[lower_wallnum+1].linked_wall != -1) + Walls[Walls[lower_wallnum+1].linked_wall].linked_wall = -1; + + for (w=lower_wallnum;w lower_wallnum+1) + Segments[s].sides[w].wall_num -= 2; + + // Destroy any links to the deleted wall. + for (t=0;tsides[side].wall_num = -1; + csegp->sides[Connectside].wall_num = -1; + + Update_flags |= UF_WORLD_CHANGED; + return 1; + } + + editor_status( "Can't remove wall. No wall present."); + return 0; +} + +//--------------------------------------------------------------------- +// Remove a special wall. +int wall_remove() +{ + return wall_remove_side(Cursegp, Curside); +} + +//--------------------------------------------------------------------- +// Add a wall to curside +int wall_add_to_side(segment *segp, int side, sbyte type) +{ + int connectside; + segment *csegp; + + if (add_wall(segp, side)) { + csegp = &Segments[segp->children[side]]; + connectside = find_connect_side(segp, csegp); + + Walls[segp->sides[side].wall_num].segnum = segp-Segments; + Walls[csegp->sides[connectside].wall_num].segnum = csegp-Segments; + + Walls[segp->sides[side].wall_num].sidenum = side; + Walls[csegp->sides[connectside].wall_num].sidenum = connectside; + + Walls[segp->sides[side].wall_num].flags = 0; + Walls[csegp->sides[connectside].wall_num].flags = 0; + + Walls[segp->sides[side].wall_num].type = type; + Walls[csegp->sides[connectside].wall_num].type = type; + +// Walls[segp->sides[side].wall_num].trigger = -1; +// Walls[csegp->sides[connectside].wall_num].trigger = -1; + + Walls[segp->sides[side].wall_num].clip_num = -1; + Walls[csegp->sides[connectside].wall_num].clip_num = -1; + + Walls[segp->sides[side].wall_num].keys = KEY_NONE; + Walls[csegp->sides[connectside].wall_num].keys = KEY_NONE; + + if (type == WALL_BLASTABLE) { + Walls[segp->sides[side].wall_num].hps = WALL_HPS; + Walls[csegp->sides[connectside].wall_num].hps = WALL_HPS; + + //Walls[segp->sides[side].wall_num].clip_num = 0; + //Walls[csegp->sides[connectside].wall_num].clip_num = 0; + } + + if (type != WALL_DOOR) { + segp->sides[side].tmap_num2 = 0; + csegp->sides[connectside].tmap_num2 = 0; + } + + if (type == WALL_DOOR) { + Walls[segp->sides[side].wall_num].flags |= WALL_DOOR_AUTO; + Walls[csegp->sides[connectside].wall_num].flags |= WALL_DOOR_AUTO; + + Walls[segp->sides[side].wall_num].clip_num = Current_door_type; + Walls[csegp->sides[connectside].wall_num].clip_num = Current_door_type; + } + + //Update_flags |= UF_WORLD_CHANGED; + //return 1; + +// return NextWall(); //assign a clip num + return wall_assign_door(Current_door_type); + + } else { + editor_status( "Cannot add wall here, no children" ); + return 0; + } +} + + +//--------------------------------------------------------------------- +// Add a wall to markedside +int wall_add_to_markedside(sbyte type) +{ + int Connectside; + segment *csegp; + + if (add_wall(Markedsegp, Markedside)) { + int wall_num, cwall_num; + csegp = &Segments[Markedsegp->children[Markedside]]; + + Connectside = find_connect_side(Markedsegp, csegp); + + wall_num = Markedsegp->sides[Markedside].wall_num; + cwall_num = csegp->sides[Connectside].wall_num; + + Walls[wall_num].segnum = Markedsegp-Segments; + Walls[cwall_num].segnum = csegp-Segments; + + Walls[wall_num].sidenum = Markedside; + Walls[cwall_num].sidenum = Connectside; + + Walls[wall_num].flags = 0; + Walls[cwall_num].flags = 0; + + Walls[wall_num].type = type; + Walls[cwall_num].type = type; + + Walls[wall_num].trigger = -1; + Walls[cwall_num].trigger = -1; + + Walls[wall_num].clip_num = -1; + Walls[cwall_num].clip_num = -1; + + Walls[wall_num].keys = KEY_NONE; + Walls[cwall_num].keys = KEY_NONE; + + if (type == WALL_BLASTABLE) { + Walls[wall_num].hps = WALL_HPS; + Walls[cwall_num].hps = WALL_HPS; + + Walls[wall_num].clip_num = 0; + Walls[cwall_num].clip_num = 0; + } + + if (type != WALL_DOOR) { + Markedsegp->sides[Markedside].tmap_num2 = 0; + csegp->sides[Connectside].tmap_num2 = 0; + } + + Update_flags |= UF_WORLD_CHANGED; + return 1; + } else { + editor_status( "Cannot add wall here, no children" ); + return 0; + } +} + + +int wall_add_door_flag(sbyte flag) +{ + int Connectside; + segment *csegp; + + if (Cursegp->sides[Curside].wall_num == -1) + { + editor_status("Cannot change flag. No wall at Curside."); + return 0; + } + + if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR) + { + editor_status("Cannot change flag. No door at Curside."); + return 0; + } + + csegp = &Segments[Cursegp->children[Curside]]; + Connectside = find_connect_side(Cursegp, csegp); + + Walls[Cursegp->sides[Curside].wall_num].flags |= flag; + Walls[csegp->sides[Connectside].wall_num].flags |= flag; + + Update_flags |= UF_ED_STATE_CHANGED; + return 1; +} + +int wall_remove_door_flag(sbyte flag) +{ + int Connectside; + segment *csegp; + + if (Cursegp->sides[Curside].wall_num == -1) + { + editor_status("Cannot change flag. No wall at Curside."); + return 0; + } + + if (Walls[Cursegp->sides[Curside].wall_num].type != WALL_DOOR) + { + editor_status("Cannot change flag. No door at Curside."); + return 0; + } + + csegp = &Segments[Cursegp->children[Curside]]; + Connectside = find_connect_side(Cursegp, csegp); + + Walls[Cursegp->sides[Curside].wall_num].flags &= ~flag; + Walls[csegp->sides[Connectside].wall_num].flags &= ~flag; + + Update_flags |= UF_ED_STATE_CHANGED; + return 1; +} + + +int bind_wall_to_control_center() { + + int link_num; + int i; + + if (Cursegp->sides[Curside].wall_num == -1) { + editor_status("No wall at Curside."); + return 0; + } + + link_num = ControlCenterTriggers.num_links; + for (i=0;isides[Curside].wall_num != -1) + w1 = &Walls[Cursegp->sides[Curside].wall_num]; + + if (Markedsegp->sides[Markedside].wall_num != -1) + w2 = &Walls[Markedsegp->sides[Markedside].wall_num]; + + if (!w1 || w1->type != WALL_DOOR) { + editor_status("Curseg/curside is not a door"); + return 0; + } + + if (!w2 || w2->type != WALL_DOOR) { + editor_status("Markedseg/markedside is not a door"); + return 0; + } + + if (w1->linked_wall != -1) + editor_status("Curseg/curside is already linked"); + + if (w2->linked_wall != -1) + editor_status("Markedseg/markedside is already linked"); + + w1->linked_wall = w2-Walls; + w2->linked_wall = w1-Walls; + + return 1; +} + +int wall_unlink_door() +{ + wall *w1=NULL; + + if (Cursegp->sides[Curside].wall_num != -1) + w1 = &Walls[Cursegp->sides[Curside].wall_num]; + + if (!w1 || w1->type != WALL_DOOR) { + editor_status("Curseg/curside is not a door"); + return 0; + } + + if (w1->linked_wall == -1) + editor_status("Curseg/curside is not linked"); + + Assert(Walls[w1->linked_wall].linked_wall == w1-Walls); + + Walls[w1->linked_wall].linked_wall = -1; + w1->linked_wall = -1; + + return 1; + +} + +#define DIAGNOSTIC_MESSAGE_MAX 150 + +int check_walls() +{ + int w, seg, side, wall_count, trigger_count; + int w1, w2, t, l; + count_wall CountedWalls[MAX_WALLS]; + char Message[DIAGNOSTIC_MESSAGE_MAX]; + int matcen_num; + + wall_count = 0; + for (seg=0;seg<=Highest_segment_index;seg++) + if (Segments[seg].segnum != -1) { + // Check fuelcenters + matcen_num = Segments[seg].matcen_num; + if (matcen_num == 0) + if (RobotCenters[0].segnum != seg) { + mprintf((0,"Fixing Matcen 0\n")); + Segments[seg].matcen_num = -1; + } + + if (matcen_num > -1) + if (RobotCenters[matcen_num].segnum != seg) { + mprintf((0,"Matcen [%d] (seg %d) doesn't point back to correct segment %d\n", matcen_num, RobotCenters[matcen_num].segnum, seg)); + mprintf((0,"Fixing....\n")); + RobotCenters[matcen_num].segnum = seg; + } + + for (side=0;side= Num_walls) + mprintf((0,"wallnum %d in Segments exceeds Num_walls!\n", CountedWalls[w].wallnum)); + + if (Walls[w].segnum == -1) { + mprintf((0, "Wall[%d] is BOGUS\n", w)); + for (seg=0;seg<=Highest_segment_index;seg++) + for (side=0;side +#include +#include +#include + +#include "mono.h" +#include "key.h" +#include "gr.h" + +#include "bm.h" // for MAX_TEXTURES + +#include "inferno.h" +#include "segment.h" +#include "editor.h" +#include "error.h" +#include "textures.h" +#include "object.h" + +#include "gamemine.h" +#include "gameseg.h" + +#include "ui.h" // Because texpage.h need UI_WINDOW type +#include "texpage.h" // For texpage_goto_first + +#include "medwall.h" +#include "switch.h" + +#include "nocfile.h" +#include "fuelcen.h" + +#define REMOVE_EXT(s) (*(strchr( (s), '.' ))='\0') + +int CreateDefaultNewSegment(); +int save_mine_data(CFILE * SaveFile); +int save_mine_data_compiled_new(FILE * SaveFile); + +static char current_tmap_list[MAX_TEXTURES][13]; + +// ----------------------------------------------------------------------------- +// Save mine will: +// 1. Write file info, header info, editor info, vertex data, segment data, +// and new_segment in that order, marking their file offset. +// 2. Go through all the fields and fill in the offset, size, and sizeof +// values in the headers. + +int med_save_mine(char * filename) +{ + FILE * SaveFile; + char ErrorMessage[256]; + + SaveFile = cfopen( filename, CF_WRITE_MODE ); + if (!SaveFile) + { +#ifndef __LINUX__ + char fname[20]; + _splitpath( filename, NULL, NULL, fname, NULL ); + + sprintf( ErrorMessage, \ + "ERROR: Cannot write to '%s'.\nYou probably need to check out a locked\nversion of the file. You should save\nthis under a different filename, and then\ncheck out a locked copy by typing\n\'co -l %s.lvl'\nat the DOS prompt.\n" + , filename, fname); +#endif + sprintf( ErrorMessage, "ERROR: Unable to open %s\n", filename ); + MessageBox( -2, -2, 1, ErrorMessage, "Ok" ); + return 1; + } + + save_mine_data(SaveFile); + + //==================== CLOSE THE FILE ============================= + cfclose(SaveFile); + + return 0; + +} + +// ----------------------------------------------------------------------------- +// saves to an already-open file +int save_mine_data(CFILE * SaveFile) +{ + int header_offset, editor_offset, vertex_offset, segment_offset, doors_offset, texture_offset, walls_offset, triggers_offset; //, links_offset; + int newseg_verts_offset; + int newsegment_offset; + int i; + + med_compress_mine(); + warn_if_concave_segments(); + + for (i=0;i>nbits); + if( int_value > 0x7fff ) { + short_value = 0x7fff; + mprintf((1, "Warning: Fix (%8x) won't fit in short. Saturating to %8x.\n", int_value, short_value<> nbits; + + if( int_value > 0xffff ) { + short_value = 0xffff; + mprintf((1, "Warning: Fix (%8x) won't fit in unsigned short. Saturating to %8x.\n", int_value, short_value<= MAX_GAME_SEGMENTS) { + char message[128]; + sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_GAME_SEGMENTS); + MessageBox( -2, -2, 1, message, "Ok" ); + } + + if (Highest_vertex_index >= MAX_GAME_VERTICES) { + char message[128]; + sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_GAME_VERTICES); + MessageBox( -2, -2, 1, message, "Ok" ); + } + + //=============================== Writing part ============================== + cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version + cfwrite( &Num_vertices, sizeof(int), 1, SaveFile ); // 4 bytes = Num_vertices + cfwrite( &Num_segments, sizeof(int), 1, SaveFile ); // 4 bytes = Num_segments + cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile ); + + for (segnum=0; segnum>5, write as short, l>>1 write as short) + for (i=0; i<4; i++ ) { + dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].u, 5, SaveFile ); + dump_fix_as_short( Segments[segnum].sides[sidenum].uvls[i].v, 5, SaveFile ); + dump_fix_as_ushort( Segments[segnum].sides[sidenum].uvls[i].l, 1, SaveFile ); + //cfwrite( &Segments[segnum].sides[sidenum].uvls[i].l, sizeof(fix), 1, SaveFile ); + } + } + } + + } + + return 0; +} + +// ----------------------------------------------------------------------------- +// saves compiled mine data to an already-open file... +int save_mine_data_compiled_new(FILE * SaveFile) +{ + short i, segnum, sidenum, temp_short; + ubyte version = COMPILED_MINE_VERSION; + ubyte bit_mask = 0; + + med_compress_mine(); + warn_if_concave_segments(); + + if (Highest_segment_index >= MAX_GAME_SEGMENTS) { + char message[128]; + sprintf(message, "Error: Too many segments (%i > %i) for game (not editor)", Highest_segment_index+1, MAX_GAME_SEGMENTS); + MessageBox( -2, -2, 1, message, "Ok" ); + } + + if (Highest_vertex_index >= MAX_GAME_VERTICES) { + char message[128]; + sprintf(message, "Error: Too many vertices (%i > %i) for game (not editor)", Highest_vertex_index+1, MAX_GAME_VERTICES); + MessageBox( -2, -2, 1, message, "Ok" ); + } + + //=============================== Writing part ============================== + cfwrite( &version, sizeof(ubyte), 1, SaveFile ); // 1 byte = compiled version + temp_short = Num_vertices; + cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_vertices + temp_short = Num_segments; + cfwrite( &temp_short, sizeof(short), 1, SaveFile ); // 2 bytes = Num_segments + cfwrite( Vertices, sizeof(vms_vector), Num_vertices, SaveFile ); + + for (segnum=0; segnum= 0) { + bit_mask |= (1 << sidenum); + wallnum = Segments[segnum].sides[sidenum].wall_num; + Assert( wallnum < 255 ); // Get John or Mike.. can only store up to 255 walls!!! + } + } + cfwrite( &bit_mask, sizeof(ubyte), 1, SaveFile ); + + for (sidenum=0; sidenum N_polygon_models +// Cur_robot_type --> Cur_robot_type +// Texture[Cur_robot_type]->bitmap ---> robot_bms[robot_bm_nums[ Cur_robot_type ] ] + +#include +#include + + +#include "inferno.h" +#include "screens.h" // For GAME_SCREEN????? +#include "editor.h" // For TMAP_CURBOX?????? +#include "gr.h" // For canves, font stuff +#include "ui.h" // For UI_GADGET stuff +#include "object.h" // For robot_bms +#include "mono.h" // For debugging +#include "error.h" + +#include "objpage.h" +#include "bm.h" +#include "player.h" +#include "piggy.h" + + +#define OBJS_PER_PAGE 8 + +static UI_GADGET_USERBOX * ObjBox[OBJS_PER_PAGE]; +static UI_GADGET_USERBOX * ObjCurrent; + +static int ObjectPage = 0; + +//static char Description[8][20] = { "Pig", "Star", "Little\nJosh", "Big\nJosh", "Flying\nPig", "Flying\nStar", +//"Little\nFlying\nJosh", "Big\nFlying\nJosh" }; + +//static grs_canvas * ObjnameCanvas; +//static char object_filename[13]; + +//static void objpage_print_name( char name[13] ) { +// short w,h,aw; +// +// gr_set_current_canvas( ObjnameCanvas ); +// gr_get_string_size( name, &w, &h, &aw ); +// gr_string( 0, 0, name ); +// //gr_set_fontcolor( CBLACK, CWHITE ); +//} + +//static void objpage_display_name( char *format, ... ) { +// va_list ap; +// +// va_start(ap, format); +// vsprintf(object_filename, format, ap); +// va_end(ap); +// +// objpage_print_name(object_filename); +// +//} + +#include "vecmat.h" +#include "3d.h" +#include "polyobj.h" +#include "texmap.h" + +#include "hostage.h" +#include "powerup.h" + +vms_angvec objpage_view_orient; +fix objpage_view_dist; + +//this is bad to have the extern, but this snapshot stuff is special +extern int polyobj_lighting; + + +//canvas set +// Type is optional. If you pass -1, type is determined, else type is used, and id is not xlated through ObjId. +void draw_robot_picture(int id, vms_angvec *orient_angles, int type) +{ + + if (id >= Num_total_object_types) + return; + + if ( type == -1 ) { + type = ObjType[id]; // Find the object type, given an object id. + id = ObjId[id]; // Translate to sub-id. + } + + switch (type) { + + case OL_HOSTAGE: + PIGGY_PAGE_IN(Vclip[Hostage_vclip_num[id]].frames[0]); + gr_bitmap(0,0,&GameBitmaps[Vclip[Hostage_vclip_num[id]].frames[0].index]); + break; + + case OL_POWERUP: + if ( Powerup_info[id].vclip_num > -1 ) { + PIGGY_PAGE_IN(Vclip[Powerup_info[id].vclip_num].frames[0]); + gr_bitmap(0,0,&GameBitmaps[Vclip[Powerup_info[id].vclip_num].frames[0].index]); + } + break; + + case OL_PLAYER: + draw_model_picture(Player_ship->model_num,orient_angles); // Draw a poly model below + break; + + case OL_ROBOT: + draw_model_picture(Robot_info[id].model_num,orient_angles); // Draw a poly model below + break; + + case OL_CONTROL_CENTER: + case OL_CLUTTER: + draw_model_picture(id,orient_angles); + break; + default: + //Int3(); // Invalid type!!! + return; + } + +} + +void redraw_current_object() +{ + grs_canvas * cc; + + cc = grd_curcanv; + gr_set_current_canvas(ObjCurrent->canvas); + draw_robot_picture(Cur_robot_type,&objpage_view_orient, -1); + gr_set_current_canvas(cc); +} + +void gr_label_box( int i) +{ + + gr_clear_canvas(BM_XRGB(0,0,0)); + draw_robot_picture(i,&objpage_view_orient, -1); + +// char s[20]; +// sprintf( s, " %d ", i ); +// gr_clear_canvas( BM_XRGB(0,15,0) ); +// gr_set_fontcolor( CWHITE, BM_XRGB(0,15,0) ); +// ui_string_centered( grd_curcanv->cv_bitmap.bm_w/2, grd_curcanv->cv_bitmap.bm_h/2, Description[i] ); +} + +int objpage_goto_first() +{ + int i; + + ObjectPage=0; + for (i=0; icanvas); + if (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types ) { + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); + gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); + } else + gr_clear_canvas( CGREY ); + } + + return 1; +} + +int objpage_goto_last() +{ + int i; + + ObjectPage=(Num_total_object_types)/OBJS_PER_PAGE; + for (i=0; icanvas); + if (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types ) + { + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); + gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); + } else { + gr_clear_canvas( CGREY ); + } + } + return 1; +} + +static int objpage_goto_prev() +{ + int i; + if (ObjectPage > 0) { + ObjectPage--; + for (i=0; icanvas); + if (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types) + { + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); + gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); + } else { + gr_clear_canvas( CGREY ); + } + } + } + return 1; +} + +static int objpage_goto_next() +{ + int i; + if ((ObjectPage+1)*OBJS_PER_PAGE < Num_total_object_types) { + ObjectPage++; + for (i=0; icanvas); + if (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types) + { + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); + gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); + } else { + gr_clear_canvas( CGREY ); + } + } + } + return 1; +} + +int objpage_grab_current(int n) +{ + int i; + + if ( (n<0) || ( n>= Num_total_object_types) ) return 0; + + ObjectPage = n / OBJS_PER_PAGE; + + if (ObjectPage*OBJS_PER_PAGE < Num_total_object_types) { + for (i=0; icanvas); + if (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types) + { + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); + gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); + } else { + gr_clear_canvas( CGREY ); + } + } + } + + Cur_robot_type = n; + gr_set_current_canvas(ObjCurrent->canvas); + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ Cur_robot_type ] ] ); + gr_label_box(Cur_robot_type); + + //objpage_display_name( Texture[Cur_robot_type]->filename ); + + return 1; +} + +int objpage_goto_next_object() +{ + int n; + + n = Cur_robot_type++; + if (n >= Num_total_object_types) n = 0; + + objpage_grab_current(n); + + return 1; + +} + +#define OBJBOX_X (TMAPBOX_X) //location of first one +#define OBJBOX_Y (OBJCURBOX_Y - 24 ) +#define OBJBOX_W 64 +#define OBJBOX_H 64 + +#define DELTA_ANG 0x800 + +int objpage_increase_pitch() +{ + objpage_view_orient.p += DELTA_ANG; + redraw_current_object(); + return 1; +} + +int objpage_decrease_pitch() +{ + objpage_view_orient.p -= DELTA_ANG; + redraw_current_object(); + return 1; +} + +int objpage_increase_heading() +{ + objpage_view_orient.h += DELTA_ANG; + redraw_current_object(); + return 1; +} + +int objpage_decrease_heading() +{ + objpage_view_orient.h -= DELTA_ANG; + redraw_current_object(); + return 1; +} + +int objpage_increase_bank() +{ + objpage_view_orient.b += DELTA_ANG; + redraw_current_object(); + return 1; +} + +int objpage_decrease_bank() +{ + objpage_view_orient.b -= DELTA_ANG; + redraw_current_object(); + return 1; +} + +int objpage_increase_z() +{ + objpage_view_dist -= 0x8000; + redraw_current_object(); + return 1; +} + +int objpage_decrease_z() +{ + objpage_view_dist += 0x8000; + redraw_current_object(); + return 1; +} + +int objpage_reset_orient() +{ + objpage_view_orient.p = 0; + objpage_view_orient.b = 0; + objpage_view_orient.h = -0x8000; + //objpage_view_dist = DEFAULT_VIEW_DIST; + redraw_current_object(); + return 1; +} + + +// INIT TEXTURE STUFF + +void objpage_init( UI_WINDOW *win ) +{ + int i; + + //Num_total_object_types = N_polygon_models + N_hostage_types + N_powerup_types; + //Assert (N_polygon_models < MAX_POLYGON_MODELS); + //Assert (Num_total_object_types < MAX_OBJTYPE ); + //Assert (N_hostage_types < MAX_HOSTAGE_TYPES ); + //Assert (N_powerup_types < MAX_POWERUP_TYPES ); + // Assert (N_robot_types < MAX_ROBOTS); + + ui_add_gadget_button( win, OBJCURBOX_X + 00, OBJCURBOX_Y - 27, 30, 20, "<<", objpage_goto_prev ); + ui_add_gadget_button( win, OBJCURBOX_X + 32, OBJCURBOX_Y - 27, 30, 20, ">>", objpage_goto_next ); + + ui_add_gadget_button( win, OBJCURBOX_X + 00, OBJCURBOX_Y - 54, 30, 20, "B", objpage_goto_first ); + ui_add_gadget_button( win, OBJCURBOX_X + 32, OBJCURBOX_Y - 54, 30, 20, "E", objpage_goto_last ); + + ui_add_gadget_button( win, OBJCURBOX_X + 25, OBJCURBOX_Y + 62, 22, 13, "P-", objpage_decrease_pitch ); + ui_add_gadget_button( win, OBJCURBOX_X + 25, OBJCURBOX_Y + 90, 22, 13, "P+", objpage_increase_pitch ); + ui_add_gadget_button( win, OBJCURBOX_X + 00, OBJCURBOX_Y + 90, 22, 13, "B-", objpage_decrease_bank ); + ui_add_gadget_button( win, OBJCURBOX_X + 50, OBJCURBOX_Y + 90, 22, 13, "B+", objpage_increase_bank ); + ui_add_gadget_button( win, OBJCURBOX_X + 00, OBJCURBOX_Y + 76, 22, 13, "H-", objpage_decrease_heading ); + ui_add_gadget_button( win, OBJCURBOX_X + 50, OBJCURBOX_Y + 76, 22, 13, "H+", objpage_increase_heading ); + ui_add_gadget_button( win, OBJCURBOX_X + 00, OBJCURBOX_Y + 62, 22, 13, "Z+", objpage_increase_z ); + ui_add_gadget_button( win, OBJCURBOX_X + 50, OBJCURBOX_Y + 62, 22, 13, "Z-", objpage_decrease_z ); + ui_add_gadget_button( win, OBJCURBOX_X + 25, OBJCURBOX_Y + 76, 22, 13, "R", objpage_reset_orient ); + + for (i=0;icanvas); + if (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types) + { + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ i+ObjectPage*OBJS_PER_PAGE ] ] ); + gr_label_box(i+ObjectPage*OBJS_PER_PAGE ); + } else { + gr_clear_canvas( CGREY ); + } + } + +// Don't reset robot_type when we return to editor. +// Cur_robot_type = ObjectPage*OBJS_PER_PAGE; + gr_set_current_canvas(ObjCurrent->canvas); + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ Cur_robot_type ] ] ); + gr_label_box(Cur_robot_type); + + //ObjnameCanvas = gr_create_sub_canvas(&grd_curscreen->sc_canvas, OBJCURBOX_X , OBJCURBOX_Y + OBJBOX_H + 10, 100, 20); + //gr_set_current_canvas( ObjnameCanvas ); + //gr_set_curfont( ui_small_font ); + //gr_set_fontcolor( CBLACK, CWHITE ); + //objpage_display_name( Texture[Cur_robot_type]->filename ); + +} + +void objpage_close() +{ + //gr_free_sub_canvas(ObjnameCanvas); +} + + +// DO TEXTURE STUFF + +void objpage_do() +{ + int i; + + for (i=0; ib1_clicked && (i+ObjectPage*OBJS_PER_PAGE < Num_total_object_types)) + { + Cur_robot_type = i+ObjectPage*OBJS_PER_PAGE; + gr_set_current_canvas(ObjCurrent->canvas); + //gr_ubitmap(0,0, robot_bms[robot_bm_nums[ Cur_robot_type ] ] ); + gr_label_box(Cur_robot_type); + //objpage_display_name( Texture[Cur_robot_type]->filename ); + } + } +} diff --git a/main/editor/objpage.h b/main/editor/objpage.h new file mode 100644 index 00000000..e97a1e18 --- /dev/null +++ b/main/editor/objpage.h @@ -0,0 +1,71 @@ +/* +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/objpage.h,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * object selection stuff. + * + * $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:32 john + * Version 2.0! No anonymous unions, Watcom 10.0, with no need + * for bitmaps.tbl. + * + * Revision 1.8 1994/11/02 16:19:20 matt + * Moved draw_model_picture() out of editor, and cleaned up code + * + * Revision 1.7 1994/07/28 16:59:36 mike + * objects containing objects. + * + * Revision 1.6 1994/05/17 14:45:48 mike + * Get object type and id from ObjectType and ObjectId. + * + * Revision 1.5 1994/05/17 12:03:55 mike + * Deal with little known fact that polygon object != robot. + * + * Revision 1.4 1994/05/14 18:00:33 matt + * Got rid of externs in source (non-header) files + * + * Revision 1.3 1994/04/01 11:17:06 yuan + * Added objects to objpage. Added buttons for easier tmap scrolling. + * Objects are selected fully from objpage and add object menu or pad. + * + * Revision 1.2 1993/12/16 17:26:27 john + * Moved texture and object selection to texpage and objpage + * + * Revision 1.1 1993/12/16 16:13:08 john + * Initial revision + * + * + */ + +#ifndef _OBJPAGE_H +#define _OBJPAGE_H + +#include "ui.h" + +int objpage_grab_current(int n); +int objpage_goto_first(); + +void objpage_init( UI_WINDOW *win ); +void objpage_close(); +void objpage_do(); + +extern void draw_robot_picture(int id, vms_angvec *orient_angles, int type); + +#endif diff --git a/main/editor/seguvs.c b/main/editor/seguvs.c new file mode 100644 index 00000000..559652f1 --- /dev/null +++ b/main/editor/seguvs.c @@ -0,0 +1,1656 @@ +/* +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.c,v $ + * $Revision: 1.1 $ + * $Author: btb $ + * $Date: 2004-12-19 13:54:27 $ + * + * u,v coordinate computation for segment faces + * + * $Log: not supported by cvs2svn $ + * Revision 1.2 2003/03/09 06:34:09 donut + * change byte typedef to sbyte to avoid conflict with win32 byte which is unsigned + * + * Revision 1.1.1.1 1999/06/14 22:04:31 donut + * Import of d1x 1.37 source. + * + * Revision 2.1 1995/05/08 10:49:34 mike + * fix lighting bug: oblong segments could be very dark. + * + * Revision 2.0 1995/02/27 11:36:37 john + * Version 2.0. Ansi-fied. + * + * Revision 1.84 1994/11/27 23:17:18 matt + * Made changes for new mprintf calling convention + * + * Revision 1.83 1994/11/17 14:48:02 mike + * validation functions moved from editor to game. + * + * Revision 1.82 1994/10/15 19:08:26 mike + * Disable exhaustive search mprintfs in find_point_seg during lighting. + * + * Revision 1.81 1994/08/25 21:55:50 mike + * IS_CHILD stuff. + * + * Revision 1.80 1994/08/04 19:13:22 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.79 1994/08/03 10:31:33 mike + * Texture map propagation without uv assignment. + * + * Revision 1.78 1994/08/01 13:31:12 matt + * Made fvi() check holes in transparent walls, and changed fvi() calling + * parms to take all input data in query structure. + * + * Revision 1.77 1994/07/08 14:31:24 matt + * New parms for FVI + * + * Revision 1.76 1994/06/23 14:01:04 mike + * Fix cache bug which caused some vertices to not get light, mainly + * noticeable at joints which had doors. + * + * Revision 1.75 1994/06/22 17:33:11 mike + * Make position of light (which is always towards center of segment from + * actual light panel) constant, not dependent on segment size, which fixes + * bug of dark light panels in very large segments. + * + * Revision 1.74 1994/06/21 18:58:18 mike + * Fix stupid bug in light propagation, was using wrong vector in fvi caching. + * + * Revision 1.73 1994/06/20 11:20:24 mike + * Fix stupid lighting bug introduced when I went to cached fvi results. + * + * Revision 1.72 1994/06/19 16:26:37 mike + * Speed up lighting by storing and hashing fvi results. + * + * Revision 1.71 1994/06/17 16:05:56 mike + * Support optional quick lighting propagation: no find_vector_intersection. + * + * Revision 1.70 1994/06/15 15:42:30 mike + * Propagate static_light. + * + * Revision 1.69 1994/06/14 16:59:37 mike + * Fix references to tmap_num2, must strip off orientation bits. + * + * Revision 1.68 1994/06/09 09:58:58 matt + * Moved find_vector_intersection() from physics.c to new file fvi.c + * + * + * Revision 1.67 1994/06/08 18:14:02 mike + * mprintf a dot in light casting. + * + * Revision 1.66 1994/06/08 14:37:45 mike + * double static light value in going from value (a short) to static_light (a fix). + * + * Revision 1.65 1994/06/08 14:29:44 matt + * Added static_light field to segment structure, and padded side struct + * to be longword aligned. + * + * Revision 1.64 1994/06/08 11:45:24 mike + * New, supercool, superslow lighting function. + * + * Revision 1.63 1994/06/07 09:38:11 mike + * Make lighting function yet better by calling find_vector_intersection. + * + * Revision 1.62 1994/06/06 13:14:33 mike + * Make illusory walls cast light. + * + * Revision 1.61 1994/06/05 20:39:47 mike + * Add new distance and dot product based lighting function. + * + * Revision 1.60 1994/05/31 12:31:18 mike + * fix bugs in lighting, though it's not perfect, will be changing all + * lighting to be distance based. Bug had to do with not handling one + * of the return values from WALL_IS_DOORWAY, so assuming light couldn't + * be recursively propagated almost all the time. + * + * Revision 1.59 1994/05/19 23:35:26 mike + * Support uv coordinates in range 0..1.0. + * + * Revision 1.58 1994/05/19 12:10:21 matt + * Use new vecmat macros and globals + * + * Revision 1.57 1994/05/04 19:15:53 mike + * Error checking for degenerate segments. + * + * Revision 1.56 1994/05/03 11:02:34 mike + * Change how default texture map assignment works; now pixels are constant size. + * + * Revision 1.55 1994/04/28 23:25:26 yuan + * Obliterated warnings. + * + */ + + +#ifdef RCS +static char rcsid[] = "$Id: seguvs.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include "inferno.h" +#include "segment.h" +#include "editor/editor.h" + +#include "gameseg.h" + +#include "fix.h" +#include "mono.h" +#include "error.h" + +#include "wall.h" +#include "editor/kdefs.h" +#include "bm.h" // Needed for TmapInfo +#include "effects.h" // Needed for effects_bm_num +#include "fvi.h" + +void cast_all_light_in_mine(int quick_flag); +//--rotate_uvs-- vms_vector Rightvec; + +// --------------------------------------------------------------------------------------------- +// Returns approximate area of a side +fix area_on_side(side *sidep) +{ + fix du,dv,width,height; + + du = sidep->uvls[1].u - sidep->uvls[0].u; + dv = sidep->uvls[1].v - sidep->uvls[0].v; + + width = fix_sqrt(fixmul(du,du) + fixmul(dv,dv)); + + du = sidep->uvls[3].u - sidep->uvls[0].u; + dv = sidep->uvls[3].v - sidep->uvls[0].v; + + height = fix_sqrt(fixmul(du,du) + fixmul(dv,dv)); + + return fixmul(width, height); +} + +// ------------------------------------------------------------------------------------------- +// DEBUG function -- callable from debugger. +// Returns approximate area of all sides which get mapped (ie, are not a connection). +// I wrote this because I was curious how much memory would be required to texture map all +// sides individually with custom artwork. For demo1.min on 2/18/94, it would be about 5 meg. +int area_on_all_sides(void) +{ + int i,s; + int total_area = 0; + + for (i=0; i<=Highest_segment_index; i++) { + segment *segp = &Segments[i]; + + for (s=0; schildren[s])) + total_area += f2i(area_on_side(&segp->sides[s])); + } + + return total_area; +} + +fix average_connectivity(void) +{ + int i,s; + int total_sides = 0, total_mapped_sides = 0; + + for (i=0; i<=Highest_segment_index; i++) { + segment *segp = &Segments[i]; + + for (s=0; schildren[s])) + total_mapped_sides++; + total_sides++; + } + } + + return 6 * fixdiv(total_mapped_sides, total_sides); +} + +#define MAX_LIGHT_SEGS 16 + +// --------------------------------------------------------------------------------------------- +// Scan all polys in all segments, return average light value for vnum. +// segs = output array for segments containing vertex, terminated by -1. +fix get_average_light_at_vertex(int vnum, short *segs) +{ + int segnum, relvnum, sidenum; + fix total_light; + int num_occurrences; +// #ifndef NDEBUG //Removed this ifdef because the version of Assert that I used to get it to compile doesn't work without this symbol. -KRB + short *original_segs; + + original_segs = segs; +// #endif + + + num_occurrences = 0; + total_light = 0; + + for (segnum=0; segnum<=Highest_segment_index; segnum++) { + segment *segp = &Segments[segnum]; + short *vp = segp->verts; + + for (relvnum=0; relvnumchildren[sidenum])) { + side *sidep = &segp->sides[sidenum]; + sbyte *vp = Side_to_verts[sidenum]; + int v; + + for (v=0; v<4; v++) + if (*vp++ == relvnum) { + total_light += sidep->uvls[v].l; + num_occurrences++; + } + } // end if + } // end sidenum + } + } // end segnum + + *segs = -1; + + if (num_occurrences) + return total_light/num_occurrences; + else + return 0; + +} + +void set_average_light_at_vertex(int vnum) +{ + int relvnum, sidenum; + short Segment_indices[MAX_LIGHT_SEGS]; + int segind; + + fix average_light; + + average_light = get_average_light_at_vertex(vnum, Segment_indices); + + if (!average_light) + return; + + segind = 0; + while (Segment_indices[segind] != -1) { + int segnum = Segment_indices[segind++]; + + segment *segp = &Segments[segnum]; + + for (relvnum=0; relvnumverts[relvnum] == vnum) + break; + + if (relvnum < MAX_VERTICES_PER_SEGMENT) { + for (sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { + if (!IS_CHILD(segp->children[sidenum])) { + side *sidep = &segp->sides[sidenum]; + sbyte *vp = Side_to_verts[sidenum]; + int v; + + for (v=0; v<4; v++) + if (*vp++ == relvnum) + sidep->uvls[v].l = average_light; + } // end if + } // end sidenum + } // end if + } // end while + + Update_flags |= UF_WORLD_CHANGED; +} + +void set_average_light_on_side(segment *segp, int sidenum) +{ + int v; + + if (!IS_CHILD(segp->children[sidenum])) + for (v=0; v<4; v++) { +// mprintf((0,"Vertex %i\n", segp->verts[Side_to_verts[side][v]])); + set_average_light_at_vertex(segp->verts[Side_to_verts[sidenum][v]]); + } + +} + +int set_average_light_on_curside(void) +{ + set_average_light_on_side(Cursegp, Curside); + return 0; +} + +// ----------------------------------------------------------------------------------------- +void set_average_light_on_all_fast(void) +{ + int s,v,relvnum; + fix al; + int alc; + int seglist[MAX_LIGHT_SEGS]; + int *segptr; + + set_vertex_counts(); + + // Set total light value for all vertices in array average_light. + for (v=0; v<=Highest_vertex_index; v++) { + al = 0; + alc = 0; + + if (Vertex_active[v]) { + segptr = seglist; + + for (s=0; s<=Highest_segment_index; s++) { + segment *segp = &Segments[s]; + for (relvnum=0; relvnumverts[relvnum] == v) + break; + + if (relvnum != MAX_VERTICES_PER_SEGMENT) { + int si; + + *segptr++ = s; // Note this segment in list, so we can process it below. + Assert(segptr - seglist < MAX_LIGHT_SEGS); + + for (si=0; sichildren[si])) { + side *sidep = &segp->sides[si]; + sbyte *vp = Side_to_verts[si]; + int vv; + + for (vv=0; vv<4; vv++) + if (*vp++ == relvnum) { + al += sidep->uvls[vv].l; + alc++; + } + } // if (segp->children[si == -1) { + } // for (si=0... + } // if (relvnum != ... + } // for (s=0; ... + + *segptr = -1; + + // Now, divide average_light by number of number of occurrences for each vertex + if (alc) + al /= alc; + else + al = 0; + + segptr = seglist; + while (*segptr != -1) { + int segnum = *segptr++; + segment *segp = &Segments[segnum]; + int sidenum; + + for (relvnum=0; relvnumverts[relvnum] == v) + break; + + Assert(relvnum < MAX_VERTICES_PER_SEGMENT); // IMPOSSIBLE! This segment is in seglist, but vertex v does not occur! + for (sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++) { + int wid_result; + wid_result = WALL_IS_DOORWAY(segp, sidenum); + if ((wid_result != WID_FLY_FLAG) && (wid_result != WID_NO_WALL)) { + side *sidep = &segp->sides[sidenum]; + sbyte *vp = Side_to_verts[sidenum]; + int v; + + for (v=0; v<4; v++) + if (*vp++ == relvnum) + sidep->uvls[v].l = al; + } // end if + } // end sidenum + } // end while + + } // if (Vertex_active[v]... + + } // for (v=0... + +} + +extern int Doing_lighting_hack_flag; // If set, don't mprintf warning messages in gameseg.c/find_point_seg +int set_average_light_on_all(void) +{ +// set_average_light_on_all_fast(); + + Doing_lighting_hack_flag = 1; + cast_all_light_in_mine(0); + Doing_lighting_hack_flag = 0; + Update_flags |= UF_WORLD_CHANGED; + +// int seg, side; + +// for (seg=0; seg<=Highest_segment_index; seg++) +// for (side=0; sideu; + v0.y = 0; + v0.z = uv0->v; + + v1.x = uv1->u; + v1.y = 0; + v1.z = uv1->v; + + return vm_vec_dist(&v0,&v1); +} + +// --------------------------------------------------------------------------------------------- +// Given a polygon, compress the uv coordinates so that they are as close to 0 as possible. +// Do this by adding a constant u and v to each uv pair. +void compress_uv_coordinates(side *sidep) +{ + int v; + fix uc, vc; + + uc = 0; + vc = 0; + + for (v=0; v<4; v++) { + uc += sidep->uvls[v].u; + vc += sidep->uvls[v].v; + } + + uc /= 4; + vc /= 4; + uc = uc & 0xffff0000; + vc = vc & 0xffff0000; + + for (v=0; v<4; v++) { + sidep->uvls[v].u -= uc; + sidep->uvls[v].v -= vc; + } + +} + +// --------------------------------------------------------------------------------------------- +void compress_uv_coordinates_on_side(side *sidep) +{ + compress_uv_coordinates(sidep); +} + +// --------------------------------------------------------------------------------------------- +void validate_uv_coordinates_on_side(segment *segp, int sidenum) +{ +// int v; +// fix uv_dist,threed_dist; +// vms_vector tvec; +// fix dist_ratios[MAX_VERTICES_PER_POLY]; + side *sidep = &segp->sides[sidenum]; +// sbyte *vp = Side_to_verts[sidenum]; + +// This next hunk doesn't seem to affect anything. @mk, 02/13/94 +// for (v=1; v<4; v++) { +// uv_dist = compute_uv_dist(&sidep->uvls[v],&sidep->uvls[0]); +// threed_dist = vm_vec_mag(vm_vec_sub(&tvec,&Vertices[segp->verts[vp[v]],&Vertices[vp[0]])); +// dist_ratios[v-1] = fixdiv(uv_dist,threed_dist); +// } + + compress_uv_coordinates_on_side(sidep); +} + +void compress_uv_coordinates_in_segment(segment *segp) +{ + int side; + + for (side=0; sidesides[side]); +} + +void compress_uv_coordinates_all(void) +{ + int seg; + + for (seg=0; seg<=Highest_segment_index; seg++) + if (Segments[seg].segnum != -1) + compress_uv_coordinates_in_segment(&Segments[seg]); +} + +void check_lighting_side(segment *sp, int sidenum) +{ + int v; + side *sidep = &sp->sides[sidenum]; + + for (v=0; v<4; v++) + if ((sidep->uvls[v].l > F1_0*16) || (sidep->uvls[v].l < 0)) + Int3(); //mprintf(0,"Bogus lighting value in segment %i, side %i, vert %i = %x\n",sp-Segments, side, v, sidep->uvls[v].l); +} + +void check_lighting_segment(segment *segp) +{ + int side; + + for (side=0; sidesides[sidenum]; + + for (v=0; v<4; v++) + sidep->uvls[v].l = DEFAULT_LIGHTING; +} + +void assign_default_lighting(segment *segp) +{ + int sidenum; + + for (sidenum=0; sidenumsides[sidenum]; + + for (v=0; v<4; v++) + sidep->uvls[v] = uvls[v]; + +} + +#ifdef __WATCOMC__ +fix zhypot(fix a,fix b); +#pragma aux zhypot parm [eax] [ebx] value [eax] modify [eax ebx ecx edx] = \ + "imul eax" \ + "xchg eax,ebx" \ + "mov ecx,edx" \ + "imul eax" \ + "add eax,ebx" \ + "adc edx,ecx" \ + "call quad_sqrt"; +#else +fix zhypot(fix a,fix b) { + double x = (double)a / 65536; + double y = (double)b / 65536; + return (long)(sqrt(x * x + y * y) * 65536); +} +#endif + +// --------------------------------------------------------------------------------------------- +// Assign lighting value to side, a function of the normal vector. +void assign_light_to_side(segment *sp, int sidenum) +{ + int v; + side *sidep = &sp->sides[sidenum]; + + for (v=0; v<4; v++) + sidep->uvls[v].l = DEFAULT_LIGHTING; +} + +fix Stretch_scale_x = F1_0; +fix Stretch_scale_y = F1_0; + +// --------------------------------------------------------------------------------------------- +// Given u,v coordinates at two vertices, assign u,v coordinates to other two vertices on a side. +// (Actually, assign them to the coordinates in the faces.) +// va, vb = face-relative vertex indices corresponding to uva, uvb. Ie, they are always in 0..3 and should be looked up in +// Side_to_verts[side] to get the segment relative index. +void assign_uvs_to_side(segment *segp, int sidenum, uvl *uva, uvl *uvb, int va, int vb) +{ + int vlo,vhi,v0,v1,v2,v3; + vms_vector fvec,rvec,tvec; + vms_matrix rotmat; + uvl uvls[4],ruvmag,fuvmag,uvlo,uvhi; + fix fmag,mag01; + sbyte *vp; + + Assert( (va<4) && (vb<4) ); + Assert((abs(va - vb) == 1) || (abs(va - vb) == 3)); // make sure the verticies specify an edge + + vp = (sbyte *)&Side_to_verts[sidenum]; + + // We want vlo precedes vhi, ie vlo < vhi, or vlo = 3, vhi = 0 + if (va == ((vb + 1) % 4)) { // va = vb + 1 + vlo = vb; + vhi = va; + uvlo = *uvb; + uvhi = *uva; + } else { + vlo = va; + vhi = vb; + uvlo = *uva; + uvhi = *uvb; + } + + Assert(((vlo+1) % 4) == vhi); // If we are on an edge, then uvhi is one more than uvlo (mod 4) + uvls[vlo] = uvlo; + uvls[vhi] = uvhi; + + // Now we have vlo precedes vhi, compute vertices ((vhi+1) % 4) and ((vhi+2) % 4) + + // Assign u,v scale to a unit length right vector. + fmag = zhypot(uvhi.v - uvlo.v,uvhi.u - uvlo.u); + if (fmag < 64) { // this is a fix, so 64 = 1/1024 + mprintf((0,"Warning: fmag = %7.3f, using approximate u,v values\n",f2fl(fmag))); + ruvmag.u = F1_0*256; + ruvmag.v = F1_0*256; + fuvmag.u = F1_0*256; + fuvmag.v = F1_0*256; + } else { + ruvmag.u = uvhi.v - uvlo.v; + ruvmag.v = uvlo.u - uvhi.u; + + fuvmag.u = uvhi.u - uvlo.u; + fuvmag.v = uvhi.v - uvlo.v; + } + + v0 = segp->verts[vp[vlo]]; + v1 = segp->verts[vp[vhi]]; + v2 = segp->verts[vp[(vhi+1)%4]]; + v3 = segp->verts[vp[(vhi+2)%4]]; + + // Compute right vector by computing orientation matrix from: + // forward vector = vlo:vhi + // right vector = vlo:(vhi+2) % 4 + vm_vec_sub(&fvec,&Vertices[v1],&Vertices[v0]); + vm_vec_sub(&rvec,&Vertices[v3],&Vertices[v0]); + + if (((fvec.x == 0) && (fvec.y == 0) && (fvec.z == 0)) || ((rvec.x == 0) && (rvec.y == 0) && (rvec.z == 0))) { + mprintf((1, "Trapped null vector in assign_uvs_to_side, using identity matrix.\n")); + rotmat = vmd_identity_matrix; + } else + vm_vector_2_matrix(&rotmat,&fvec,0,&rvec); + + rvec = rotmat.rvec; vm_vec_negate(&rvec); + fvec = rotmat.fvec; + + // mprintf((0, "va = %i, vb = %i\n", va, vb)); + mag01 = vm_vec_dist(&Vertices[v1],&Vertices[v0]); + if ((va == 0) || (va == 2)) + mag01 = fixmul(mag01, Stretch_scale_x); + else + mag01 = fixmul(mag01, Stretch_scale_y); + + if (mag01 < F1_0/1024 ) + editor_status("U, V bogosity in segment #%i, probably on side #%i. CLEAN UP YOUR MESS!", segp-Segments, sidenum); + else { + vm_vec_sub(&tvec,&Vertices[v2],&Vertices[v1]); + uvls[(vhi+1)%4].u = uvhi.u + + fixdiv(fixmul(ruvmag.u,vm_vec_dotprod(&rvec,&tvec)),mag01) + + fixdiv(fixmul(fuvmag.u,vm_vec_dotprod(&fvec,&tvec)),mag01); + + uvls[(vhi+1)%4].v = uvhi.v + + fixdiv(fixmul(ruvmag.v,vm_vec_dotprod(&rvec,&tvec)),mag01) + + fixdiv(fixmul(fuvmag.v,vm_vec_dotprod(&fvec,&tvec)),mag01); + + + vm_vec_sub(&tvec,&Vertices[v3],&Vertices[v0]); + uvls[(vhi+2)%4].u = uvlo.u + + fixdiv(fixmul(ruvmag.u,vm_vec_dotprod(&rvec,&tvec)),mag01) + + fixdiv(fixmul(fuvmag.u,vm_vec_dotprod(&fvec,&tvec)),mag01); + + uvls[(vhi+2)%4].v = uvlo.v + + fixdiv(fixmul(ruvmag.v,vm_vec_dotprod(&rvec,&tvec)),mag01) + + fixdiv(fixmul(fuvmag.v,vm_vec_dotprod(&fvec,&tvec)),mag01); + + uvls[(vhi+1)%4].l = uvhi.l; + uvls[(vhi+2)%4].l = uvlo.l; + + copy_uvs_from_side_to_faces(segp, sidenum, uvls); + } +} + + +int Vmag = VMAG; + +// ----------------------------------------------------------------------------------------------------------- +// Assign default uvs to side. +// This means: +// v0 = 0,0 +// v1 = k,0 where k is 3d size dependent +// v2, v3 assigned by assign_uvs_to_side +void assign_default_uvs_to_side(segment *segp,int side) +{ + uvl uv0,uv1; + sbyte *vp; + + uv0.u = 0; + uv0.v = 0; + + vp = Side_to_verts[side]; + + uv1.u = 0; + uv1.v = Num_tilings * fixmul(Vmag, vm_vec_dist(&Vertices[segp->verts[vp[1]]],&Vertices[segp->verts[vp[0]]])); + + assign_uvs_to_side(segp, side, &uv0, &uv1, 0, 1); +} + +// ----------------------------------------------------------------------------------------------------------- +// Assign default uvs to side. +// This means: +// v0 = 0,0 +// v1 = k,0 where k is 3d size dependent +// v2, v3 assigned by assign_uvs_to_side +void stretch_uvs_from_curedge(segment *segp, int side) +{ + uvl uv0,uv1; + int v0, v1; + + v0 = Curedge; + v1 = (v0 + 1) % 4; + + uv0.u = segp->sides[side].uvls[v0].u; + uv0.v = segp->sides[side].uvls[v0].v; + + uv1.u = segp->sides[side].uvls[v1].u; + uv1.v = segp->sides[side].uvls[v1].v; + + assign_uvs_to_side(segp, side, &uv0, &uv1, v0, v1); +} + +// -------------------------------------------------------------------------------------------------------------- +// Assign default uvs to a segment. +void assign_default_uvs_to_segment(segment *segp) +{ + int s; + + for (s=0; ssides[base_common_side].num_faces; f++) { +// -- mk021394 -- face *fp = &base_seg->sides[base_common_side].faces[f]; +// -- mk021394 -- for (p=0; pnum_polys; p++) { +// -- mk021394 -- poly *pp = &fp->polys[p]; +// -- mk021394 -- for (v=0; vnum_vertices; v++) +// -- mk021394 -- if (pp->verts[v] == v1) { +// -- mk021394 -- *ff = f; +// -- mk021394 -- *vv = v; +// -- mk021394 -- *pi = p; +// -- mk021394 -- return; +// -- mk021394 -- } +// -- mk021394 -- } +// -- mk021394 -- } +// -- mk021394 -- +// -- mk021394 -- Assert(0); // Error -- Couldn't find face:vertex which matched vertex v1 on base_seg:base_common_side +// -- mk021394 -- } + +// -- mk021394 -- // -------------------------------------------------------------------------------------------------------------- +// -- mk021394 -- // Find the vertex index in base_seg:base_common_side which is segment relative vertex v1 +// -- mk021394 -- // This very specific routine is subsidiary to med_assign_uvs_to_side. +// -- mk021394 -- void get_side_vert(segment *base_seg,int base_common_side,int v1,int *vv) +// -- mk021394 -- { +// -- mk021394 -- int p,f,v; +// -- mk021394 -- +// -- mk021394 -- Assert((base_seg->sides[base_common_side].tri_edge == 0) || (base_seg->sides[base_common_side].tri_edge == 1)); +// -- mk021394 -- Assert(base_seg->sides[base_common_side].num_faces <= 2); +// -- mk021394 -- +// -- mk021394 -- for (f=0; fsides[base_common_side].num_faces; f++) { +// -- mk021394 -- face *fp = &base_seg->sides[base_common_side].faces[f]; +// -- mk021394 -- for (p=0; pnum_polys; p++) { +// -- mk021394 -- poly *pp = &fp->polys[p]; +// -- mk021394 -- for (v=0; vnum_vertices; v++) +// -- mk021394 -- if (pp->verts[v] == v1) { +// -- mk021394 -- if (pp->num_vertices == 4) { +// -- mk021394 -- *vv = v; +// -- mk021394 -- return; +// -- mk021394 -- } +// -- mk021394 -- +// -- mk021394 -- if (base_seg->sides[base_common_side].tri_edge == 0) { // triangulated 012, 023, so if f==0, *vv = v, if f==1, *vv = v if v=0, else v+1 +// -- mk021394 -- if ((f == 1) && (v > 0)) +// -- mk021394 -- v++; +// -- mk021394 -- *vv = v; +// -- mk021394 -- return; +// -- mk021394 -- } else { // triangulated 013, 123 +// -- mk021394 -- if (f == 0) { +// -- mk021394 -- if (v == 2) +// -- mk021394 -- v++; +// -- mk021394 -- } else +// -- mk021394 -- v++; +// -- mk021394 -- *vv = v; +// -- mk021394 -- return; +// -- mk021394 -- } +// -- mk021394 -- } +// -- mk021394 -- } +// -- mk021394 -- } +// -- mk021394 -- +// -- mk021394 -- Assert(0); // Error -- Couldn't find face:vertex which matched vertex v1 on base_seg:base_common_side +// -- mk021394 -- } + +//--rotate_uvs-- // -------------------------------------------------------------------------------------------------------------- +//--rotate_uvs-- // Rotate uvl coordinates uva, uvb about their center point by heading +//--rotate_uvs-- void rotate_uvs(uvl *uva, uvl *uvb, vms_vector *rvec) +//--rotate_uvs-- { +//--rotate_uvs-- uvl uvc, uva1, uvb1; +//--rotate_uvs-- +//--rotate_uvs-- uvc.u = (uva->u + uvb->u)/2; +//--rotate_uvs-- uvc.v = (uva->v + uvb->v)/2; +//--rotate_uvs-- +//--rotate_uvs-- uva1.u = fixmul(uva->u - uvc.u, rvec->x) - fixmul(uva->v - uvc.v, rvec->z); +//--rotate_uvs-- uva1.v = fixmul(uva->u - uvc.u, rvec->z) + fixmul(uva->v - uvc.v, rvec->x); +//--rotate_uvs-- +//--rotate_uvs-- uva->u = uva1.u + uvc.u; +//--rotate_uvs-- uva->v = uva1.v + uvc.v; +//--rotate_uvs-- +//--rotate_uvs-- uvb1.u = fixmul(uvb->u - uvc.u, rvec->x) - fixmul(uvb->v - uvc.v, rvec->z); +//--rotate_uvs-- uvb1.v = fixmul(uvb->u - uvc.u, rvec->z) + fixmul(uvb->v - uvc.v, rvec->x); +//--rotate_uvs-- +//--rotate_uvs-- uvb->u = uvb1.u + uvc.u; +//--rotate_uvs-- uvb->v = uvb1.v + uvc.v; +//--rotate_uvs-- } + + +// -------------------------------------------------------------------------------------------------------------- +void med_assign_uvs_to_side(segment *con_seg, int con_common_side, segment *base_seg, int base_common_side, int abs_id1, int abs_id2) +{ + uvl uv1,uv2; + int v,bv1,bv2, vv1, vv2; + int cv1=0, cv2=0; + + bv1 = -1; bv2 = -1; + + // Find which vertices in segment match abs_id1, abs_id2 + for (v=0; vverts[v] == abs_id1) + bv1 = v; + if (base_seg->verts[v] == abs_id2) + bv2 = v; + if (con_seg->verts[v] == abs_id1) + cv1 = v; + if (con_seg->verts[v] == abs_id2) + cv2 = v; + } + + // Now, bv1, bv2 are segment relative vertices in base segment which are the same as absolute vertices abs_id1, abs_id2 + // cv1, cv2 are segment relative vertices in conn segment which are the same as absolute vertices abs_id1, abs_id2 + + Assert((bv1 != -1) && (bv2 != -1) && (cv1 != -1) && (cv2 != -1)); + Assert((uv1.u != uv2.u) || (uv1.v != uv2.v)); + + // Now, scan 4 vertices in base side and 4 vertices in connected side. + // Set uv1, uv2 to uv coordinates from base side which correspond to vertices bv1, bv2. + // Set vv1, vv2 to relative vertex ids (in 0..3) in connecting side which correspond to cv1, cv2 + vv1 = -1; vv2 = -1; + for (v=0; v<4; v++) { + if (bv1 == Side_to_verts[base_common_side][v]) + uv1 = base_seg->sides[base_common_side].uvls[v]; + + if (bv2 == Side_to_verts[base_common_side][v]) + uv2 = base_seg->sides[base_common_side].uvls[v]; + + if (cv1 == Side_to_verts[con_common_side][v]) + vv1 = v; + + if (cv2 == Side_to_verts[con_common_side][v]) + vv2 = v; + } + + Assert( (vv1 != -1) && (vv2 != -1) ); + assign_uvs_to_side(con_seg, con_common_side, &uv1, &uv2, vv1, vv2); +} + + +// ----------------------------------------------------------------------------- +// Given a base and a connecting segment, a side on each of those segments and two global vertex ids, +// determine which side in each of the segments shares those two vertices. +// This is used to propagate a texture map id to a connecting segment in an expected and desired way. +// Since we can attach any side of a segment to any side of another segment, and do so in each case in +// four different rotations (for a total of 6*6*4 = 144 ways), not having this nifty function will cause +// great confusion. +void get_side_ids(segment *base_seg, segment *con_seg, int base_side, int con_side, int abs_id1, int abs_id2, int *base_common_side, int *con_common_side) +{ + char *base_vp,*con_vp; + int v0,side; + + *base_common_side = -1; + + // Find side in base segment which contains the two global vertex ids. + for (side=0; sideverts[(int) base_vp[v0]] == abs_id1) && (base_seg->verts[(int) base_vp[(v0+1) % 4]] == abs_id2)) || ((base_seg->verts[(int) base_vp[v0]] == abs_id2) && (base_seg->verts[(int)base_vp[ (v0+1) % 4]] == abs_id1))) { + Assert(*base_common_side == -1); // This means two different sides shared the same edge with base_side == impossible! + *base_common_side = side; + } + } + } + + // Note: For connecting segment, process vertices in reversed order. + *con_common_side = -1; + + // Find side in connecting segment which contains the two global vertex ids. + for (side=0; sideverts[(int) con_vp[(v0 + 1) % 4]] == abs_id1) && (con_seg->verts[(int) con_vp[v0]] == abs_id2)) || ((con_seg->verts[(int) con_vp[(v0 + 1) % 4]] == abs_id2) && (con_seg->verts[(int) con_vp[v0]] == abs_id1))) { + Assert(*con_common_side == -1); // This means two different sides shared the same edge with con_side == impossible! + *con_common_side = side; + } + } + } + +// mprintf((0,"side %3i adjacent to side %3i\n",*base_common_side,*con_common_side)); + + Assert((*base_common_side != -1) && (*con_common_side != -1)); +} + +// ----------------------------------------------------------------------------- +// Propagate texture map u,v coordinates from base_seg:base_side to con_seg:con_side. +// The two vertices abs_id1 and abs_id2 are the only two vertices common to the two sides. +// If uv_only_flag is 1, then don't assign texture map ids, only update the uv coordinates +// If uv_only_flag is -1, then ONLY assign texture map ids, don't update the uv coordinates +void propagate_tmaps_to_segment_side(segment *base_seg, int base_side, segment *con_seg, int con_side, int abs_id1, int abs_id2, int uv_only_flag) +{ + int base_common_side,con_common_side; + int tmap_num; + + Assert ((uv_only_flag == -1) || (uv_only_flag == 0) || (uv_only_flag == 1)); + + // Set base_common_side = side in base_seg which contains edge abs_id1:abs_id2 + // Set con_common_side = side in con_seg which contains edge abs_id1:abs_id2 + if (base_seg != con_seg) + get_side_ids(base_seg, con_seg, base_side, con_side, abs_id1, abs_id2, &base_common_side, &con_common_side); + else { + base_common_side = base_side; + con_common_side = con_side; + } + + // Now, all faces in con_seg which are on side con_common_side get their tmap_num set to whatever tmap is assigned + // to whatever face I find which is on side base_common_side. + // First, find tmap_num for base_common_side. If it doesn't exist (ie, there is a connection there), look at the segment + // that is connected through it. + if (!IS_CHILD(con_seg->children[con_common_side])) { + if (!IS_CHILD(base_seg->children[base_common_side])) { + // There is at least one face here, so get the tmap_num from there. + tmap_num = base_seg->sides[base_common_side].tmap_num; + + // Now assign all faces in the connecting segment on side con_common_side to tmap_num. + if ((uv_only_flag == -1) || (uv_only_flag == 0)) + con_seg->sides[con_common_side].tmap_num = tmap_num; + + if (uv_only_flag != -1) + med_assign_uvs_to_side(con_seg, con_common_side, base_seg, base_common_side, abs_id1, abs_id2); + + } else { // There are no faces here, there is a connection, trace through the connection. + int cside; + + cside = find_connect_side(base_seg, &Segments[base_seg->children[base_common_side]]); + propagate_tmaps_to_segment_side(&Segments[base_seg->children[base_common_side]], cside, con_seg, con_side, abs_id1, abs_id2, uv_only_flag); + } + } + +} + +sbyte Edge_between_sides[MAX_SIDES_PER_SEGMENT][MAX_SIDES_PER_SEGMENT][2] = { +// left top right bottom back front + { {-1,-1}, { 3, 7}, {-1,-1}, { 2, 6}, { 6, 7}, { 2, 3} }, // left + { { 3, 7}, {-1,-1}, { 0, 4}, {-1,-1}, { 4, 7}, { 0, 3} }, // top + { {-1,-1}, { 0, 4}, {-1,-1}, { 1, 5}, { 4, 5}, { 0, 1} }, // right + { { 2, 6}, {-1,-1}, { 1, 5}, {-1,-1}, { 5, 6}, { 1, 2} }, // bottom + { { 6, 7}, { 4, 7}, { 4, 5}, { 5, 6}, {-1,-1}, {-1,-1} }, // back + { { 2, 3}, { 0, 3}, { 0, 1}, { 1, 2}, {-1,-1}, {-1,-1} }}; // front + +// ----------------------------------------------------------------------------- +// Propagate texture map u,v coordinates to base_seg:back_side from base_seg:some-other-side +// There is no easy way to figure out which side is adjacent to another side along some edge, so we do a bit of searching. +void med_propagate_tmaps_to_back_side(segment *base_seg, int back_side, int uv_only_flag) +{ + int v1=0,v2=0; + int s,ss,tmap_num,back_side_tmap; + + if (IS_CHILD(base_seg->children[back_side])) + return; // connection, so no sides here. + + // Scan all sides, look for an occupied side which is not back_side or Side_opposite[back_side] + for (s=0; sverts[v1], base_seg->verts[v2], uv_only_flag); + + // Assign an unused tmap id to the back side. + // Note that this can get undone by the caller if this was not part of a new attach, but a rotation or a scale (which + // both do attaches). + // First see if tmap on back side is anywhere else. + if (!uv_only_flag) { + back_side_tmap = base_seg->sides[back_side].tmap_num; + for (s=0; ssides[s].tmap_num == back_side_tmap) { + for (tmap_num=0; tmap_num < MAX_SIDES_PER_SEGMENT; tmap_num++) { + for (ss=0; sssides[ss].tmap_num == New_segment.sides[tmap_num].tmap_num) + goto found2; // current texture map (tmap_num) is used on current (ss) side, so try next one + // Current texture map (tmap_num) has not been used, assign to all faces on back_side. + base_seg->sides[back_side].tmap_num = New_segment.sides[tmap_num].tmap_num; + goto done1; + found2: ; + } + } + } + done1: ; + } + +} + +int fix_bogus_uvs_on_side(void) +{ + med_propagate_tmaps_to_back_side(Cursegp, Curside, 1); + return 0; +} + +void fix_bogus_uvs_on_side1(segment *sp, int sidenum, int uvonly_flag) +{ + side *sidep = &sp->sides[sidenum]; + + if ((sidep->uvls[0].u == 0) && (sidep->uvls[1].u == 0) && (sidep->uvls[2].u == 0)) { + mprintf((0,"Found bogus segment %i, side %i\n", sp-Segments, sidenum)); + med_propagate_tmaps_to_back_side(sp, sidenum, uvonly_flag); + } +} + +void fix_bogus_uvs_seg(segment *segp) +{ + int s; + + for (s=0; schildren[s])) + fix_bogus_uvs_on_side1(segp, s, 1); + } +} + +int fix_bogus_uvs_all(void) +{ + int seg; + + for (seg=0; seg<=Highest_segment_index; seg++) + if (Segments[seg].segnum != -1) + fix_bogus_uvs_seg(&Segments[seg]); + return 0; +} + +// ----------------------------------------------------------------------------- +// Propagate texture map u,v coordinates to base_seg:back_side from base_seg:some-other-side +// There is no easy way to figure out which side is adjacent to another side along some edge, so we do a bit of searching. +void med_propagate_tmaps_to_any_side(segment *base_seg, int back_side, int tmap_num, int uv_only_flag) +{ + int v1=0,v2=0; + int s; + + // Scan all sides, look for an occupied side which is not back_side or Side_opposite[back_side] + for (s=0; sverts[v1], base_seg->verts[v2], uv_only_flag); + + base_seg->sides[back_side].tmap_num = tmap_num; + +} + +// ----------------------------------------------------------------------------- +// Segment base_seg is connected through side base_side to segment con_seg on con_side. +// For all walls in con_seg, find the wall in base_seg which shares an edge. Copy tmap_num +// from that side in base_seg to the wall in con_seg. If the wall in base_seg is not present +// (ie, there is another segment connected through it), follow the connection through that +// segment to get the wall in the connected segment which shares the edge, and get tmap_num from there. +void propagate_tmaps_to_segment_sides(segment *base_seg, int base_side, segment *con_seg, int con_side, int uv_only_flag) +{ + char *base_vp,*con_vp; + short abs_id1,abs_id2; + int v; + + base_vp = Side_to_verts[base_side]; + con_vp = Side_to_verts[con_side]; + + // Do for each edge on connecting face. + for (v=0; v<4; v++) { + abs_id1 = base_seg->verts[(int) base_vp[v]]; + abs_id2 = base_seg->verts[(int) base_vp[(v+1) % 4]]; + propagate_tmaps_to_segment_side(base_seg, base_side, con_seg, con_side, abs_id1, abs_id2, uv_only_flag); + } + +} + +// ----------------------------------------------------------------------------- +// Propagate texture maps in base_seg to con_seg. +// For each wall in con_seg, find the wall in base_seg which shared an edge. Copy tmap_num from that +// wall in base_seg to the wall in con_seg. If the wall in base_seg is not present, then look at the +// segment connected through base_seg through the wall. The wall with a common edge is the new wall +// of interest. Continue searching in this way until a wall of interest is present. +void med_propagate_tmaps_to_segments(segment *base_seg,segment *con_seg, int uv_only_flag) +{ + int s; + +// mprintf((0,"Propagating segments from %i to %i\n",base_seg-Segments,con_seg-Segments)); + for (s=0; schildren[s] == con_seg-Segments) + propagate_tmaps_to_segment_sides(base_seg, s, con_seg, find_connect_side(base_seg, con_seg), uv_only_flag); + + con_seg->static_light = base_seg->static_light; + + validate_uv_coordinates(con_seg); +} + + +// ------------------------------------------------------------------------------- +// Copy texture map uvs from srcseg to destseg. +// If two segments have different face structure (eg, destseg has two faces on side 3, srcseg has only 1) +// then assign uvs according to side vertex id, not face vertex id. +void copy_uvs_seg_to_seg(segment *destseg,segment *srcseg) +{ + int s; + + for (s=0; ssides[s].tmap_num = srcseg->sides[s].tmap_num; + destseg->sides[s].tmap_num2 = srcseg->sides[s].tmap_num2; + } + + destseg->static_light = srcseg->static_light; +} + +// _________________________________________________________________________________________________________________________ +// Maximum distance between a segment containing light to a segment to receive light. +#define LIGHT_DISTANCE_THRESHOLD (F1_0*80) +fix Magical_light_constant = (F1_0*16); + +// int Seg0, Seg1; + +//int Bugseg = 27; + +typedef struct { + sbyte flag, hit_type; + vms_vector vector; +} hash_info; + +#define FVI_HASH_SIZE 8 +#define FVI_HASH_AND_MASK (FVI_HASH_SIZE - 1) + +// Note: This should be malloced. +// Also, the vector should not be 12 bytes, you should only care about some smaller portion of it. +hash_info fvi_cache[FVI_HASH_SIZE]; +int Hash_hits=0, Hash_retries=0, Hash_calcs=0; + +// ----------------------------------------------------------------------------------------- +// Set light from a light source. +// Light incident on a surface is defined by the light incident at its points. +// Light at a point = K * (V . N) / d +// where: +// K = some magical constant to make everything look good +// V = normalized vector from light source to point +// N = surface normal at point +// d = distance from light source to point +// (Note that the above equation can be simplified to K * (VV . N) / d^2 where VV = non-normalized V) +// Light intensity emitted from a light source is defined to be cast from four points. +// These four points are 1/64 of the way from the corners of the light source to the center +// of its segment. By assuming light is cast from these points, rather than from on the +// light surface itself, light will be properly cast on the light surface. Otherwise, the +// vector V would be the null vector. +// If quick_light set, then don't use find_vector_intersection +void cast_light_from_side(segment *segp, int light_side, fix light_intensity, int quick_light) +{ + vms_vector segment_center; + int segnum,sidenum,vertnum, lightnum; + + compute_segment_center(&segment_center, segp); + +//mprintf((0, "From [%i %i %7.3f]: ", segp-Segments, light_side, f2fl(light_intensity))); + + // Do for four lights, one just inside each corner of side containing light. + for (lightnum=0; lightnum<4; lightnum++) { + int light_vertex_num, i; + vms_vector vector_to_center; + vms_vector light_location; + // fix inverse_segment_magnitude; + + light_vertex_num = segp->verts[Side_to_verts[light_side][lightnum]]; + light_location = Vertices[light_vertex_num]; + + + // New way, 5/8/95: Move towards center irrespective of size of segment. + vm_vec_sub(&vector_to_center, &segment_center, &light_location); + vm_vec_normalize_quick(&vector_to_center); + vm_vec_add2(&light_location, &vector_to_center); + +// -- Old way, before 5/8/95 -- // -- This way was kind of dumb. In larger segments, you move LESS towards the center. +// -- Old way, before 5/8/95 -- // Main problem, though, is vertices don't illuminate themselves well in oblong segments because the dot product is small. +// -- Old way, before 5/8/95 -- vm_vec_sub(&vector_to_center, &segment_center, &light_location); +// -- Old way, before 5/8/95 -- inverse_segment_magnitude = fixdiv(F1_0/5, vm_vec_mag(&vector_to_center)); +// -- Old way, before 5/8/95 -- vm_vec_scale_add(&light_location, &light_location, &vector_to_center, inverse_segment_magnitude); + + for (segnum=0; segnum<=Highest_segment_index; segnum++) { + segment *rsegp = &Segments[segnum]; + vms_vector r_segment_center; + fix dist_to_rseg; + + for (i=0; isides[sidenum]; + vms_vector *side_normalp = &rsidep->normals[0]; // kinda stupid? always use vector 0. + +//mprintf((0, "[%i %i], ", rsegp-Segments, sidenum)); + for (vertnum=0; vertnum<4; vertnum++) { + fix distance_to_point, light_at_point, light_dot; + vms_vector vert_location, vector_to_light; + int abs_vertnum; + + abs_vertnum = rsegp->verts[Side_to_verts[sidenum][vertnum]]; + vert_location = Vertices[abs_vertnum]; + distance_to_point = vm_vec_dist_quick(&vert_location, &light_location); + vm_vec_sub(&vector_to_light, &light_location, &vert_location); + vm_vec_normalize(&vector_to_light); + + // Hack: In oblong segments, it's possible to get a very small dot product + // but the light source is very nearby (eg, illuminating light itself!). + light_dot = vm_vec_dot(&vector_to_light, side_normalp); + if (distance_to_point < F1_0) + if (light_dot > 0) + light_dot = (light_dot + F1_0)/2; + + if (light_dot > 0) { + light_at_point = fixdiv(fixmul(light_dot, light_dot), distance_to_point); + light_at_point = fixmul(light_at_point, Magical_light_constant); + if (light_at_point >= 0) { + fvi_info hit_data; + int hit_type; + vms_vector vert_location_1, r_vector_to_center; + fix inverse_segment_magnitude; + + vm_vec_sub(&r_vector_to_center, &r_segment_center, &vert_location); + inverse_segment_magnitude = fixdiv(F1_0/3, vm_vec_mag(&r_vector_to_center)); + vm_vec_scale_add(&vert_location_1, &vert_location, &r_vector_to_center, inverse_segment_magnitude); + vert_location = vert_location_1; + +//if ((segp-Segments == 199) && (rsegp-Segments==199)) +// Int3(); +// Seg0 = segp-Segments; +// Seg1 = rsegp-Segments; + if (!quick_light) { + int hash_value = Side_to_verts[sidenum][vertnum]; + hash_info *hashp = &fvi_cache[hash_value]; + while (1) { + if (hashp->flag) { + if ((hashp->vector.x == vector_to_light.x) && (hashp->vector.y == vector_to_light.y) && (hashp->vector.z == vector_to_light.z)) { +//mprintf((0, "{CACHE %4x} ", hash_value)); + hit_type = hashp->hit_type; + Hash_hits++; + break; + } else { + Int3(); // How is this possible? Should be no hits! + Hash_retries++; + hash_value = (hash_value+1) & FVI_HASH_AND_MASK; + hashp = &fvi_cache[hash_value]; + } + } else { +//mprintf((0, "\nH:%04x ", hash_value)); + fvi_query fq; + + Hash_calcs++; + hashp->vector = vector_to_light; + hashp->flag = 1; + + fq.p0 = &light_location; + fq.startseg = segp-Segments; + fq.p1 = &vert_location; + fq.rad = 0; + fq.thisobjnum = -1; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + hit_type = find_vector_intersection(&fq,&hit_data); + hashp->hit_type = hit_type; + break; + } + } + } else + hit_type = HIT_NONE; +//mprintf((0, "hit=%i ", hit_type)); + switch (hit_type) { + case HIT_NONE: + light_at_point = fixmul(light_at_point, light_intensity); + rsidep->uvls[vertnum].l += light_at_point; +//mprintf((0, "(%5.2f) ", f2fl(light_at_point))); + if (rsidep->uvls[vertnum].l > F1_0) + rsidep->uvls[vertnum].l = F1_0; + break; + case HIT_WALL: + break; + case HIT_OBJECT: + Int3(); // Hit object, should be ignoring objects! + break; + case HIT_BAD_P0: + Int3(); // Ugh, this thing again, what happened, what does it mean? + break; + } + } // end if (light_at_point... + } // end if (light_dot >... + } // end for (vertnum=0... + } // end if (rsegp... + } // end for (sidenum=0... + } // end if (dist_to_rseg... + + } // end for (segnum=0... + + } // end for (lightnum=0... + +//mprintf((0, "\n")); +} + + +// ------------------------------------------------------------------------------------------ +// Zero all lighting values. +void calim_zero_light_values(void) +{ + int segnum, sidenum, vertnum; + + for (segnum=0; segnum<=Highest_segment_index; segnum++) { + segment *segp = &Segments[segnum]; + for (sidenum=0; sidenumsides[sidenum]; + for (vertnum=0; vertnum<4; vertnum++) + sidep->uvls[vertnum].l = F1_0/64; // Put a tiny bit of light here. + } + Segments[segnum].static_light = F1_0/64; + } +} + + +// ------------------------------------------------------------------------------------------ +// Used in setting average light value in a segment, cast light from a side to the center +// of all segments. +void cast_light_from_side_to_center(segment *segp, int light_side, fix light_intensity, int quick_light) +{ + vms_vector segment_center; + int segnum, lightnum; + + compute_segment_center(&segment_center, segp); + + // Do for four lights, one just inside each corner of side containing light. + for (lightnum=0; lightnum<4; lightnum++) { + int light_vertex_num; + vms_vector vector_to_center; + vms_vector light_location; + + light_vertex_num = segp->verts[Side_to_verts[light_side][lightnum]]; + light_location = Vertices[light_vertex_num]; + vm_vec_sub(&vector_to_center, &segment_center, &light_location); + vm_vec_scale_add(&light_location, &light_location, &vector_to_center, F1_0/64); + + for (segnum=0; segnum<=Highest_segment_index; segnum++) { + segment *rsegp = &Segments[segnum]; + vms_vector r_segment_center; + fix dist_to_rseg; +//if ((segp == &Segments[Bugseg]) && (rsegp == &Segments[Bugseg])) +// Int3(); + compute_segment_center(&r_segment_center, rsegp); + dist_to_rseg = vm_vec_dist_quick(&r_segment_center, &segment_center); + + if (dist_to_rseg <= LIGHT_DISTANCE_THRESHOLD) { + fix light_at_point; + if (dist_to_rseg > F1_0) + light_at_point = fixdiv(Magical_light_constant, dist_to_rseg); + else + light_at_point = Magical_light_constant; + + if (light_at_point >= 0) { + int hit_type; + + if (!quick_light) { + fvi_query fq; + fvi_info hit_data; + + fq.p0 = &light_location; + fq.startseg = segp-Segments; + fq.p1 = &r_segment_center; + fq.rad = 0; + fq.thisobjnum = -1; + fq.ignore_obj_list = NULL; + fq.flags = 0; + + hit_type = find_vector_intersection(&fq,&hit_data); + } + else + hit_type = HIT_NONE; + + switch (hit_type) { + case HIT_NONE: + light_at_point = fixmul(light_at_point, light_intensity); + if (light_at_point >= F1_0) + light_at_point = F1_0-1; + rsegp->static_light += light_at_point; + if (segp->static_light < 0) // if it went negative, saturate + segp->static_light = 0; + break; + case HIT_WALL: + break; + case HIT_OBJECT: + Int3(); // Hit object, should be ignoring objects! + break; + case HIT_BAD_P0: + Int3(); // Ugh, this thing again, what happened, what does it mean? + break; + } + } // end if (light_at_point... + } // end if (dist_to_rseg... + + } // end for (segnum=0... + + } // end for (lightnum=0... + +} + +// ------------------------------------------------------------------------------------------ +// Process all lights. +void calim_process_all_lights(int quick_light) +{ + int segnum, sidenum; + + for (segnum=0; segnum<=Highest_segment_index; segnum++) { + segment *segp = &Segments[segnum]; + mprintf((0, ".")); + for (sidenum=0; sidenumchildren[sidenum])) { + if (WALL_IS_DOORWAY(segp, sidenum) != WID_NO_WALL) { + side *sidep = &segp->sides[sidenum]; + fix light_intensity; + + light_intensity = TmapInfo[sidep->tmap_num].lighting + TmapInfo[sidep->tmap_num2 & 0x3fff].lighting; + +// if (segp->sides[sidenum].wall_num != -1) { +// int wall_num, bitmap_num, effect_num; +// wall_num = segp->sides[sidenum].wall_num; +// effect_num = Walls[wall_num].type; +// bitmap_num = effects_bm_num[effect_num]; +// +// light_intensity += TmapInfo[bitmap_num].lighting; +// } + + if (light_intensity) { + light_intensity /= 4; // casting light from four spots, so divide by 4. + cast_light_from_side(segp, sidenum, light_intensity, quick_light); + cast_light_from_side_to_center(segp, sidenum, light_intensity, quick_light); + } + } + } + } +} + +// ------------------------------------------------------------------------------------------ +// Apply static light in mine. +// First, zero all light values. +// Then, for all light sources, cast their light. +void cast_all_light_in_mine(int quick_flag) +{ + + validate_segment_all(); + + calim_zero_light_values(); + + calim_process_all_lights(quick_flag); + +} + +// int Fvit_num = 1000; +// +// fix find_vector_intersection_test(void) +// { +// int i; +// fvi_info hit_data; +// int p0_seg, p1_seg, this_objnum, ignore_obj, check_obj_flag; +// fix rad; +// int start_time = timer_get_milliseconds();; +// vms_vector p0,p1; +// +// ignore_obj = 1; +// check_obj_flag = 0; +// this_objnum = -1; +// rad = F1_0/4; +// +// for (i=0; ix - v2->x) < Normal_nearness) + if (abs(v1->y - v2->y) < Normal_nearness) + if (abs(v1->z - v2->z) < Normal_nearness) + return 1; + return 0; +} + +int Total_normals=0; +int Diff_normals=0; + +void print_normals(void) +{ + int i,j,s,n,nn; + // vms_vector *normal; + int num_normals=0; + + Total_normals = 0; + Diff_normals = 0; + + for (i=0; i<=Highest_segment_index; i++) + for (s=0; s<6; s++) { + if (Segments[i].sides[s].type == SIDE_IS_QUAD) + nn=1; + else + nn=2; + for (n=0; n +#include +#include +#include + +#ifdef RCS +static char rcsid[] = "$Id: texpage.c,v 1.1 2004-12-19 13:54:27 btb Exp $"; +#endif + +#include "inferno.h" +#include "gameseg.h" +#include "screens.h" // For GAME_SCREEN????? +#include "editor.h" // For TMAP_CURBOX?????? +#include "gr.h" // For canves, font stuff +#include "ui.h" // For UI_GADGET stuff +#include "textures.h" // For NumTextures +#include "error.h" +#include "key.h" +#include "mono.h" +#include "gamesave.h" + +#include "texpage.h" +#include "piggy.h" + +#define TMAPS_PER_PAGE 12 + +static UI_GADGET_USERBOX * TmapBox[TMAPS_PER_PAGE]; +static UI_GADGET_USERBOX * TmapCurrent; + +int CurrentTmap = 0; // Used globally +int CurrentTexture = 0; // Used globally + +int TextureLights; +int TextureEffects; +int TextureMetals; + +static int TexturePage = 0; + +static grs_canvas * TmapnameCanvas; +static char tmap_filename[13]; + +static void texpage_print_name( char name[13] ) +{ + int w,h,aw; + int i; + + for (i=strlen(name);i<12;i++) + name[i]=' '; + name[i]=0; + + gr_set_current_canvas( TmapnameCanvas ); + gr_get_string_size( name, &w, &h, &aw ); + gr_string( 0, 0, name ); +} + +static void texpage_display_name( char *format, ... ) +{ + va_list ap; + + va_start(ap, format); + vsprintf(tmap_filename, format, ap); + va_end(ap); + + texpage_print_name(tmap_filename); +} + +//Redraw the list of textures, based on TexturePage +void texpage_redraw() +{ + int i; + + for (i=0; icanvas); + if (i+TexturePage*TMAPS_PER_PAGE < Num_tmaps ) { + PIGGY_PAGE_IN( Textures[TmapList[i+TexturePage*TMAPS_PER_PAGE]]); + gr_ubitmap(0,0, &GameBitmaps[Textures[TmapList[i+TexturePage*TMAPS_PER_PAGE]].index]); + } else + gr_clear_canvas( CGREY ); + } +} + +//shows the current texture, updating the window and printing the name, base +//on CurrentTexture +void texpage_show_current() +{ + gr_set_current_canvas(TmapCurrent->canvas); + PIGGY_PAGE_IN(Textures[CurrentTexture]); + gr_ubitmap(0,0, &GameBitmaps[Textures[CurrentTexture].index]); + texpage_display_name( TmapInfo[CurrentTexture].filename ); +} + +int texpage_goto_first() +{ + TexturePage=0; + texpage_redraw(); + return 1; +} + +int texpage_goto_metals() +{ + + TexturePage=TextureMetals/TMAPS_PER_PAGE; + texpage_redraw(); + return 1; +} + + +// Goto lights (paste ons) +int texpage_goto_lights() +{ + TexturePage=TextureLights/TMAPS_PER_PAGE; + texpage_redraw(); + return 1; +} + +int texpage_goto_effects() +{ + TexturePage=TextureEffects/TMAPS_PER_PAGE; + texpage_redraw(); + return 1; +} + +static int texpage_goto_prev() +{ + if (TexturePage > 0) { + TexturePage--; + texpage_redraw(); + } + return 1; +} + +static int texpage_goto_next() +{ + if ((TexturePage+1)*TMAPS_PER_PAGE < Num_tmaps ) { + TexturePage++; + texpage_redraw(); + } + return 1; +} + +//NOTE: this code takes the texture map number, not this index in the +//list of available textures. There are different if there are holes in +//the list +int texpage_grab_current(int n) +{ + int i; + + if ( (n<0) || ( n>= Num_tmaps) ) return 0; + + CurrentTexture = n; + + for (i=0;i>", texpage_goto_next ); + + ui_add_gadget_button( win, TMAPCURBOX_X + 00, TMAPCURBOX_Y - 48, 15, 20, "T", texpage_goto_first ); + ui_add_gadget_button( win, TMAPCURBOX_X + 17, TMAPCURBOX_Y - 48, 15, 20, "M", texpage_goto_metals ); + ui_add_gadget_button( win, TMAPCURBOX_X + 34, TMAPCURBOX_Y - 48, 15, 20, "L", texpage_goto_lights ); + ui_add_gadget_button( win, TMAPCURBOX_X + 51, TMAPCURBOX_Y - 48, 15, 20, "E", texpage_goto_effects ); + + + for (i=0;isc_canvas, TMAPCURBOX_X , TMAPCURBOX_Y + TMAPBOX_H + 10, 100, 20); + gr_set_current_canvas( TmapnameCanvas ); + gr_set_curfont( ui_small_font ); + gr_set_fontcolor( CBLACK, CWHITE ); + + texpage_redraw(); + +// Don't reset the current tmap every time we go back to the editor. +// CurrentTmap = TexturePage*TMAPS_PER_PAGE; +// CurrentTexture = TmapList[CurrentTmap]; + texpage_show_current(); + +} + +void texpage_close() +{ + gr_free_sub_canvas(TmapnameCanvas); +} + + +// DO TEXTURE STUFF + +#define MAX_REPLACEMENTS 32 + +typedef struct replacement { + int new, old; +} replacement; + +replacement Replacement_list[MAX_REPLACEMENTS]; +int Num_replacements=0; + +void texpage_do() +{ + int i; + + for (i=0; ib1_clicked && (i+TexturePage*TMAPS_PER_PAGE < Num_tmaps)) { + CurrentTmap = i+TexturePage*TMAPS_PER_PAGE; + CurrentTexture = TmapList[CurrentTmap]; + texpage_show_current(); + + if (keyd_pressed[KEY_LSHIFT]) { + mprintf((0, "Will replace CurrentTexture (%i) with...(select by pressing Ctrl)\n", CurrentTexture)); + Replacement_list[Num_replacements].old = CurrentTexture; + } + + if (keyd_pressed[KEY_LCTRL]) { + mprintf((0, "...Replacement texture for %i is %i\n", Replacement_list[Num_replacements].old, CurrentTexture)); + Replacement_list[Num_replacements].new = CurrentTexture; + Num_replacements++; + } + } + } +} + +void init_replacements(void) +{ + Num_replacements = 0; +} + +void do_replacements(void) +{ + int replnum, segnum, sidenum; + + med_compress_mine(); + + for (replnum=0; replnum= 0); + Assert(new_tmap_num >= 0); + + for (segnum=0; segnum <= Highest_segment_index; segnum++) { + segment *segp=&Segments[segnum]; + for (sidenum=0; sidenumsides[sidenum]; + if (sidep->tmap_num == old_tmap_num) { + sidep->tmap_num = new_tmap_num; + // mprintf((0, "Replacing tmap_num on segment:side = %i:%i\n", segnum, sidenum)); + } + if ((sidep->tmap_num2 != 0) && ((sidep->tmap_num2 & 0x3fff) == old_tmap_num)) { + if (new_tmap_num == 0) { + Int3(); // Error. You have tried to replace a tmap_num2 with + // the 0th tmap_num2 which is ILLEGAL! + } else { + sidep->tmap_num2 = new_tmap_num | (sidep->tmap_num2 & 0xc000); + // mprintf((0, "Replacing tmap_num2 on segment:side = %i:%i\n", segnum, sidenum)); + } + } + } + } + } + +} + +void do_replacements_all(void) +{ + int i; + + for (i=0; i +#include +#include +#include +#include + +#include "inferno.h" +#include "segment.h" +#include "seguvs.h" +#include "editor.h" + +#include "fix.h" +#include "mono.h" +#include "error.h" +#include "kdefs.h" + +void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum); +void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter); + +// ----------------------------------------------------------- +int TexFlipX() +{ + uvl uvcenter; + fix rotmat[4]; + + compute_uv_side_center(&uvcenter, Cursegp, Curside); + + // Create a rotation matrix + rotmat[0] = -0xffff; + rotmat[1] = 0; + rotmat[2] = 0; + rotmat[3] = 0xffff; + + rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ----------------------------------------------------------- +int TexFlipY() +{ + uvl uvcenter; + fix rotmat[4]; + + compute_uv_side_center(&uvcenter, Cursegp, Curside); + + // Create a rotation matrix + rotmat[0] = 0xffff; + rotmat[1] = 0; + rotmat[2] = 0; + rotmat[3] = -0xffff; + + rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ----------------------------------------------------------- +int DoTexSlideLeft(int value) +{ + side *sidep; + uvl duvl03; + fix dist; + sbyte *vp; + int v; + + vp = Side_to_verts[Curside]; + sidep = &Cursegp->sides[Curside]; + + dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]); + dist *= value; + if (dist < F1_0/(64*value)) + dist = F1_0/(64*value); + + duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist); + duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist); + + for (v=0; v<4; v++) { + sidep->uvls[v].u -= duvl03.u; + sidep->uvls[v].v -= duvl03.v; + } + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int TexSlideLeft() +{ + return DoTexSlideLeft(3); +} + +int TexSlideLeftBig() +{ + return DoTexSlideLeft(1); +} + +// ----------------------------------------------------------- +int DoTexSlideUp(int value) +{ + side *sidep; + uvl duvl03; + fix dist; + sbyte *vp; + int v; + + vp = Side_to_verts[Curside]; + sidep = &Cursegp->sides[Curside]; + + dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]); + dist *= value; + + if (dist < F1_0/(64*value)) + dist = F1_0/(64*value); + + duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist); + duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist); + + for (v=0; v<4; v++) { + sidep->uvls[v].u -= duvl03.u; + sidep->uvls[v].v -= duvl03.v; + } + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int TexSlideUp() +{ + return DoTexSlideUp(3); +} + +int TexSlideUpBig() +{ + return DoTexSlideUp(1); +} + + +// ----------------------------------------------------------- +int DoTexSlideDown(int value) +{ + side *sidep; + uvl duvl03; + fix dist; + sbyte *vp; + int v; + + vp = Side_to_verts[Curside]; + sidep = &Cursegp->sides[Curside]; + + dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[1]]], &Vertices[Cursegp->verts[vp[0]]]); + dist *= value; + if (dist < F1_0/(64*value)) + dist = F1_0/(64*value); + + duvl03.u = fixdiv(sidep->uvls[1].u - sidep->uvls[0].u,dist); + duvl03.v = fixdiv(sidep->uvls[1].v - sidep->uvls[0].v,dist); + + for (v=0; v<4; v++) { + sidep->uvls[v].u += duvl03.u; + sidep->uvls[v].v += duvl03.v; + } + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int TexSlideDown() +{ + return DoTexSlideDown(3); +} + +int TexSlideDownBig() +{ + return DoTexSlideDown(1); +} + +// ----------------------------------------------------------- +// Compute the center of the side in u,v coordinates. +void compute_uv_side_center(uvl *uvcenter, segment *segp, int sidenum) +{ + int v; + side *sidep = &segp->sides[sidenum]; + + uvcenter->u = 0; + uvcenter->v = 0; + + for (v=0; v<4; v++) { + uvcenter->u += sidep->uvls[v].u; + uvcenter->v += sidep->uvls[v].v; + } + + uvcenter->u /= 4; + uvcenter->v /= 4; +} + + +// ----------------------------------------------------------- +// rotate point *uv by matrix rotmat, return *uvrot +void rotate_uv_point(uvl *uvrot, fix *rotmat, uvl *uv, uvl *uvcenter) +{ + uvrot->u = fixmul(uv->u - uvcenter->u,rotmat[0]) + fixmul(uv->v - uvcenter->v,rotmat[1]) + uvcenter->u; + uvrot->v = fixmul(uv->u - uvcenter->u,rotmat[2]) + fixmul(uv->v - uvcenter->v,rotmat[3]) + uvcenter->v; +} + +// ----------------------------------------------------------- +// Compute the center of the side in u,v coordinates. +void rotate_uv_points_on_side(segment *segp, int sidenum, fix *rotmat, uvl *uvcenter) +{ + int v; + side *sidep = &segp->sides[sidenum]; + uvl tuv; + + for (v=0; v<4; v++) { + rotate_uv_point(&tuv, rotmat, &sidep->uvls[v], uvcenter); + sidep->uvls[v] = tuv; + } +} + +// ----------------------------------------------------------- +// ang is in 0..ffff = 0..359.999 degrees +// rotmat is filled in with 4 fixes +void create_2d_rotation_matrix(fix *rotmat, fix ang) +{ + fix sinang, cosang; + + fix_sincos(ang, &sinang, &cosang); + + rotmat[0] = cosang; + rotmat[1] = sinang; + rotmat[2] = -sinang; + rotmat[3] = cosang; + +} + + +// ----------------------------------------------------------- +int DoTexRotateLeft(int value) +{ + uvl uvcenter; + fix rotmat[4]; + + compute_uv_side_center(&uvcenter, Cursegp, Curside); + + // Create a rotation matrix + create_2d_rotation_matrix(rotmat, -F1_0/value); + + rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int TexRotateLeft() +{ + return DoTexRotateLeft(192); +} + +int TexRotateLeftBig() +{ + return DoTexRotateLeft(64); +} + + +// ----------------------------------------------------------- +int DoTexSlideRight(int value) +{ + side *sidep; + uvl duvl03; + fix dist; + sbyte *vp; + int v; + + vp = Side_to_verts[Curside]; + sidep = &Cursegp->sides[Curside]; + + dist = vm_vec_dist(&Vertices[Cursegp->verts[vp[3]]], &Vertices[Cursegp->verts[vp[0]]]); + dist *= value; + if (dist < F1_0/(64*value)) + dist = F1_0/(64*value); + + duvl03.u = fixdiv(sidep->uvls[3].u - sidep->uvls[0].u,dist); + duvl03.v = fixdiv(sidep->uvls[3].v - sidep->uvls[0].v,dist); + + for (v=0; v<4; v++) { + sidep->uvls[v].u += duvl03.u; + sidep->uvls[v].v += duvl03.v; + } + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int TexSlideRight() +{ + return DoTexSlideRight(3); +} + +int TexSlideRightBig() +{ + return DoTexSlideRight(1); +} + +// ----------------------------------------------------------- +int DoTexRotateRight(int value) +{ + uvl uvcenter; + fix rotmat[4]; + + compute_uv_side_center(&uvcenter, Cursegp, Curside); + + // Create a rotation matrix + create_2d_rotation_matrix(rotmat, F1_0/value); + + rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +int TexRotateRight() +{ + return DoTexRotateRight(192); +} + +int TexRotateRightBig() +{ + return DoTexRotateRight(64); +} + +// ----------------------------------------------------------- +int TexSelectActiveEdge() +{ + return 1; +} + +// ----------------------------------------------------------- +int TexRotate90Degrees() +{ + uvl uvcenter; + fix rotmat[4]; + + compute_uv_side_center(&uvcenter, Cursegp, Curside); + + // Create a rotation matrix + create_2d_rotation_matrix(rotmat, F1_0/4); + + rotate_uv_points_on_side(Cursegp, Curside, rotmat, &uvcenter); + + Update_flags |= UF_WORLD_CHANGED; + + return 1; +} + +// ----------------------------------------------------------- +int TexSetDefault() +{ + Num_tilings = 1; + + Stretch_scale_x = F1_0; + Stretch_scale_y = F1_0; + + assign_default_uvs_to_side(Cursegp,Curside); + + Update_flags |= UF_GAME_VIEW_CHANGED; + return 1; +} + +// ----------------------------------------------------------- +int TexIncreaseTiling() +{ + + Num_tilings++; + assign_default_uvs_to_side(Cursegp, Curside); + Update_flags |= UF_GAME_VIEW_CHANGED; + + return 1; +} + +// ----------------------------------------------------------- +int TexDecreaseTiling() +{ + + if (--Num_tilings < 1) + Num_tilings = 1; + + assign_default_uvs_to_side(Cursegp, Curside); + Update_flags |= UF_GAME_VIEW_CHANGED; + + return 1; +} + + +// direction = -1 or 1 depending on direction +int TexStretchCommon(int direction) +{ + fix *sptr; + + if ((Curedge == 0) || (Curedge == 2)) + sptr = &Stretch_scale_x; + else + sptr = &Stretch_scale_y; + + *sptr += direction*F1_0/64; + + if (*sptr < F1_0/16) + *sptr = F1_0/16; + + if (*sptr > 2*F1_0) + *sptr = 2*F1_0; + + stretch_uvs_from_curedge(Cursegp, Curside); + + editor_status("Stretch scale = %7.4f, use Set Default to return to 1.0", f2fl(*sptr)); + + Update_flags |= UF_GAME_VIEW_CHANGED; + return 1; + +} + +int TexStretchDown(void) +{ + return TexStretchCommon(-1); + +} + +int TexStretchUp(void) +{ + return TexStretchCommon(1); + +} + -- 2.39.2