home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
WADS of WADS
/
WadsOfWads.1994.zip
/
ZIPS
/
A_D
/
DMGDR.ZIP
/
GDREDIT.CPP
< prev
next >
Wrap
Text File
|
1994-07-25
|
78KB
|
2,549 lines
#include "doom.h"
#include "gdredit.h"
#include <mem.h>
#include <stdio.h>
#include <commdlg.h>
#include <io.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <fstream.h>
#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;
}