#include "doom.h" #include "gdredit.h" #include #include #include #include #include #include #include #include #define BUFFER_SIZE 132 #define MAX_THINGS 120 #define MAX_UNKNOWNS 40 #define MainClassName "GDREdit" #define MAX_OBJECTS 50 #define VERTEX_SIZE 3 #define RED_COLOUR RGB (255,0,0) #define YELLOW_COLOUR RGB (255,255,95) #define BLUE_COLOUR RGB (0,0,160) #define SECTION_NAME "CONFIG" #define PROFILE_FILE "GDREDIT.INI" // Edit modes. #define THING_EDIT 1 #define VERTEX_EDIT 2 #define LINEDEF_EDIT 3 #define SECTOR_EDIT 4 #define REDRAW_MESSAGE WM_USER + 1 #define ADD_MESSAGE WM_USER + 2 #define DELETE_MESSAGE WM_USER + 3 // Our fabulous global variable area. HWND hInst; HWND hWndMain; HWND hWndButtonBar; HWND hWndThing; HWND hWndSector; HWND hWndLineDef; HWND hWndSideDef; Header DoomHeader; DirectoryEntry * DoomDirectory = NULL; DoomObject * DoomObjects [MAX_OBJECTS]; int StartObject; int EndObject; int NoOfDoomObjects; int CurrentThing = -1; int CurrentVertex = -1; int CurrentSector = -1; int CurrentLineDef = -1; int CurrentLeftDef = -1; int CurrentRightDef = -1; int LastLineDef = -1; int UseSide1; int SectorOn = FALSE; int Scale; int OffsetX; int OffsetY; int ThingSize; int MouseDown = FALSE; int MoveMode = FALSE; char FileName [20]; int EditMode = THING_EDIT; int ObjectList [512]; int NoOfListObjects; int GridSnap; int GridSize; HPEN YellowPen; HPEN RedPen; HPEN BluePen; HBRUSH RedBrush; HBRUSH BlueBrush; int LineDefAddMode; int SectorAddMode; int FromVertex; int ToVertex; char DoomWadName [80]; char DoomWadPath [80]; int Registered = FALSE; BOOL FAR PASCAL ChooseLevelProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_INITDIALOG: { char Text [10]; int Loop; // Load the level names into the list box. for (Loop = 0;Loop < DoomHeader.NumberOfEntries;Loop++) { if (DoomDirectory [Loop].ResourceName [0] == 'E') { strncpy (Text,DoomDirectory [Loop].ResourceName,8); SendDlgItemMessage (hWndDlg,10,LB_ADDSTRING,0,(LONG) Text); } } SendDlgItemMessage (hWndDlg,10,LB_SETCURSEL,0,0); } break; case WM_CLOSE: PostMessage (hWndDlg,WM_COMMAND,IDCANCEL,0L); break; case WM_COMMAND: switch (wParam) { case 10: // The list box. if (HIWORD (lParam) == LBN_DBLCLK) SendMessage (hWndDlg,WM_COMMAND,IDOK,0L); break; case IDOK: { char Text [10]; int Loop; int Loop2; int Done; // Set up the globals to whichever level was selected. SendDlgItemMessage (hWndDlg,10,LB_GETTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,LB_GETCURSEL,0,0L),(LONG) Text); for (Loop = 0;Loop < DoomHeader.NumberOfEntries;Loop++) { if (strncmp (DoomDirectory [Loop].ResourceName,Text,8) == 0) { StartObject = Loop; EndObject = (int) DoomHeader.NumberOfEntries; Loop2 = Loop + 1; Done = FALSE; do { if (DoomDirectory [Loop2].ResourceName [0] == 'E') { EndObject = Loop2; Done = TRUE; } Loop2++; } while ((Loop2 < DoomHeader.NumberOfEntries) && (!Done)); } } EndDialog (hWndDlg,TRUE); } break; case IDCANCEL: EndDialog (hWndDlg,FALSE); break; } break; default: return FALSE; } return TRUE; } void UnloadWadFile () { int Loop; // Delete all our objects in the system. for (Loop = 0;Loop < NoOfDoomObjects;Loop++) delete DoomObjects [Loop]; // Get rid of the directory. if (DoomDirectory) { delete [] DoomDirectory; DoomDirectory = NULL; } // Reset the globals. StartObject = 0; EndObject = 0; NoOfDoomObjects = 0; CurrentThing = -1; CurrentLineDef = -1; LastLineDef = -1; CurrentSector = -1; CurrentVertex = -1; CurrentLeftDef = -1; CurrentRightDef = -1; NoOfListObjects = 0; FileName [0] = '\000'; // Reset the drawing area or there will be divide by zero errors // when editing new wads. Scale = 8; OffsetX = 0; OffsetY = 0; } void ReadWadFile (char * WadFileName) { int FileHandle; int Done; int Loop; FARPROC MsgProc; int Result; int NoOfLevels = 0; // Unload current wad file if one exists. UnloadWadFile (); // Read in the header and directory with room to add entries. FileHandle = open (WadFileName,O_BINARY|O_RDONLY); read (FileHandle,&DoomHeader,sizeof (Header)); DoomDirectory = new DirectoryEntry [DoomHeader.NumberOfEntries + 100]; lseek (FileHandle,DoomHeader.DirectoryPointer,SEEK_SET); lread (FileHandle,DoomDirectory,sizeof (DirectoryEntry) * DoomHeader.NumberOfEntries); // Load the level names into the list box. for (Loop = 0;Loop < DoomHeader.NumberOfEntries;Loop++) { if (DoomDirectory [Loop].ResourceName [0] == 'E') NoOfLevels++; } // Display a list of levels and select one. if (NoOfLevels > 1) { MsgProc = MakeProcInstance ((FARPROC) ChooseLevelProc,hInst); Result = DialogBox (hInst,(LPSTR) "CHOOSE_BOX",hWndMain,MsgProc); FreeProcInstance (MsgProc); if (!Result) return; } else { // Only one level. Load all the stuff in. EndObject = (int) DoomHeader.NumberOfEntries; } // Load up our selected level. for (Loop = StartObject;Loop < EndObject;Loop++) { Done = FALSE; if (strncmp (DoomDirectory [Loop].ResourceName,"VERTEXES",8) == 0) { int MinX = 32000; int MinY = 32000; int MaxX = -32000; int MaxY = -32000; int InnerLoop; Done = TRUE; DoomObjects [NoOfDoomObjects] = new DoomVertexObject (FileHandle,&DoomDirectory [Loop]); VertexPointer = (DoomVertexObject *) DoomObjects [NoOfDoomObjects]; if (VertexPointer->NoOfObjects > 0) CurrentVertex = 0; // Now find a good viewing point to survey our kingdom from. Scale = 8; for (InnerLoop = 0;InnerLoop < VertexPointer->NoOfObjects;InnerLoop++) { MinX = min (VertexPointer->Data [InnerLoop].X,MinX); MinY = min (VertexPointer->Data [InnerLoop].Y,MinY); MaxX = max (VertexPointer->Data [InnerLoop].X,MaxX); MaxY = max (VertexPointer->Data [InnerLoop].Y,MaxY); } OffsetX = -(MinX + MaxX) / 2 + (400 * Scale); OffsetY = -(MinY + MaxY) / 2 - (300 * Scale); } if (strncmp (DoomDirectory [Loop].ResourceName,"LINEDEFS",8) == 0) { Done = TRUE; DoomObjects [NoOfDoomObjects] = new DoomLineDefObject (FileHandle,&DoomDirectory [Loop]); if (LineDefPointer->NoOfObjects > 0) CurrentLineDef = 0; } if (strncmp (DoomDirectory [Loop].ResourceName,"THINGS",8) == 0) { Done = TRUE; DoomObjects [NoOfDoomObjects] = new DoomThingObject (FileHandle,&DoomDirectory [Loop]); if (ThingPointer->NoOfObjects > 0) CurrentThing = 0; } if (strncmp (DoomDirectory [Loop].ResourceName,"SIDEDEFS",8) == 0) { Done = TRUE; DoomObjects [NoOfDoomObjects] = new DoomSideDefObject (FileHandle,&DoomDirectory [Loop]); } if (strncmp (DoomDirectory [Loop].ResourceName,"SECTORS",8) == 0) { Done = TRUE; DoomObjects [NoOfDoomObjects] = new DoomSectorObject (FileHandle,&DoomDirectory [Loop]); if (SectorPointer->NoOfObjects > 0) CurrentSector = 0; } if (!Done) DoomObjects [NoOfDoomObjects] = new DoomObject (FileHandle,&DoomDirectory [Loop]); NoOfDoomObjects++; } // Fill the dialogs with some default info. SendMessage (hWndThing,REDRAW_MESSAGE,0,0L); SendMessage (hWndSector,REDRAW_MESSAGE,0,0L); SendMessage (hWndLineDef,REDRAW_MESSAGE,0,0L); // Clean up. close (FileHandle); } void WriteWadFile (char * WadFileName) { int FileHandle; int Loop; // Write the header to hold a place for the real header. FileHandle = open (WadFileName,O_BINARY|O_WRONLY|O_TRUNC|O_CREAT); strncpy (DoomHeader.Signature,"PWAD",4); DoomHeader.NumberOfEntries = NoOfDoomObjects; write (FileHandle,&DoomHeader,sizeof (Header)); // Save all the objects. for (Loop = 0;Loop < NoOfDoomObjects;Loop++) DoomObjects [Loop]->SaveObject (FileHandle,&DoomDirectory [StartObject + Loop]); // Pump out the directory, then a REAL copy of the header. DoomHeader.DirectoryPointer = tell (FileHandle); lwrite (FileHandle,&DoomDirectory [StartObject],(long) sizeof (DirectoryEntry) * (long) NoOfDoomObjects); lseek (FileHandle,0L,SEEK_SET); write (FileHandle,&DoomHeader,sizeof (Header)); // Clean up. close (FileHandle); } void NewWadFile () { // Unload current wad file if one exists. UnloadWadFile (); SetWindowText (hWndMain,"GDR Edit - NEW.WAD"); strcpy (FileName,"NEW.WAD"); // Set up the header. strncpy (DoomHeader.Signature,"PWAD",4); DoomHeader.NumberOfEntries = 11; NoOfDoomObjects = 11; // Set up the directory with spare room in it. DoomDirectory = new DirectoryEntry [DoomHeader.NumberOfEntries + 100]; memset (DoomDirectory,0,(int (DoomHeader.NumberOfEntries) + 100) * sizeof (DirectoryEntry)); // Load up the values for a base level. strncpy (DoomDirectory [0].ResourceName,"E1M1",8); DoomObjects [0] = new DoomObject (); strncpy (DoomDirectory [1].ResourceName,"THINGS",8); DoomObjects [1] = new DoomThingObject (); strncpy (DoomDirectory [2].ResourceName,"LINEDEFS",8); DoomObjects [2] = new DoomLineDefObject (); strncpy (DoomDirectory [3].ResourceName,"SIDEDEFS",8); DoomObjects [3] = new DoomSideDefObject (); strncpy (DoomDirectory [4].ResourceName,"VERTEXES",8); DoomObjects [4] = new DoomVertexObject (); strncpy (DoomDirectory [5].ResourceName,"SEGS",8); DoomObjects [5] = new DoomObject (); strncpy (DoomDirectory [6].ResourceName,"SSECTORS",8); DoomObjects [6] = new DoomObject (); strncpy (DoomDirectory [7].ResourceName,"NODES",8); DoomObjects [7] = new DoomObject (); strncpy (DoomDirectory [8].ResourceName,"SECTORS",8); DoomObjects [8] = new DoomSectorObject (); strncpy (DoomDirectory [9].ResourceName,"REJECT",8); DoomObjects [9] = new DoomObject (); strncpy (DoomDirectory [10].ResourceName,"BLOCKMAP",8); DoomObjects [10] = new DoomObject (); // Fill the dialogs with some default info. InvalidateRect (hWndMain,NULL,TRUE); SendMessage (hWndThing,REDRAW_MESSAGE,0,0L); SendMessage (hWndSector,REDRAW_MESSAGE,0,0L); SendMessage (hWndLineDef,REDRAW_MESSAGE,0,0L); } void LoadWadFile () { OPENFILENAME FileOpenDialog; char Filter [] = "Data files (*.wad)\0*.wad\0All files (*.*)\0*.*\0"; char Text [80]; char FileName [20]; // Setup for the common file open dialog. memset (&FileOpenDialog,0,sizeof (FileOpenDialog)); FileOpenDialog.lStructSize = sizeof (FileOpenDialog); FileOpenDialog.hWndOwner = hWndMain; FileOpenDialog.hInstance = hInst; FileOpenDialog.lpstrFilter = Filter; FileOpenDialog.nFilterIndex = 1; FileOpenDialog.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; FileOpenDialog.lpstrFileTitle = FileName; if (GetOpenFileName (&FileOpenDialog)) { // Found a filename, process the file. ReadWadFile (FileName); sprintf (Text,"GDR Edit - %s",FileName); SetWindowText (hWndMain,Text); InvalidateRect (hWndMain,NULL,TRUE); } } void SaveWadFile () { OPENFILENAME FileSaveDialog; char Text [80]; // Setup for the common file open dialog. memset (&FileSaveDialog,0,sizeof (FileSaveDialog)); FileSaveDialog.lStructSize = sizeof (FileSaveDialog); FileSaveDialog.hWndOwner = hWndMain; FileSaveDialog.hInstance = hInst; FileSaveDialog.lpstrFilter = "Data files (*.wad)\0*.wad\0All files (*.*)\0*.*\0"; FileSaveDialog.lpstrDefExt = "WAD"; FileSaveDialog.nFilterIndex = 1; FileSaveDialog.Flags = OFN_PATHMUSTEXIST; FileSaveDialog.lpstrFileTitle = FileName; // If we get a name, save the file. if (GetSaveFileName (&FileSaveDialog)) { WriteWadFile (FileName); sprintf (Text,"GDR Edit - %s",FileName); SetWindowText (hWndMain,Text); } } void DrawLineDef (HDC DC,int EntryNo) { int MidX; int MidY; int EndX; int EndY; int Trim; // Draw the line itself. MoveTo (DC,(VertexPointer->Data [LineDefPointer->Data [EntryNo].FromVertex].X + OffsetX) / Scale,-(VertexPointer->Data [LineDefPointer->Data [EntryNo].FromVertex].Y + OffsetY) / Scale); LineTo (DC,(VertexPointer->Data [LineDefPointer->Data [EntryNo].ToVertex].X + OffsetX) / Scale,-(VertexPointer->Data [LineDefPointer->Data [EntryNo].ToVertex].Y + OffsetY) / Scale); // Place the tick mark. if (EditMode == SECTOR_EDIT || EditMode == LINEDEF_EDIT) { // Get the midpoints. MidX = (VertexPointer->Data [LineDefPointer->Data [EntryNo].FromVertex].X + VertexPointer->Data [LineDefPointer->Data [EntryNo].ToVertex].X) / 2; MidY = (VertexPointer->Data [LineDefPointer->Data [EntryNo].FromVertex].Y + VertexPointer->Data [LineDefPointer->Data [EntryNo].ToVertex].Y) / 2; // Get the deltas. EndX = VertexPointer->Data [LineDefPointer->Data [EntryNo].ToVertex].Y - VertexPointer->Data [LineDefPointer->Data [EntryNo].FromVertex].Y; EndY = VertexPointer->Data [LineDefPointer->Data [EntryNo].FromVertex].X - VertexPointer->Data [LineDefPointer->Data [EntryNo].ToVertex].X; // Trim the deltas to a maximum value. if (abs (EndX) >= abs (EndY)) Trim = abs (EndX) / 16; else Trim = abs (EndY) / 16; if (Trim == 0) Trim = 1; EndX /= Trim; EndY /= Trim; // Add our delta values. EndX += MidX; EndY += MidY; MoveTo (DC,(MidX + OffsetX) / Scale,-(MidY + OffsetY) / Scale); LineTo (DC,(EndX + OffsetX) / Scale,-(EndY + OffsetY) / Scale); } } void PaintIt (HDC DC) { int Loop; RECT Rect; // Setup for the draw. SetROP2 (DC,R2_NOTMERGEPEN); // Draw some linedefs. if (LineDefPointer && VertexPointer) { for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) DrawLineDef (DC,Loop); } // Draw some vertexes. if (VertexPointer && (EditMode == VERTEX_EDIT || EditMode == LINEDEF_EDIT || EditMode == SECTOR_EDIT)) { for (Loop = 0;Loop < VertexPointer->NoOfObjects;Loop++) { SetRect (&Rect,(VertexPointer->Data [Loop].X + OffsetX) / Scale - VERTEX_SIZE,-(VertexPointer->Data [Loop].Y + OffsetY) / Scale - VERTEX_SIZE,(VertexPointer->Data [Loop].X + OffsetX) / Scale + VERTEX_SIZE,-(VertexPointer->Data [Loop].Y + OffsetY) / Scale + VERTEX_SIZE); InvertRect (DC,&Rect); } } // Draw some things. if (ThingPointer && (EditMode == THING_EDIT)) { // Set the size a thing should be drawn at. ThingSize = 16 / Scale; if (ThingSize < 2) ThingSize = 2; // Draw all the things. for (Loop = 0;Loop < ThingPointer->NoOfObjects;Loop++) { SetRect (&Rect,(ThingPointer->Data [Loop].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [Loop].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [Loop].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [Loop].Y + OffsetY) / Scale + ThingSize); InvertRect (DC,&Rect); } } // Draw the highlighted linedef. SetROP2 (DC,R2_COPYPEN); SelectObject (DC,RedPen); if (LineDefPointer && EditMode == LINEDEF_EDIT && CurrentLineDef >= 0) DrawLineDef (DC,CurrentLineDef); // If we have a sector then we should highlight it. if (SectorPointer && EditMode == SECTOR_EDIT && CurrentSector >= 0) for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); } BOOL FAR PASCAL ButtonBarMsgProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_COMMAND: switch (wParam) { case 202: // Up arrow. OffsetY -= 20 * Scale; InvalidateRect (hWndMain,NULL,TRUE); break; case 203: // Down arrow. OffsetY += 20 * Scale; InvalidateRect (hWndMain,NULL,TRUE); break; case 204: // Left arrow. OffsetX += 20 * Scale; InvalidateRect (hWndMain,NULL,TRUE); break; case 205: // Right arrow. OffsetX -= 20 * Scale; InvalidateRect (hWndMain,NULL,TRUE); break; case 206: // Zoom in. // Zoom in for detail work. if (Scale > 1) { Scale--; OffsetX -= 400; OffsetY += 300; InvalidateRect (hWndMain,NULL,TRUE); } break; case 207: // Zoom out // Zoom out for overall view. if (Scale < 20) { Scale++; OffsetX += 400; OffsetY -= 300; InvalidateRect (hWndMain,NULL,TRUE); } break; case 212: // Add something. SendMessage (hWndMain,ADD_MESSAGE,0,0L); break; case 213: // Delete something. SendMessage (hWndMain,DELETE_MESSAGE,0,0L); break; } break; default: return FALSE; } return TRUE; } // ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» // º Thing Editing º // º º // º Allow the adding, moving, changing and deleting of things in the .WAD º // º file. º // ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ int FindThatThing (int X,int Y) { int Loop; long DX; long DY; long Min = 1000000L; long Value; int Selected = -1; RECT Rect; POINT Point; Point.x = X; Point.y = Y; if (ThingPointer) { // Check for an exact hit first. for (Loop = 0;Loop < ThingPointer->NoOfObjects;Loop++) { SetRect (&Rect,(ThingPointer->Data [Loop].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [Loop].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [Loop].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [Loop].Y + OffsetY) / Scale + ThingSize); if (PtInRect (&Rect,Point)) return Loop; } // Try for the nearest instead. for (Loop = 0;Loop < ThingPointer->NoOfObjects;Loop++) { DX = (long) (ThingPointer->Data [Loop].X + OffsetX) / Scale - X; DY = (long) -(ThingPointer->Data [Loop].Y + OffsetY) / Scale - Y; Value = DX * DX + DY * DY; if (Value < Min) { Min = Value; Selected = Loop; } } } return Selected; } BOOL FAR PASCAL ThingProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_INITDIALOG: { fstream InActivityFile; char Buffer [BUFFER_SIZE]; char Text [BUFFER_SIZE]; int ItemType; char * CopyFrom; InActivityFile.open ("GDREDIT.INI",ios::in|ios::nocreate); if (!InActivityFile.fail ()) { // Get to the start of the section we want. do { InActivityFile.getline (Buffer,BUFFER_SIZE); } while (!InActivityFile.eof () && strcmp (Buffer,"[THINGS]") != 0); InActivityFile.getline (Buffer,BUFFER_SIZE); while (!InActivityFile.eof () && Buffer [0] != '[') { if (strlen (Buffer) > 0) { ItemType = atoi (Buffer); CopyFrom = strstr (Buffer,","); if (CopyFrom != NULL) strcpy (Text,CopyFrom + 1); SendDlgItemMessage (hWndDlg,10,CB_SETITEMDATA,(WORD) SendDlgItemMessage (hWndDlg,10,CB_ADDSTRING,0,(LONG) Text),(LONG) ItemType); } InActivityFile.getline (Buffer,BUFFER_SIZE); } InActivityFile.close (); } SendDlgItemMessage (hWndDlg,10,CB_SETCURSEL,0,0); } break; case REDRAW_MESSAGE: // Update the window. { int Loop; int ListCount; int Finished = FALSE; int Entry = -1; // Update our display. if (ThingPointer && CurrentThing >= 0) { Loop = -1; ListCount = (int) SendDlgItemMessage (hWndDlg,10,CB_GETCOUNT,0,0L); do { Loop++; if (SendDlgItemMessage (hWndDlg,10,CB_GETITEMDATA,Loop,0) == ThingPointer->Data [CurrentThing].Type) { Finished = TRUE; Entry = Loop; } } while ((!Finished) && (Loop < ListCount - 1)); SendDlgItemMessage (hWndDlg,10,CB_SETCURSEL,Entry,0); CheckDlgButton (hWndDlg,11,ThingPointer->Data [CurrentThing].Bitset & 1); CheckDlgButton (hWndDlg,12,ThingPointer->Data [CurrentThing].Bitset & 2); CheckDlgButton (hWndDlg,13,ThingPointer->Data [CurrentThing].Bitset & 4); CheckDlgButton (hWndDlg,14,ThingPointer->Data [CurrentThing].Bitset & 8); CheckDlgButton (hWndDlg,15,ThingPointer->Data [CurrentThing].Bitset & 16); SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); } } break; case WM_COMMAND: if (ThingPointer && CurrentThing >= 0) { switch (wParam) { case 10: // Type of object. if (HIWORD (lParam) == CBN_SELCHANGE) ThingPointer->Data [CurrentThing].Type = (int) SendDlgItemMessage (hWndDlg,10,CB_GETITEMDATA,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),0); break; case 11: // Level 1 if (ThingPointer->Data [CurrentThing].Bitset & 1) ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset - 1; else ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset + 1; break; case 12: // Levels 2 & 3 if (ThingPointer->Data [CurrentThing].Bitset & 2) ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset - 2; else ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset + 2; break; case 13: // Levels 4 & 5 if (ThingPointer->Data [CurrentThing].Bitset & 4) ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset - 4; else ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset + 4; break; case 14: // Deaf bugger. if (ThingPointer->Data [CurrentThing].Bitset & 8) ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset - 8; else ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset + 8; break; case 15: // Net game. if (ThingPointer->Data [CurrentThing].Bitset & 16) ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset - 16; else ThingPointer->Data [CurrentThing].Bitset = ThingPointer->Data [CurrentThing].Bitset + 16; break; case 204: ThingPointer->Data [CurrentThing].Angle = 0; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 208: ThingPointer->Data [CurrentThing].Angle = 45; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 202: ThingPointer->Data [CurrentThing].Angle = 90; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 209: ThingPointer->Data [CurrentThing].Angle = 135; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 205: ThingPointer->Data [CurrentThing].Angle = 180; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 210: ThingPointer->Data [CurrentThing].Angle = 225; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 203: ThingPointer->Data [CurrentThing].Angle = 270; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; case 211: ThingPointer->Data [CurrentThing].Angle = 315; SetDlgItemInt (hWndDlg,16,ThingPointer->Data [CurrentThing].Angle,TRUE); break; } } break; default: return FALSE; } return TRUE; } LONG FAR PASCAL ThingEdit (HWND hWnd, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_RBUTTONDOWN: // They want to add/delete things. { RECT Rect; POINT Point; int Done = FALSE; int Loop; HDC DC; Point.x = LOWORD (lParam); Point.y = HIWORD (lParam); if (ThingPointer) { // Check for an exact hit. for (Loop = 0;Loop < ThingPointer->NoOfObjects;Loop++) { SetRect (&Rect,(ThingPointer->Data [Loop].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [Loop].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [Loop].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [Loop].Y + OffsetY) / Scale + ThingSize); if (PtInRect (&Rect,Point)) { Done = TRUE; CurrentThing = Loop; SendMessage (hWndMain,DELETE_MESSAGE,0,0L); } } // Add a new thing instead. if (Done == FALSE) { CurrentThing = ThingPointer->Add (CurrentThing,LOWORD (lParam) * Scale - OffsetX,-(HIWORD (lParam) * Scale + OffsetY)); DC = GetDC (hWndMain); SetRect (&Rect,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale + ThingSize); InvertRect (DC,&Rect); ReleaseDC (hWndMain,DC); SendMessage (hWndThing,REDRAW_MESSAGE,0,0L); } } } break; case WM_LBUTTONDOWN: // They want to move/edit something. { int Result; Result = FindThatThing (LOWORD (lParam),HIWORD (lParam)); if (Result != -1) { CurrentThing = Result; SendMessage (hWndThing,REDRAW_MESSAGE,0,0L); MouseDown = TRUE; } } break; case WM_LBUTTONUP: // Cleanup after move. MoveMode = FALSE; MouseDown = FALSE; break; case WM_MOUSEMOVE: // Check for drags. if (MouseDown) { RECT Rect; HDC DC; // Erase object. MoveMode = TRUE; DC = GetDC (hWndMain); SetRect (&Rect,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale + ThingSize); InvertRect (DC,&Rect); // Update position. ThingPointer->Data [CurrentThing].X = LOWORD (lParam) * Scale - OffsetX; ThingPointer->Data [CurrentThing].Y = -(HIWORD (lParam) * Scale + OffsetY); // Redraw object at new location. SetRect (&Rect,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale + ThingSize); InvertRect (DC,&Rect); ReleaseDC (hWndMain,DC); } break; case DELETE_MESSAGE: { RECT Rect; HDC DC; // Erase object. DC = GetDC (hWndMain); SetRect (&Rect,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale - ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale - ThingSize,(ThingPointer->Data [CurrentThing].X + OffsetX) / Scale + ThingSize,-(ThingPointer->Data [CurrentThing].Y + OffsetY) / Scale + ThingSize); InvertRect (DC,&Rect); ThingPointer->Delete (CurrentThing); ReleaseDC (hWndMain,DC); // Switch to the previous thing. ThingPointer->Delete (CurrentThing); CurrentThing--; if (CurrentThing < 0) CurrentThing = ThingPointer->NoOfObjects - 1; // Update the dialog box. SendMessage (hWndThing,REDRAW_MESSAGE,0,0L); } break; default: return DefWindowProc (hWnd,Message,wParam,lParam); } return 0L; } // ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» // º Vertex Editing º // º º // º Pretty obvious. º // ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ int FindThatVertex (int X,int Y) { int Loop; RECT Rect; POINT Point; long DX; long DY; long Min = 1000000L; long Value; int Selected = -1; Point.x = X; Point.y = Y; if (VertexPointer) { // Check for an exact hit first. for (Loop = 0;Loop < VertexPointer->NoOfObjects;Loop++) { SetRect (&Rect,(VertexPointer->Data [Loop].X + OffsetX) / Scale - VERTEX_SIZE,-(VertexPointer->Data [Loop].Y + OffsetY) / Scale - VERTEX_SIZE,(VertexPointer->Data [Loop].X + OffsetX) / Scale + VERTEX_SIZE,-(VertexPointer->Data [Loop].Y + OffsetY) / Scale + VERTEX_SIZE); if (PtInRect (&Rect,Point)) return Loop; } // Try for the nearest instead. for (Loop = 0;Loop < VertexPointer->NoOfObjects;Loop++) { DX = (long) (VertexPointer->Data [Loop].X + OffsetX) / Scale - X; DY = (long) -(VertexPointer->Data [Loop].Y + OffsetY) / Scale - Y; Value = DX * DX + DY * DY; if (Value < Min) { Min = Value; Selected = Loop; } } } return Selected; } LONG FAR PASCAL VertexEdit (HWND hWnd, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_RBUTTONDOWN: // They want to add/delete vertexes. { RECT Rect; POINT Point; int Done = FALSE; int Loop; int Loop2; HDC DC; Point.x = LOWORD (lParam); Point.y = HIWORD (lParam); if (VertexPointer) { // Setup time. DC = GetDC (hWndMain); SetROP2 (DC,R2_NOTMERGEPEN); // Check for an exact hit. for (Loop = 0;Loop < VertexPointer->NoOfObjects;Loop++) { SetRect (&Rect,(VertexPointer->Data [Loop].X + OffsetX) / Scale - VERTEX_SIZE,-(VertexPointer->Data [Loop].Y + OffsetY) / Scale - VERTEX_SIZE,(VertexPointer->Data [Loop].X + OffsetX) / Scale + VERTEX_SIZE,-(VertexPointer->Data [Loop].Y + OffsetY) / Scale + VERTEX_SIZE); if (PtInRect (&Rect,Point)) { // Find all linedefs that use this vertex. CurrentVertex = Loop; NoOfListObjects = 0; if (LineDefPointer) { // Detect which lines need updating. for (Loop2 = 0;Loop2 < LineDefPointer->NoOfObjects;Loop2++) { if ((LineDefPointer->Data [Loop2].FromVertex == CurrentVertex) || (LineDefPointer->Data [Loop2].ToVertex == CurrentVertex)) { ObjectList [NoOfListObjects] = Loop2; NoOfListObjects++; } } } // Erase and delete the current linedefs. Work // backwards to avoid indexes changing before we delete // a line. for (Loop2 = NoOfListObjects - 1;Loop2 >= 0;Loop2--) { DrawLineDef (DC,ObjectList [Loop2]); LineDefPointer->Delete (ObjectList [Loop2]); } // Erase object. InvertRect (DC,&Rect); VertexPointer->Delete (CurrentVertex); Done = TRUE; } } // Add a new vertex instead. if (Done == FALSE) { // Add a new vertex taking gridsnap into account. CurrentVertex = VertexPointer->Add (LOWORD (lParam) * Scale - OffsetX,-(HIWORD (lParam) * Scale + OffsetY)); SetRect (&Rect,(VertexPointer->Data [CurrentVertex].X + OffsetX) / Scale - VERTEX_SIZE,-(VertexPointer->Data [CurrentVertex].Y + OffsetY) / Scale - VERTEX_SIZE,(VertexPointer->Data [CurrentVertex].X + OffsetX) / Scale + VERTEX_SIZE,-(VertexPointer->Data [CurrentVertex].Y + OffsetY) / Scale + VERTEX_SIZE); InvertRect (DC,&Rect); } // Cleanup. ReleaseDC (hWndMain,DC); } } break; case WM_LBUTTONDOWN: { int Result; int Loop; Result = FindThatVertex (LOWORD (lParam),HIWORD (lParam)); if (Result != -1) { // Set some global state variables. CurrentVertex = Result; MouseDown = TRUE; // Now we narrow down the list of lines to update from this move. NoOfListObjects = 0; if (LineDefPointer) { // Detect which lines need updating. for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) { if ((LineDefPointer->Data [Loop].FromVertex == CurrentVertex) || (LineDefPointer->Data [Loop].ToVertex == CurrentVertex)) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } } } } } break; case WM_LBUTTONUP: MoveMode = FALSE; MouseDown = FALSE; break; case WM_MOUSEMOVE: // Detect guys in chicks clothes (drags). if (MouseDown) { int Loop; RECT Rect; HDC DC; DC = GetDC (hWndMain); SetROP2 (DC,R2_NOTMERGEPEN); // Erase the vertex from the screen. SetRect (&Rect,(VertexPointer->Data [CurrentVertex].X + OffsetX) / Scale - VERTEX_SIZE,-(VertexPointer->Data [CurrentVertex].Y + OffsetY) / Scale - VERTEX_SIZE,(VertexPointer->Data [CurrentVertex].X + OffsetX) / Scale + VERTEX_SIZE,-(VertexPointer->Data [CurrentVertex].Y + OffsetY) / Scale + VERTEX_SIZE); InvertRect (DC,&Rect); // Erase the current linedefs. for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); // Update the vertex position. VertexPointer->Data [CurrentVertex].X = LOWORD (lParam) * Scale - OffsetX; VertexPointer->Data [CurrentVertex].Y = -(HIWORD (lParam) * Scale + OffsetY); // Take gridsnap int account. if (GridSnap) { VertexPointer->Data [CurrentVertex].X -= VertexPointer->Data [CurrentVertex].X % GridSize; VertexPointer->Data [CurrentVertex].Y -= VertexPointer->Data [CurrentVertex].Y % GridSize; } // Redraw the vertex. SetRect (&Rect,(VertexPointer->Data [CurrentVertex].X + OffsetX) / Scale - VERTEX_SIZE,-(VertexPointer->Data [CurrentVertex].Y + OffsetY) / Scale - VERTEX_SIZE,(VertexPointer->Data [CurrentVertex].X + OffsetX) / Scale + VERTEX_SIZE,-(VertexPointer->Data [CurrentVertex].Y + OffsetY) / Scale + VERTEX_SIZE); InvertRect (DC,&Rect); // Redraw all linedefs. for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); ReleaseDC (hWndMain,DC); MoveMode = TRUE; } break; default: return DefWindowProc (hWnd,Message,wParam,lParam); } return 0L; } // ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» // º LineDef Editing º // º º // º Pretty obvious. º // ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ int FindThatLineDef (int X,int Y) { int Loop; int MidX; int MidY; long DX; long DY; long Min = 1000000L; long Value; int Selected = -1; if (VertexPointer && LineDefPointer) { // Nearest to the centre of a linedef wins ! for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) { // Get the midpoints. MidX = (VertexPointer->Data [LineDefPointer->Data [Loop].FromVertex].X + VertexPointer->Data [LineDefPointer->Data [Loop].ToVertex].X) / 2; MidY = (VertexPointer->Data [LineDefPointer->Data [Loop].FromVertex].Y + VertexPointer->Data [LineDefPointer->Data [Loop].ToVertex].Y) / 2; // Work out distance from the midpoints. DX = (long) (MidX + OffsetX) / Scale - X; DY = (long) -(MidY + OffsetY) / Scale - Y; Value = DX * DX + DY * DY; if (Value < Min) { Min = Value; Selected = Loop; } } } return Selected; } BOOL FAR PASCAL SideDefProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_INITDIALOG: { int Loop; int Loop2; char Text [60]; HANDLE MemHandle; char * MemPointer; int FileHandle; int NoOfTextures; // Open the main WAD file and check out the textures. FileHandle = open (DoomWadName,O_BINARY|O_RDONLY); if (FileHandle) { for (Loop = 0;Loop < DoomHeader.NumberOfEntries;Loop++) { if (strncmp (DoomDirectory [Loop].ResourceName,"TEXTURE",7) == 0) { // One of the texture patch maps. MemHandle = GlobalAlloc (GMEM_MOVEABLE,DoomDirectory [Loop].ResourceSize); MemPointer = (char *) GlobalLock (MemHandle); if (MemPointer) { lseek (FileHandle,DoomDirectory [Loop].ResourcePointer,SEEK_SET); lread (FileHandle,MemPointer,DoomDirectory [Loop].ResourceSize); // Put the strings into a list box. Text [8] = '\000'; NoOfTextures = int (*(long *) MemPointer); for (Loop2 = 0;Loop2 < NoOfTextures;Loop2++) { strncpy (Text,MemPointer + long (*(long *) (MemPointer + 4L * long (Loop2 + 1))),8); SendDlgItemMessage (hWndDlg,10,CB_ADDSTRING,0,(LONG) Text); } // Free the memory. GlobalUnlock (MemHandle); GlobalFree (MemHandle); } } } close (FileHandle); } SendDlgItemMessage (hWndDlg,10,CB_SETCURSEL,0,0); } break; case REDRAW_MESSAGE: // Update the window. { // Update our display. if (SideDefPointer) { if (SideDefPointer->NoOfObjects > 0) { int LeftOn; char Text [20]; // Only make these controls accessable when the left sidedef // exists. LeftOn = LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0; EnableWindow (GetDlgItem (hWndDlg,11),LeftOn); EnableWindow (GetDlgItem (hWndDlg,12),LeftOn); EnableWindow (GetDlgItem (hWndDlg,22),LeftOn); EnableWindow (GetDlgItem (hWndDlg,14),LeftOn); EnableWindow (GetDlgItem (hWndDlg,15),LeftOn); EnableWindow (GetDlgItem (hWndDlg,17),LeftOn); EnableWindow (GetDlgItem (hWndDlg,18),LeftOn); EnableWindow (GetDlgItem (hWndDlg,20),LeftOn); EnableWindow (GetDlgItem (hWndDlg,21),LeftOn); // Fill in the right hand side. SetDlgItemInt (hWndDlg,23,SideDefPointer->Data [CurrentRightDef].X,TRUE); SetDlgItemInt (hWndDlg,24,SideDefPointer->Data [CurrentRightDef].Y,TRUE); SetDlgItemInt (hWndDlg,34,SideDefPointer->Data [CurrentRightDef].Sector,TRUE); Text [8] = '\000'; strncpy (Text,SideDefPointer->Data [CurrentRightDef].Above,8); SetDlgItemText (hWndDlg,25,Text); strncpy (Text,SideDefPointer->Data [CurrentRightDef].Wall,8); SetDlgItemText (hWndDlg,28,Text); strncpy (Text,SideDefPointer->Data [CurrentRightDef].Below,8); SetDlgItemText (hWndDlg,31,Text); // Fill in the left hand side. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { SetDlgItemInt (hWndDlg,11,SideDefPointer->Data [CurrentLeftDef].X,TRUE); SetDlgItemInt (hWndDlg,12,SideDefPointer->Data [CurrentLeftDef].Y,TRUE); SetDlgItemInt (hWndDlg,22,SideDefPointer->Data [CurrentLeftDef].Sector,TRUE); strncpy (Text,SideDefPointer->Data [CurrentLeftDef].Above,8); SetDlgItemText (hWndDlg,13,Text); strncpy (Text,SideDefPointer->Data [CurrentLeftDef].Wall,8); SetDlgItemText (hWndDlg,16,Text); strncpy (Text,SideDefPointer->Data [CurrentLeftDef].Below,8); SetDlgItemText (hWndDlg,19,Text); } else { // Blank out the left side to avoid confusion. SetDlgItemText (hWndDlg,11,""); SetDlgItemText (hWndDlg,12,""); SetDlgItemText (hWndDlg,22,""); SetDlgItemText (hWndDlg,13,""); SetDlgItemText (hWndDlg,16,""); SetDlgItemText (hWndDlg,19,""); } } } } break; case WM_COMMAND: { int Trans; char Text [10]; if (SideDefPointer) { switch (wParam) { case 1: // Ok button. ShowWindow (hWndSideDef,SW_HIDE); break; case 23: // X. if (HIWORD (lParam) == EN_CHANGE) SideDefPointer->Data [CurrentRightDef].X = GetDlgItemInt (hWndDlg,wParam,&Trans,TRUE); break; case 24: // Y. if (HIWORD (lParam) == EN_CHANGE) SideDefPointer->Data [CurrentRightDef].Y = GetDlgItemInt (hWndDlg,wParam,&Trans,TRUE); break; case 26: // Clear Above. strcpy (SideDefPointer->Data [CurrentRightDef].Above,"-"); SetDlgItemText (hWndDlg,25,"-"); break; case 27: // Set Above. SendDlgItemMessage (hWndDlg,10,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SideDefPointer->Data [CurrentRightDef].Above,Text,8); SetDlgItemText (hWndDlg,25,Text); break; case 29: // Clear wall. strcpy (SideDefPointer->Data [CurrentRightDef].Wall,"-"); SetDlgItemText (hWndDlg,28,"-"); break; case 30: // Set wall. SendDlgItemMessage (hWndDlg,10,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SideDefPointer->Data [CurrentRightDef].Wall,Text,8); SetDlgItemText (hWndDlg,28,Text); break; case 32: // Clear Below. strcpy (SideDefPointer->Data [CurrentRightDef].Below,"-"); SetDlgItemText (hWndDlg,31,"-"); break; case 33: // Set Below. SendDlgItemMessage (hWndDlg,10,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SideDefPointer->Data [CurrentRightDef].Below,Text,8); SetDlgItemText (hWndDlg,31,Text); break; // These apply to the left sidedef. case 11: // X. if (HIWORD (lParam) == EN_CHANGE && LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) SideDefPointer->Data [CurrentLeftDef].X = GetDlgItemInt (hWndDlg,wParam,&Trans,TRUE); break; case 12: // Y. if (HIWORD (lParam) == EN_CHANGE && LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) SideDefPointer->Data [CurrentLeftDef].Y = GetDlgItemInt (hWndDlg,wParam,&Trans,TRUE); break; case 14: // Clear Above. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { strcpy (SideDefPointer->Data [CurrentLeftDef].Above,"-"); SetDlgItemText (hWndDlg,13,"-"); } break; case 15: // Set Above. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { SendDlgItemMessage (hWndDlg,10,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SideDefPointer->Data [CurrentLeftDef].Above,Text,8); SetDlgItemText (hWndDlg,13,Text); } break; case 17: // Clear wall. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { strcpy (SideDefPointer->Data [CurrentLeftDef].Wall,"-"); SetDlgItemText (hWndDlg,16,"-"); } break; case 18: // Set wall. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { SendDlgItemMessage (hWndDlg,10,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SideDefPointer->Data [CurrentLeftDef].Wall,Text,8); SetDlgItemText (hWndDlg,16,Text); } break; case 20: // Clear Below. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { strcpy (SideDefPointer->Data [CurrentLeftDef].Below,"-"); SetDlgItemText (hWndDlg,19,"-"); } break; case 21: // Set Below. if (LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) { SendDlgItemMessage (hWndDlg,10,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,10,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SideDefPointer->Data [CurrentLeftDef].Below,Text,8); SetDlgItemText (hWndDlg,19,Text); } break; } } } break; default: return FALSE; } return TRUE; } BOOL FAR PASCAL LineDefProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_INITDIALOG: { fstream InActivityFile; char Buffer [BUFFER_SIZE]; char Text [BUFFER_SIZE]; int LineType; char * CopyFrom; // Load info into the special dialog box. InActivityFile.open ("GDREDIT.INI",ios::in|ios::nocreate); if (!InActivityFile.fail ()) { // Get to the start of the section we want. do { InActivityFile.getline (Buffer,BUFFER_SIZE); } while (!InActivityFile.eof () && strcmp (Buffer,"[LINETYPES]") != 0); InActivityFile.getline (Buffer,BUFFER_SIZE); while (!InActivityFile.eof () && Buffer [0] != '[') { if (strlen (Buffer) > 0) { LineType = atoi (Buffer); CopyFrom = strstr (Buffer,","); if (CopyFrom != NULL) strcpy (Text,CopyFrom + 1); SendDlgItemMessage (hWndDlg,10,CB_SETITEMDATA,(WORD) SendDlgItemMessage (hWndDlg,10,CB_ADDSTRING,0,(LONG) Text),(LONG) LineType); } InActivityFile.getline (Buffer,BUFFER_SIZE); } InActivityFile.close (); } SendDlgItemMessage (hWndDlg,10,CB_SETCURSEL,0,0); } break; case REDRAW_MESSAGE: // Update the window. { int Loop; int Finished = FALSE; int Entry = -1; int MaxTypes; // Update our display. if (LineDefPointer && CurrentLineDef >= 0) { // Set up the line type item. MaxTypes = (int) SendDlgItemMessage (hWndDlg,10,CB_GETCOUNT,0,0); Loop = -1; do { Loop++; if (SendDlgItemMessage (hWndDlg,10,CB_GETITEMDATA,Loop,0) == LineDefPointer->Data [CurrentLineDef].Types) { Finished = TRUE; Entry = Loop; } } while (!Finished && Loop < MaxTypes); SendDlgItemMessage (hWndDlg,10,CB_SETCURSEL,Entry,0); // Set up the bitsets. CheckDlgButton (hWndDlg,11,LineDefPointer->Data [CurrentLineDef].Bitset & 1); CheckDlgButton (hWndDlg,12,LineDefPointer->Data [CurrentLineDef].Bitset & 2); CheckDlgButton (hWndDlg,13,LineDefPointer->Data [CurrentLineDef].Bitset & 4); CheckDlgButton (hWndDlg,14,LineDefPointer->Data [CurrentLineDef].Bitset & 8); CheckDlgButton (hWndDlg,15,LineDefPointer->Data [CurrentLineDef].Bitset & 16); CheckDlgButton (hWndDlg,16,LineDefPointer->Data [CurrentLineDef].Bitset & 32); CheckDlgButton (hWndDlg,17,LineDefPointer->Data [CurrentLineDef].Bitset & 64); CheckDlgButton (hWndDlg,18,LineDefPointer->Data [CurrentLineDef].Bitset & 128); CheckDlgButton (hWndDlg,19,LineDefPointer->Data [CurrentLineDef].Bitset & 256); // Set up the edit fields. SetDlgItemInt (hWndDlg,20,LineDefPointer->Data [CurrentLineDef].Trigger,TRUE); // Set up the sidedefs. CurrentRightDef = LineDefPointer->Data [CurrentLineDef].Sidedef1; CurrentLeftDef = LineDefPointer->Data [CurrentLineDef].Sidedef2; SendMessage (hWndSideDef,REDRAW_MESSAGE,0,0L); } } break; case WM_COMMAND: { int Trans; if (LineDefPointer && CurrentLineDef >= 0) { switch (wParam) { case 1: // Ok button. ShowWindow (hWndLineDef,SW_HIDE); break; case 10: // Line type changed. if (HIWORD (lParam) == CBN_SELCHANGE) LineDefPointer->Data [CurrentLineDef].Types = (int) SendDlgItemMessage (hWndDlg,wParam,CB_GETITEMDATA,(WORD) SendDlgItemMessage (hWndDlg,wParam,CB_GETCURSEL,0,0),0); break; case 11: // Impassable line. case 12: // Monsters can't cross. case 13: // Two sided. case 14: // Above unpegged. case 15: // Below unpegged. case 16: // Secret wall. case 17: // Soundproof wall. case 18: // Unmappable. case 19: // Mapped at start of game. { int Toggle = 1 << (wParam - 11); // We can toggle the state of the bitset by use of // some maths. if (LineDefPointer->Data [CurrentLineDef].Bitset & Toggle) LineDefPointer->Data [CurrentLineDef].Bitset -= Toggle; else LineDefPointer->Data [CurrentLineDef].Bitset += Toggle; } break; case 20: // Trigger. if (HIWORD (lParam) == EN_CHANGE) LineDefPointer->Data [CurrentLineDef].Trigger = GetDlgItemInt (hWndDlg,wParam,&Trans,TRUE); break; case 21: // Edit the sidedefs. ShowWindow (hWndSideDef,SW_SHOW); break; } } } break; default: return FALSE; } return TRUE; } LONG FAR PASCAL LineDefEdit (HWND hWnd, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_LBUTTONDOWN: { int Result; HDC DC; if (LineDefAddMode) { if (LineDefPointer) { // Add new linedefs. FromVertex = ToVertex; ToVertex = FindThatVertex (LOWORD (lParam),HIWORD (lParam)); if (FromVertex >= 0 && ToVertex >= 0) { // We got one! Add it on. CurrentLineDef = LineDefPointer->Add (FromVertex,ToVertex); if (CurrentLineDef >= 0) { DC = GetDC (hWndMain); SelectObject (DC,RedPen); DrawLineDef (DC,CurrentLineDef); SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); } } } } else { // Change the selected linedef. Result = FindThatLineDef (LOWORD (lParam),HIWORD (lParam)); if (Result != -1) { HDC DC; // Set up for some drawing. DC = GetDC (hWndMain); // Erase old highlighted linedef. if (CurrentLineDef >= 0) { SelectObject (DC,YellowPen); DrawLineDef (DC,CurrentLineDef); } // Draw the new linedef. CurrentLineDef = Result; SelectObject (DC,RedPen); DrawLineDef (DC,CurrentLineDef); // Clean up after drawing. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); SendMessage (hWndLineDef,REDRAW_MESSAGE,0,0L); } } } break; case WM_LBUTTONDBLCLK: ShowWindow (hWndLineDef,SW_SHOW); break; case ADD_MESSAGE: { HDC DC; // Set up for the line drawing. LineDefAddMode = TRUE; LastLineDef = CurrentLineDef; FromVertex = -1; ToVertex = -1; // Erase old highlighted linedef if it exists. if (CurrentLineDef >= 0) { DC = GetDC (hWndMain); SelectObject (DC,YellowPen); DrawLineDef (DC,CurrentLineDef); SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); } } break; case WM_RBUTTONDOWN: // Add mode off. { HDC DC; int Loop; // Set up for some drawing. DC = GetDC (hWndMain); // Remove red pen highlights except for the last item. SelectObject (DC,YellowPen); if (LastLineDef >= 0) { for (Loop = LastLineDef;Loop < LineDefPointer->NoOfObjects - 1;Loop++) DrawLineDef (DC,Loop); } // Clean up after drawing. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); LineDefAddMode = FALSE; LastLineDef = -1; } break; case DELETE_MESSAGE: if (CurrentLineDef >= 0) { HDC DC; // Setup time. DC = GetDC (hWndMain); // Erase and delete the current linedef. SelectObject (DC,BluePen); DrawLineDef (DC,CurrentLineDef); LineDefPointer->Delete (CurrentLineDef); // We can switch to another line now. CurrentLineDef--; if (CurrentLineDef < 0) CurrentLineDef = LineDefPointer->NoOfObjects - 1; // Highlight the linedef we switched to. if (CurrentLineDef >= 0) { SelectObject (DC,RedPen); DrawLineDef (DC,CurrentLineDef); } // Clean up. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); } break; default: return DefWindowProc (hWnd,Message,wParam,lParam); } return 0L; } // ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» // º Sector Editing º // º º // º The edit procedure makes heavy use of the "ObjectList" to store the º // º lines for the current sector. Be sure this list always contains the º // º correct information. º // ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ BOOL FAR PASCAL SectorProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_INITDIALOG: { fstream InActivityFile; char Buffer [BUFFER_SIZE]; char Text [BUFFER_SIZE]; int ItemType; char * CopyFrom; int Loop; int Add = FALSE; // Load info into the special dialog box. InActivityFile.open ("GDREDIT.INI",ios::in|ios::nocreate); if (!InActivityFile.fail ()) { // Get to the start of the section we want. do { InActivityFile.getline (Buffer,BUFFER_SIZE); } while (!InActivityFile.eof () && strcmp (Buffer,"[SPECIAL]") != 0); InActivityFile.getline (Buffer,BUFFER_SIZE); while (!InActivityFile.eof () && Buffer [0] != '[') { if (strlen (Buffer) > 0) { ItemType = atoi (Buffer); CopyFrom = strstr (Buffer,","); if (CopyFrom != NULL) strcpy (Text,CopyFrom + 1); SendDlgItemMessage (hWndDlg,16,CB_SETITEMDATA,(WORD) SendDlgItemMessage (hWndDlg,16,CB_ADDSTRING,0,(LONG) Text),(LONG) ItemType); } InActivityFile.getline (Buffer,BUFFER_SIZE); } InActivityFile.close (); } // Load the floor and ceiling textures. Text [8] = '\000'; for (Loop = 0;Loop < DoomHeader.NumberOfEntries;Loop++) { if (strncmp (DoomDirectory [Loop].ResourceName,"F_END",8) == 0) Add = FALSE; if (Add && strncmp (DoomDirectory [Loop].ResourceName,"F1",2) != 0 && strncmp (DoomDirectory [Loop].ResourceName,"F2",2) != 0) { strncpy (Text,DoomDirectory [Loop].ResourceName,8); SendDlgItemMessage (hWndDlg,14,CB_ADDSTRING,0,(LONG) Text); SendDlgItemMessage (hWndDlg,15,CB_ADDSTRING,0,(LONG) Text); } if (strncmp (DoomDirectory [Loop].ResourceName,"F_START",8) == 0) Add = TRUE; } SendDlgItemMessage (hWndDlg,10,CB_SETCURSEL,0,0); } break; case REDRAW_MESSAGE: // Update the window. { int Loop; int Finished = FALSE; int Entry = -1; char Text [20]; int MaxTypes; // Update our display. if (SectorPointer && CurrentSector >= 0) { // Set up the special item. MaxTypes = (int) SendDlgItemMessage (hWndDlg,16,CB_GETCOUNT,0,0); Loop = -1; do { Loop++; if (SendDlgItemMessage (hWndDlg,16,CB_GETITEMDATA,Loop,0) == SectorPointer->Data [CurrentSector].Special) { Finished = TRUE; Entry = Loop; } } while (!Finished && Loop < MaxTypes); SendDlgItemMessage (hWndDlg,16,CB_SETCURSEL,Entry,0); // Set up the edit fields. SetDlgItemInt (hWndDlg,10,SectorPointer->Data [CurrentSector].FloorHeight,TRUE); SetDlgItemInt (hWndDlg,11,SectorPointer->Data [CurrentSector].CeilingHeight,TRUE); SetDlgItemInt (hWndDlg,12,SectorPointer->Data [CurrentSector].Brightness,TRUE); SetDlgItemInt (hWndDlg,13,SectorPointer->Data [CurrentSector].Trigger,TRUE); // Now set the list boxes. Text [8] = '\000'; strncpy (Text,SectorPointer->Data [CurrentSector].FloorTexture,8); Entry = (int) SendDlgItemMessage (hWndDlg,14,CB_FINDSTRING,0,(LONG) Text); SendDlgItemMessage (hWndDlg,14,CB_SETCURSEL,Entry,0); strncpy (Text,SectorPointer->Data [CurrentSector].CeilingTexture,8); Entry = (int) SendDlgItemMessage (hWndDlg,15,CB_FINDSTRING,0,(LONG) Text); SendDlgItemMessage (hWndDlg,15,CB_SETCURSEL,Entry,0); } } break; case WM_COMMAND: { int Trans; char Text [20]; if (SectorPointer && CurrentSector >= 0) { switch (wParam) { case 10: // Floor Height. if (HIWORD (lParam) == EN_CHANGE) SectorPointer->Data [CurrentSector].FloorHeight = GetDlgItemInt (hWndDlg,10,&Trans,TRUE); break; case 11: // Ceiling Height. if (HIWORD (lParam) == EN_CHANGE) SectorPointer->Data [CurrentSector].CeilingHeight = GetDlgItemInt (hWndDlg,11,&Trans,TRUE); break; case 12: // Sector brightness changed. if (HIWORD (lParam) == EN_CHANGE) SectorPointer->Data [CurrentSector].Brightness = GetDlgItemInt (hWndDlg,12,&Trans,TRUE); break; case 13: // Trigger has changed. if (HIWORD (lParam) == EN_CHANGE) SectorPointer->Data [CurrentSector].Trigger = GetDlgItemInt (hWndDlg,13,&Trans,TRUE); break; case 14: // Floor texture has changed. if (HIWORD (lParam) == CBN_SELCHANGE) { SendDlgItemMessage (hWndDlg,14,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,14,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SectorPointer->Data [CurrentSector].FloorTexture,Text,8); } break; case 15: // Ceiling texture has changed. if (HIWORD (lParam) == CBN_SELCHANGE) { SendDlgItemMessage (hWndDlg,15,CB_GETLBTEXT,(WORD) SendDlgItemMessage (hWndDlg,15,CB_GETCURSEL,0,0),(LONG) Text); strncpy (SectorPointer->Data [CurrentSector].CeilingTexture,Text,8); } break; case 16: // Special info changed. if (HIWORD (lParam) == CBN_SELCHANGE) SectorPointer->Data [CurrentSector].Special = (int) SendDlgItemMessage (hWndDlg,16,CB_GETITEMDATA,(WORD) SendDlgItemMessage (hWndDlg,16,CB_GETCURSEL,0,0),0); break; } } } break; default: return FALSE; } return TRUE; } LONG FAR PASCAL SectorEdit (HWND hWnd, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_LBUTTONDOWN: { int Result; int Loop; if (SectorAddMode) { if (LineDefPointer) { // Add new linedefs. FromVertex = ToVertex; ToVertex = FindThatVertex (LOWORD (lParam),HIWORD (lParam)); if (FromVertex >= 0 && ToVertex >= 0) { HDC DC; // Set up for some drawing. DC = GetDC (hWndMain); SelectObject (DC,RedPen); // Check for a linedef. for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) { // Place the sector on the right sidedef. if ((LineDefPointer->Data [Loop].FromVertex == FromVertex) && (LineDefPointer->Data [Loop].ToVertex == ToVertex)) { // Select this line and display. CurrentLineDef = Loop; DrawLineDef (DC,CurrentLineDef); // Create a new sidedef if needed. if (LineDefPointer->Data [Loop].Sidedef1 < 0) LineDefPointer->Data [Loop].Sidedef1 = SideDefPointer->Add (); SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef1].Sector = CurrentSector; } // Place the sector on the left sidedef. if ((LineDefPointer->Data [Loop].ToVertex == FromVertex) && (LineDefPointer->Data [Loop].FromVertex == ToVertex)) { // Select this line and display. CurrentLineDef = Loop; DrawLineDef (DC,CurrentLineDef); // Create a new sidedef if needed. if (LineDefPointer->Data [Loop].Sidedef2 < 0) LineDefPointer->Data [Loop].Sidedef2 = SideDefPointer->Add (); SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef2].Sector = CurrentSector; } } // Clean up after drawing. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); } } } else { Result = FindThatLineDef (LOWORD (lParam),HIWORD (lParam)); if (Result != -1) { HDC DC; // Set up for some drawing. DC = GetDC (hWndMain); // Get ready to update the dialog. CurrentLineDef = Result; if (CurrentLineDef == LastLineDef) if (UseSide1 && LineDefPointer->Data [CurrentLineDef].Sidedef2 >= 0) UseSide1 = FALSE; else UseSide1 = TRUE; else UseSide1 = TRUE; // Select the sector from the linedef. if (UseSide1) CurrentSector = SideDefPointer->Data [LineDefPointer->Data [CurrentLineDef].Sidedef1].Sector; else CurrentSector = SideDefPointer->Data [LineDefPointer->Data [CurrentLineDef].Sidedef2].Sector; SendMessage (hWndSector,REDRAW_MESSAGE,0,0L); // Erase the sector. if (SectorOn) { SelectObject (DC,YellowPen); for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); } // Possible for no sector to be defined for a linedef. if (CurrentSector >= 0) { SectorOn = TRUE; NoOfListObjects = 0; SelectObject (DC,RedPen); for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) { // Right hand sides. These MUST exist for each linedef. if (SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef1].Sector == CurrentSector) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } // Left hand sides are optional. if (LineDefPointer->Data [Loop].Sidedef2 >= 0) { if (SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef2].Sector == CurrentSector) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } } } // Draw the sector. for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); } // Clean up after drawing. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); LastLineDef = CurrentLineDef; } } } break; case ADD_MESSAGE: { HDC DC; int Loop; // Set up for some drawing. DC = GetDC (hWndMain); // Erase the current sector. if (CurrentSector >= 0) { SelectObject (DC,YellowPen); for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); } // Add the sector and prepare to draw the lines. CurrentSector = SectorPointer->Add (); SectorAddMode = TRUE; FromVertex = -1; ToVertex = -1; // Clean up after drawing. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); } break; case WM_RBUTTONDOWN: // Add mode off. { int Loop; // Turn off the useful globals. SectorAddMode = FALSE; // We want to update the list for the new sector to be erased. if (CurrentSector >= 0) { SectorOn = TRUE; NoOfListObjects = 0; for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) { // Right hand sides. These MUST exist for each linedef. if (SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef1].Sector == CurrentSector) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } // Left hand sides are optional. if (LineDefPointer->Data [Loop].Sidedef2 >= 0) { if (SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef2].Sector == CurrentSector) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } } } } } break; case DELETE_MESSAGE: if (CurrentSector >= 0) { HDC DC; int Loop; // Setup time. DC = GetDC (hWndMain); // Erase the sector. SelectObject (DC,YellowPen); for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); SectorPointer->Delete (CurrentSector); NoOfListObjects = 0; // Switch to the next sector. CurrentSector--; if (CurrentSector < 0) CurrentSector = SectorPointer->NoOfObjects - 1; CurrentLineDef = -1; LastLineDef = -1; // Draw the next sector if it exists. if (CurrentSector >= 0) { // Work out who appears in the new sector. for (Loop = 0;Loop < LineDefPointer->NoOfObjects;Loop++) { // Right hand sides. These MUST exist for each linedef. if (SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef1].Sector == CurrentSector) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } // Left hand sides are optional. if (LineDefPointer->Data [Loop].Sidedef2 >= 0) { if (SideDefPointer->Data [LineDefPointer->Data [Loop].Sidedef2].Sector == CurrentSector) { ObjectList [NoOfListObjects] = Loop; NoOfListObjects++; } } } // Draw the lines. SelectObject (DC,RedPen); for (Loop = 0;Loop < NoOfListObjects;Loop++) DrawLineDef (DC,ObjectList [Loop]); } // Clean up. SelectObject (DC,GetStockObject (BLACK_PEN)); ReleaseDC (hWndMain,DC); SendMessage (hWndSector,REDRAW_MESSAGE,0,0L); } break; default: return DefWindowProc (hWnd,Message,wParam,lParam); } return 0L; } // ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» // º Main Program Code º // º º // º This controls the main application. Here we take care of the main º // º menu, changing the check buttons and switching between various edit º // º modes. The rest is boilerplate windows app. º // ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ LONG FAR PASCAL WndProc (HWND hWnd, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_CREATE: if (GridSnap) { CheckMenuItem (GetMenu (hWnd),204,MF_CHECKED); GridSnap = TRUE; } break; case WM_COMMAND: switch (wParam) { case 100: // File new. NewWadFile (); break; case 101: // File open dialog. LoadWadFile (); break; case 102: // File save dialog. if (Registered) { if (strlen (FileName) == 0) SaveWadFile (); else WriteWadFile (FileName); } break; case 103: // File save as dialog. if (Registered) SaveWadFile (); break; case 104: // Exit program. DestroyWindow (hWnd); PostQuitMessage (0); break; case 200: // Thing Editor. if (EditMode != THING_EDIT) { CheckMenuItem (GetMenu (hWnd),wParam,MF_CHECKED); CheckMenuItem (GetMenu (hWnd),201,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),202,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),203,MF_UNCHECKED); ShowWindow (hWndSector,SW_HIDE); ShowWindow (hWndLineDef,SW_HIDE); ShowWindow (hWndSideDef,SW_HIDE); ShowWindow (hWndThing,SW_SHOW); InvalidateRect (hWndMain,NULL,TRUE); EditMode = THING_EDIT; } break; case 201: // Vertex Editor. if (EditMode != VERTEX_EDIT) { CheckMenuItem (GetMenu (hWnd),wParam,MF_CHECKED); CheckMenuItem (GetMenu (hWnd),200,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),202,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),203,MF_UNCHECKED); ShowWindow (hWndThing,SW_HIDE); ShowWindow (hWndSector,SW_HIDE); ShowWindow (hWndLineDef,SW_HIDE); ShowWindow (hWndSideDef,SW_HIDE); InvalidateRect (hWndMain,NULL,TRUE); EditMode = VERTEX_EDIT; } break; case 202: // Linedef Editor. if (EditMode != LINEDEF_EDIT) { CheckMenuItem (GetMenu (hWnd),wParam,MF_CHECKED); CheckMenuItem (GetMenu (hWnd),200,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),201,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),203,MF_UNCHECKED); ShowWindow (hWndThing,SW_HIDE); ShowWindow (hWndSector,SW_HIDE); ShowWindow (hWndLineDef,SW_HIDE); ShowWindow (hWndSideDef,SW_HIDE); InvalidateRect (hWndMain,NULL,TRUE); EditMode = LINEDEF_EDIT; } break; case 203: // Sector Editor. if (EditMode != SECTOR_EDIT) { CheckMenuItem (GetMenu (hWnd),wParam,MF_CHECKED); CheckMenuItem (GetMenu (hWnd),200,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),201,MF_UNCHECKED); CheckMenuItem (GetMenu (hWnd),202,MF_UNCHECKED); ShowWindow (hWndThing,SW_HIDE); ShowWindow (hWndLineDef,SW_HIDE); ShowWindow (hWndSideDef,SW_HIDE); ShowWindow (hWndSector,SW_SHOW); InvalidateRect (hWndMain,NULL,TRUE); EditMode = SECTOR_EDIT; } break; case 204: // Gridsnap. if (!GridSnap) { CheckMenuItem (GetMenu (hWnd),wParam,MF_CHECKED); GridSnap = TRUE; } else { CheckMenuItem (GetMenu (hWnd),wParam,MF_UNCHECKED); GridSnap = FALSE; } break; default: return DefWindowProc (hWnd,Message,wParam,lParam); } break; case WM_CLOSE: DestroyWindow (hWnd); PostQuitMessage (0); break; case WM_PAINT: { PAINTSTRUCT PS; HDC DC; DC = BeginPaint (hWnd,&PS); PaintIt (DC); EndPaint (hWnd,&PS); } break; default: switch (EditMode) { case THING_EDIT: return ThingEdit (hWnd,Message,wParam,lParam); break; case VERTEX_EDIT: return VertexEdit (hWnd,Message,wParam,lParam); break; case SECTOR_EDIT: return SectorEdit (hWnd,Message,wParam,lParam); break; case LINEDEF_EDIT: return LineDefEdit (hWnd,Message,wParam,lParam); break; default: return DefWindowProc (hWnd,Message,wParam,lParam); } } return 0L; } BOOL FAR PASCAL CheapProc (HWND hWndDlg, WORD Message, WORD wParam, LONG lParam) { switch (Message) { case WM_CLOSE: PostMessage (hWndDlg,WM_COMMAND,IDCANCEL,0L); break; case WM_COMMAND: switch (wParam) { case IDOK: EndDialog (hWndDlg,TRUE); break; case IDCANCEL: EndDialog (hWndDlg,FALSE); break; } break; default: return FALSE; } return TRUE; } int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; WNDCLASS wndclass; int FileHandle; FARPROC lpfnButtonBarMsgProc; FARPROC lpfnThingProc; FARPROC lpfnSectorProc; FARPROC lpfnLineDefProc; FARPROC lpfnSideDefProc; char Text [20]; int Loop; hInst = hInstance; // Create some pens. More efficient this way. YellowPen = CreatePen (PS_SOLID,1,YELLOW_COLOUR); RedPen = CreatePen (PS_SOLID,1,RED_COLOUR); BluePen = CreatePen (PS_SOLID,1,BLUE_COLOUR); RedBrush = CreateSolidBrush (RED_COLOUR); BlueBrush = CreateSolidBrush (BLUE_COLOUR); // Read our configuration information. GetPrivateProfileString (SECTION_NAME,"DoomDirectory","C:\\DOOM",DoomWadPath,sizeof (DoomWadPath),PROFILE_FILE); sprintf (DoomWadName,"%s\\DOOM.WAD",DoomWadPath); GridSnap = GetPrivateProfileInt (SECTION_NAME,"GridSnap",32,PROFILE_FILE); GridSize = GetPrivateProfileInt (SECTION_NAME,"GridSize",32,PROFILE_FILE); // Register the window class. if (!hPrevInstance) { // Register window classes if first instance of application. memset (&wndclass,0x00,sizeof (WNDCLASS)); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW | CS_DBLCLKS; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInst; wndclass.hIcon = LoadIcon (hInst,"MAIN_ICON"); wndclass.hCursor = LoadCursor (NULL,IDC_ARROW); wndclass.hbrBackground = BlueBrush; wndclass.lpszMenuName = "MAIN_MENU"; wndclass.lpszClassName = MainClassName; RegisterClass (&wndclass); } // Main window. hWndMain = CreateWindow ( MainClassName, /* Window class name */ "GDR Doom Thing Editor",/* Window's title */ WS_CAPTION | /* Title and Min/Max */ WS_SYSMENU | /* Add system menu box */ WS_MINIMIZEBOX | /* Add minimize box */ WS_MAXIMIZEBOX | /* Add maximize box */ WS_THICKFRAME | /* thick sizeable frame */ WS_CLIPCHILDREN | /* don't draw in child windows areas */ WS_OVERLAPPED, CW_USEDEFAULT, 0, /* Use default X, Y */ CW_USEDEFAULT, 0, /* Use default X, Y */ NULL, /* Parent window's handle */ NULL, /* Default to Class Menu */ hInst, /* Instance of window */ NULL); /* Create struct for WM_CREATE */ if (hWndMain == NULL) { MessageBox (NULL,"Unable to create the main window.",NULL,MB_ICONEXCLAMATION); return -1; } // Read in the DOOM.WAD stuff for wall patches and the like. FileHandle = open (DoomWadName,O_BINARY|O_RDONLY); read (FileHandle,&DoomHeader,sizeof (Header)); DoomDirectory = new DirectoryEntry [DoomHeader.NumberOfEntries]; lseek (FileHandle,DoomHeader.DirectoryPointer,SEEK_SET); lread (FileHandle,DoomDirectory,sizeof (DirectoryEntry) * DoomHeader.NumberOfEntries); close (FileHandle); // Check for registered version. for (Loop = 0;Loop < DoomHeader.NumberOfEntries;Loop++) if (strncmp (DoomDirectory [Loop].ResourceName,"E2M2",8) == 0) Registered = TRUE; // Cheapskate message. if (!Registered) { FARPROC MsgProc; MsgProc = MakeProcInstance ((FARPROC) CheapProc,hInst); DialogBox (hInst,(LPSTR) "CHEAP_BUGGERS",hWndMain,MsgProc); FreeProcInstance (MsgProc); } // Create the button bar dialog box. lpfnButtonBarMsgProc = MakeProcInstance ((FARPROC) ButtonBarMsgProc,hInst); hWndButtonBar = CreateDialog (hInst,(LPSTR) "BUTTON_BAR",hWndMain,lpfnButtonBarMsgProc); // Create the thing dialog box. lpfnThingProc = MakeProcInstance ((FARPROC) ThingProc,hInst); hWndThing = CreateDialog (hInst,(LPSTR) "THING_EDITOR",hWndMain,lpfnThingProc); // Create the sector dialog box. lpfnSectorProc = MakeProcInstance ((FARPROC) SectorProc,hInst); hWndSector = CreateDialog (hInst,(LPSTR) "SECTOR_EDITOR",hWndMain,lpfnSectorProc); // Create the linedef dialog box. lpfnLineDefProc = MakeProcInstance ((FARPROC) LineDefProc,hInst); hWndLineDef = CreateDialog (hInst,(LPSTR) "LINEDEF_EDITOR",hWndMain,lpfnLineDefProc); // Create the sidedef dialog box. lpfnSideDefProc = MakeProcInstance ((FARPROC) SideDefProc,hInst); hWndSideDef = CreateDialog (hInst,(LPSTR) "SIDEDEF_EDITOR",hWndMain,lpfnSideDefProc); ShowWindow (hWndMain,SW_SHOWMAXIMIZED); while (GetMessage (&msg,NULL,0,0)) { if (!IsDialogMessage (hWndThing,&msg) && !IsDialogMessage (hWndButtonBar,&msg) && !IsDialogMessage (hWndSector,&msg)) { TranslateMessage (&msg); DispatchMessage (&msg); } } // Remove our button bar from existence. DestroyWindow (hWndButtonBar); FreeProcInstance (lpfnButtonBarMsgProc); // Remove our thing dialog from existence. DestroyWindow (hWndThing); FreeProcInstance (lpfnThingProc); // Remove our sector dialog from existence. DestroyWindow (hWndSector); FreeProcInstance (lpfnSectorProc); // Remove our linedef dialog from existence. DestroyWindow (hWndLineDef); FreeProcInstance (lpfnLineDefProc); // Remove our linedef dialog from existence. DestroyWindow (hWndSideDef); FreeProcInstance (lpfnSideDefProc); // Delete our pens. DeleteObject (YellowPen); DeleteObject (RedPen); DeleteObject (BluePen); DeleteObject (BlueBrush); DeleteObject (RedBrush); // Write our configuration information. sprintf (Text,"%d",GridSnap); WritePrivateProfileString (SECTION_NAME,"GridSnap",Text,PROFILE_FILE); sprintf (Text,"%d",GridSize); WritePrivateProfileString (SECTION_NAME,"GridSize",Text,PROFILE_FILE); // Clean up before exiting from the application. UnregisterClass (MainClassName,hInst); UnloadWadFile (); return msg.wParam; }