aboutsummaryrefslogtreecommitdiffstats
path: root/q3radiant
diff options
context:
space:
mode:
authorzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 04:48:05 +0000
committerzakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea>2005-08-26 04:48:05 +0000
commit952c5c128f9efaea89d41d882c4ea3ade7df4591 (patch)
tree91b84d9be7afad7e99ac64a640a65b6cb5081900 /q3radiant
parentc2c2e0d25d6cdb7d42d7dc981a863f65f94f281d (diff)
downloadioquake3-aero-952c5c128f9efaea89d41d882c4ea3ade7df4591.tar.gz
ioquake3-aero-952c5c128f9efaea89d41d882c4ea3ade7df4591.zip
Itsa me, quake3io!
git-svn-id: svn://svn.icculus.org/quake3/trunk@2 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'q3radiant')
-rwxr-xr-xq3radiant/BMP.H101
-rwxr-xr-xq3radiant/BRUSH.H124
-rwxr-xr-xq3radiant/BSInput.cpp115
-rwxr-xr-xq3radiant/BSInput.h76
-rwxr-xr-xq3radiant/BSPFILE.H379
-rwxr-xr-xq3radiant/Bmp.cpp417
-rwxr-xr-xq3radiant/Brush.cpp4595
-rwxr-xr-xq3radiant/BrushScript.cpp672
-rwxr-xr-xq3radiant/CAMERA.H51
-rwxr-xr-xq3radiant/CSG.CPP686
-rwxr-xr-xq3radiant/CamWnd.cpp1165
-rwxr-xr-xq3radiant/CamWnd.h120
-rwxr-xr-xq3radiant/CapDialog.cpp64
-rwxr-xr-xq3radiant/CapDialog.h69
-rwxr-xr-xq3radiant/CharBuffer.h109
-rwxr-xr-xq3radiant/ChildFrm.cpp86
-rwxr-xr-xq3radiant/ChildFrm.h73
-rwxr-xr-xq3radiant/CommandsDlg.cpp109
-rwxr-xr-xq3radiant/CommandsDlg.h67
-rwxr-xr-xq3radiant/DRAG.CPP828
-rwxr-xr-xq3radiant/DialogInfo.cpp94
-rwxr-xr-xq3radiant/DialogInfo.h69
-rwxr-xr-xq3radiant/DialogTextures.cpp89
-rwxr-xr-xq3radiant/DialogTextures.h69
-rwxr-xr-xq3radiant/DialogThick.cpp66
-rwxr-xr-xq3radiant/DialogThick.h68
-rwxr-xr-xq3radiant/DlgEvent.cpp65
-rwxr-xr-xq3radiant/DlgEvent.h69
-rwxr-xr-xq3radiant/ECLASS.CPP932
-rwxr-xr-xq3radiant/ENTITY.CPP933
-rwxr-xr-xq3radiant/ENTITY.H76
-rwxr-xr-xq3radiant/ENTITYW.H68
-rwxr-xr-xq3radiant/EPAIRS.H1402
-rwxr-xr-xq3radiant/EditWnd.cpp61
-rwxr-xr-xq3radiant/EditWnd.h71
-rwxr-xr-xq3radiant/EntityListDlg.cpp152
-rwxr-xr-xq3radiant/EntityListDlg.h72
-rwxr-xr-xq3radiant/EpairsWrapper.h63
-rwxr-xr-xq3radiant/FNMATCH.CPP87
-rwxr-xr-xq3radiant/FNMATCH.H27
-rwxr-xr-xq3radiant/FindTextureDlg.cpp175
-rwxr-xr-xq3radiant/FindTextureDlg.h83
-rwxr-xr-xq3radiant/GLINGR.H97
-rwxr-xr-xq3radiant/GLInterface.cpp93
-rwxr-xr-xq3radiant/GLW_WIN.H49
-rwxr-xr-xq3radiant/GroupBar.cpp84
-rwxr-xr-xq3radiant/GroupBar.h69
-rwxr-xr-xq3radiant/GroupDlg.cpp655
-rwxr-xr-xq3radiant/GroupDlg.h90
-rwxr-xr-xq3radiant/IBSPFrontend.h101
-rwxr-xr-xq3radiant/ICON1.ICObin0 -> 766 bytes
-rwxr-xr-xq3radiant/IEpairs.cpp185
-rwxr-xr-xq3radiant/IEpairs.h83
-rwxr-xr-xq3radiant/IMessaging.h119
-rwxr-xr-xq3radiant/IPluginEntities.h105
-rwxr-xr-xq3radiant/ISelectedFace.h113
-rwxr-xr-xq3radiant/IShaders.cpp86
-rwxr-xr-xq3radiant/IShaders.h79
-rwxr-xr-xq3radiant/LBMLIB.CPP1329
-rwxr-xr-xq3radiant/LBMLIB.H40
-rwxr-xr-xq3radiant/LstToolBar.cpp59
-rwxr-xr-xq3radiant/LstToolBar.h69
-rwxr-xr-xq3radiant/MAP.CPP1062
-rwxr-xr-xq3radiant/MAP.H59
-rwxr-xr-xq3radiant/MATHLIB.CPP311
-rwxr-xr-xq3radiant/MATHLIB.H86
-rwxr-xr-xq3radiant/MRU.CPP671
-rwxr-xr-xq3radiant/MRU.H100
-rwxr-xr-xq3radiant/MainFrm.cpp5224
-rwxr-xr-xq3radiant/MainFrm.h504
-rwxr-xr-xq3radiant/MapInfo.cpp114
-rwxr-xr-xq3radiant/MapInfo.h70
-rwxr-xr-xq3radiant/Messaging.cpp137
-rwxr-xr-xq3radiant/Messaging.h46
-rwxr-xr-xq3radiant/NameDlg.cpp79
-rwxr-xr-xq3radiant/NameDlg.h69
-rwxr-xr-xq3radiant/NewProjDlg.cpp64
-rwxr-xr-xq3radiant/NewProjDlg.h67
-rwxr-xr-xq3radiant/PARSE.CPP148
-rwxr-xr-xq3radiant/PARSE.H34
-rwxr-xr-xq3radiant/PMESH.CPP5136
-rwxr-xr-xq3radiant/PMESH.H21
-rwxr-xr-xq3radiant/POINTS.CPP156
-rwxr-xr-xq3radiant/PatchDensityDlg.cpp89
-rwxr-xr-xq3radiant/PatchDensityDlg.h69
-rwxr-xr-xq3radiant/PatchDialog.cpp354
-rwxr-xr-xq3radiant/PatchDialog.h102
-rwxr-xr-xq3radiant/PlugIn.cpp297
-rwxr-xr-xq3radiant/PlugIn.h82
-rwxr-xr-xq3radiant/PlugInManager.cpp1665
-rwxr-xr-xq3radiant/PlugInManager.h100
-rwxr-xr-xq3radiant/PluginEntities.cpp101
-rwxr-xr-xq3radiant/PrefsDlg.cpp578
-rwxr-xr-xq3radiant/PrefsDlg.h161
-rwxr-xr-xq3radiant/QE3.CPP751
-rwxr-xr-xq3radiant/QE3.H669
-rwxr-xr-xq3radiant/QEDEFS.H164
-rwxr-xr-xq3radiant/QERTYPES.H454
-rwxr-xr-xq3radiant/QFILES.H481
-rwxr-xr-xq3radiant/QGL.H456
-rwxr-xr-xq3radiant/QGL_WIN.C1230
-rwxr-xr-xq3radiant/QGL_WIN.CPP1520
-rwxr-xr-xq3radiant/RADBSP.CPP77
-rwxr-xr-xq3radiant/RADEditView.cpp84
-rwxr-xr-xq3radiant/RADEditView.h75
-rwxr-xr-xq3radiant/RADEditWnd.cpp75
-rwxr-xr-xq3radiant/RADEditWnd.h73
-rwxr-xr-xq3radiant/RADKEYS.INI67
-rwxr-xr-xq3radiant/Radiant.clw1957
-rwxr-xr-xq3radiant/Radiant.cpp261
-rwxr-xr-xq3radiant/Radiant.h71
-rwxr-xr-xq3radiant/Radiant.rc2838
-rwxr-xr-xq3radiant/Radiant.sln95
-rwxr-xr-xq3radiant/Radiant.vcproj3381
-rwxr-xr-xq3radiant/RadiantDoc.cpp105
-rwxr-xr-xq3radiant/RadiantDoc.h78
-rwxr-xr-xq3radiant/RadiantView.cpp126
-rwxr-xr-xq3radiant/RadiantView.h87
-rwxr-xr-xq3radiant/RotateDlg.cpp130
-rwxr-xr-xq3radiant/RotateDlg.h78
-rwxr-xr-xq3radiant/SELECT.CPP1800
-rwxr-xr-xq3radiant/SELECT.H91
-rwxr-xr-xq3radiant/ScaleDialog.cpp68
-rwxr-xr-xq3radiant/ScaleDialog.h69
-rwxr-xr-xq3radiant/ScriptDlg.cpp103
-rwxr-xr-xq3radiant/ScriptDlg.h70
-rwxr-xr-xq3radiant/SelectedFace.cpp136
-rwxr-xr-xq3radiant/ShaderEdit.cpp66
-rwxr-xr-xq3radiant/ShaderEdit.h70
-rwxr-xr-xq3radiant/ShaderInfo.cpp69
-rwxr-xr-xq3radiant/ShaderInfo.h55
-rwxr-xr-xq3radiant/StdAfx.cpp27
-rwxr-xr-xq3radiant/StdAfx.h154
-rwxr-xr-xq3radiant/SurfaceDlg.cpp983
-rwxr-xr-xq3radiant/SurfaceDlg.h107
-rwxr-xr-xq3radiant/SurfacePlugin.cpp82
-rwxr-xr-xq3radiant/TexEdit.cpp85
-rwxr-xr-xq3radiant/TexEdit.h76
-rwxr-xr-xq3radiant/TexWnd.cpp3186
-rwxr-xr-xq3radiant/TexWnd.h88
-rwxr-xr-xq3radiant/TextureBar.cpp208
-rwxr-xr-xq3radiant/TextureBar.h85
-rwxr-xr-xq3radiant/TextureLayout.cpp80
-rwxr-xr-xq3radiant/TextureLayout.h69
-rwxr-xr-xq3radiant/TextureLoad.cpp80
-rwxr-xr-xq3radiant/TextureLoad.h68
-rwxr-xr-xq3radiant/Textures.h96
-rwxr-xr-xq3radiant/ToolWnd.cpp55
-rwxr-xr-xq3radiant/ToolWnd.h68
-rwxr-xr-xq3radiant/Undo.cpp884
-rwxr-xr-xq3radiant/Undo.h64
-rwxr-xr-xq3radiant/VERTSEL.CPP372
-rwxr-xr-xq3radiant/VIEW.H53
-rwxr-xr-xq3radiant/WIN_CAM.CPP274
-rwxr-xr-xq3radiant/WIN_DLG.CPP616
-rwxr-xr-xq3radiant/WIN_QE3.CPP753
-rwxr-xr-xq3radiant/WIN_QE3.RC2693
-rwxr-xr-xq3radiant/WIN_XY.CPP310
-rwxr-xr-xq3radiant/WIN_Z.CPP192
-rwxr-xr-xq3radiant/WaveOpen.cpp98
-rwxr-xr-xq3radiant/WaveOpen.h58
-rwxr-xr-xq3radiant/Win_ent.cpp1411
-rwxr-xr-xq3radiant/Win_main.cpp1085
-rwxr-xr-xq3radiant/Winding.cpp817
-rwxr-xr-xq3radiant/Winding.h70
-rwxr-xr-xq3radiant/XY.H39
-rwxr-xr-xq3radiant/XYWnd.cpp3629
-rwxr-xr-xq3radiant/XYWnd.h219
-rwxr-xr-xq3radiant/Z.CPP431
-rwxr-xr-xq3radiant/Z.H42
-rwxr-xr-xq3radiant/ZView.cpp163
-rwxr-xr-xq3radiant/ZView.h83
-rwxr-xr-xq3radiant/ZWnd.cpp264
-rwxr-xr-xq3radiant/ZWnd.h90
-rwxr-xr-xq3radiant/brush_primit.cpp461
-rwxr-xr-xq3radiant/cameratargetdlg.cpp71
-rwxr-xr-xq3radiant/cameratargetdlg.h68
-rwxr-xr-xq3radiant/cbrushstub.cpp76
-rwxr-xr-xq3radiant/dlgcamera.cpp395
-rwxr-xr-xq3radiant/dlgcamera.h98
-rwxr-xr-xq3radiant/igl.h261
-rwxr-xr-xq3radiant/iscriplib.h87
-rwxr-xr-xq3radiant/isurfaceplugin.h216
-rwxr-xr-xq3radiant/qerplugin.h566
-rwxr-xr-xq3radiant/res/BEVEL.BMPbin0 -> 486 bytes
-rwxr-xr-xq3radiant/res/BITMAP2.BMPbin0 -> 614 bytes
-rwxr-xr-xq3radiant/res/BMP00001.BMPbin0 -> 614 bytes
-rwxr-xr-xq3radiant/res/BMP00002.BMPbin0 -> 4198 bytes
-rwxr-xr-xq3radiant/res/BMP0002.BMPbin0 -> 4078 bytes
-rwxr-xr-xq3radiant/res/DEFTEX.WALbin0 -> 5540 bytes
-rwxr-xr-xq3radiant/res/ENDCAP.BMPbin0 -> 486 bytes
-rwxr-xr-xq3radiant/res/IBEVEL.BMPbin0 -> 486 bytes
-rwxr-xr-xq3radiant/res/IENDCAP.BMPbin0 -> 486 bytes
-rwxr-xr-xq3radiant/res/Q.BMPbin0 -> 47936 bytes
-rwxr-xr-xq3radiant/res/RADIANT3.GIFbin0 -> 19737 bytes
-rwxr-xr-xq3radiant/res/Radiant.icobin0 -> 1078 bytes
-rwxr-xr-xq3radiant/res/Radiant.rc213
-rwxr-xr-xq3radiant/res/RadiantDoc.icobin0 -> 1078 bytes
-rwxr-xr-xq3radiant/res/TOOLBAR1.BMPbin0 -> 2878 bytes
-rwxr-xr-xq3radiant/res/TOOLBAR2.BMPbin0 -> 478 bytes
-rwxr-xr-xq3radiant/res/Toolbar.bmpbin0 -> 718 bytes
-rwxr-xr-xq3radiant/res/VIEWDEFA.BMPbin0 -> 614 bytes
-rwxr-xr-xq3radiant/res/VIEWOPPO.BMPbin0 -> 614 bytes
-rwxr-xr-xq3radiant/res/bmp00003.bmpbin0 -> 1014 bytes
-rwxr-xr-xq3radiant/res/icon2.icobin0 -> 766 bytes
-rwxr-xr-xq3radiant/res/logo_sm3dfx.bmpbin0 -> 4918 bytes
-rwxr-xr-xq3radiant/res/shaderbar.bmpbin0 -> 1198 bytes
-rwxr-xr-xq3radiant/res/shaderdoc.icobin0 -> 1078 bytes
-rwxr-xr-xq3radiant/res/shaderframe.icobin0 -> 1078 bytes
-rwxr-xr-xq3radiant/resource.h840
-rwxr-xr-xq3radiant/splines/Splines.vcproj296
-rwxr-xr-xq3radiant/splines/math_angles.cpp150
-rwxr-xr-xq3radiant/splines/math_angles.h195
-rwxr-xr-xq3radiant/splines/math_matrix.cpp134
-rwxr-xr-xq3radiant/splines/math_matrix.h223
-rwxr-xr-xq3radiant/splines/math_quaternion.cpp78
-rwxr-xr-xq3radiant/splines/math_quaternion.h190
-rwxr-xr-xq3radiant/splines/math_vector.cpp144
-rwxr-xr-xq3radiant/splines/math_vector.h572
-rwxr-xr-xq3radiant/splines/q_parse.cpp535
-rwxr-xr-xq3radiant/splines/q_shared.cpp976
-rwxr-xr-xq3radiant/splines/q_shared.h798
-rwxr-xr-xq3radiant/splines/splines.cpp1244
-rwxr-xr-xq3radiant/splines/splines.h1080
-rwxr-xr-xq3radiant/splines/util_list.h346
-rwxr-xr-xq3radiant/splines/util_str.cpp618
-rwxr-xr-xq3radiant/splines/util_str.h817
-rwxr-xr-xq3radiant/terrain.cpp1735
-rwxr-xr-xq3radiant/terrain.h75
229 files changed, 85603 insertions, 0 deletions
diff --git a/q3radiant/BMP.H b/q3radiant/BMP.H
new file mode 100755
index 0000000..367d652
--- /dev/null
+++ b/q3radiant/BMP.H
@@ -0,0 +1,101 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef _BMP_H
+#define _BMP_H
+
+#define xBI_NONE 0
+#define xBI_RGB 0
+#define xBI_RLE4 2
+#define xBI_RLE8 1
+
+#define BMP_SIGNATURE_WORD 0x4d42
+
+#pragma pack(1)
+
+
+
+typedef struct {
+ unsigned short bfType; // signature - 'BM'
+ unsigned long bfSize; // file size in bytes
+ unsigned short bfReserved1; // 0
+ unsigned short bfReserved2; // 0
+ unsigned long bfOffBits; // offset to bitmap
+} bmphd_t;
+
+
+
+typedef struct {
+ unsigned long biSize; // size of this struct
+ long biWidth; // bmap width in pixels
+ long biHeight; // bmap height in pixels
+ unsigned short biPlanes; // num planes - always 1
+ unsigned short biBitCount; // bits perpixel
+ unsigned long biCompression; // compression flag
+ unsigned long biSizeImage; // image size in bytes
+ long biXPelsPerMeter; // horz resolution
+ long biYPelsPerMeter; // vert resolution
+ unsigned long biClrUsed; // 0 -> color table size
+ unsigned long biClrImportant; // important color count
+} binfo_t;
+
+
+typedef struct {
+ unsigned char blue;
+ unsigned char green;
+ unsigned char red;
+ unsigned char reserved;
+} drgb_t;
+
+
+// quake expects its palette to be bgr
+// this is totally backwards but what can you do
+typedef struct {
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+} rgb_t;
+
+
+typedef struct {
+ unsigned char b;
+ unsigned char g;
+ unsigned char r;
+} bgr_t;
+
+
+typedef struct {
+ int bpp; // bits per pixel
+ int width;
+ int height;
+ unsigned char *data;
+ rgb_t *palette;
+} bitmap_t;
+
+
+void LoadBMP(char *filename, bitmap_t *bit);
+void FreeBMP(bitmap_t *bitmap);
+void WriteBMP(char *filename, bitmap_t *bit);
+void NewBMP(int width, int height, int bpp, bitmap_t *bit);
+
+
+
+#endif
diff --git a/q3radiant/BRUSH.H b/q3radiant/BRUSH.H
new file mode 100755
index 0000000..13f17b6
--- /dev/null
+++ b/q3radiant/BRUSH.H
@@ -0,0 +1,124 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+// brush.h
+
+// all types moved to qertypes.h
+//--typedef struct
+//--{
+//-- int numpoints;
+//-- int maxpoints;
+//-- float points[8][5]; // variable sized
+//--} winding_t;
+
+
+// the normals on planes point OUT of the brush
+//--#define MAXPOINTS 16
+//--typedef struct face_s
+//--{
+//-- struct face_s *next;
+//-- vec3_t planepts[3];
+//-- texdef_t texdef;
+//-- plane_t plane;
+//--
+//-- winding_t *face_winding;
+//--
+//-- vec3_t d_color;
+//-- qtexture_t *d_texture;
+//--
+//--} face_t;
+//--
+//--typedef struct {
+//-- vec3_t xyz;
+//-- float sideST[2];
+//-- float capST[2];
+//--} curveVertex_t;
+//--
+//--typedef struct {
+//-- curveVertex_t v[2];
+//--} sideVertex_t;
+//--
+//--typedef struct brush_s
+//--{
+//-- struct brush_s *prev, *next; // links in active/selected
+//-- struct brush_s *oprev, *onext; // links in entity
+//-- struct entity_s *owner;
+//-- vec3_t mins, maxs;
+//-- face_t *brush_faces;
+//--
+//-- qboolean bModelFailed;
+//-- //
+//-- // curve brush extensions
+//-- // all are derived from brush_faces
+//-- qboolean curveBrush;
+//-- qboolean patchBrush;
+//-- int nPatchID;
+//--} brush_t;
+
+void Brush_AddToList (brush_t *b, brush_t *list);
+void Brush_Build(brush_t *b, bool bSnap = true, bool bMarkMap = true, bool bConvert = false);
+void Brush_BuildWindings( brush_t *b, bool bSnap = true );
+brush_t* Brush_Clone (brush_t *b);
+brush_t* Brush_FullClone(brush_t *b);
+brush_t* Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef);
+void Brush_Draw( brush_t *b );
+void Brush_DrawXY(brush_t *b, int nViewType);
+// set bRemoveNode to false to avoid trying to delete the item in group view tree control
+void Brush_Free (brush_t *b, bool bRemoveNode = true);
+int Brush_MemorySize(brush_t *b);
+void Brush_MakeSided (int sides);
+void Brush_MakeSidedCone (int sides);
+void Brush_Move (brush_t *b, const vec3_t move, bool bSnap = true);
+int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap = true);
+void Brush_ResetFaceOriginals(brush_t *b);
+brush_t* Brush_Parse (void);
+face_t* Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist);
+void Brush_RemoveFromList (brush_t *b);
+void Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back);
+void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear);
+void Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef* pPlugTexdef=NULL );
+void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir, qboolean shear);
+void Brush_SnapToGrid(brush_t *pb);
+void Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild = true);
+void Brush_MakeSidedSphere(int sides);
+void Brush_Write (brush_t *b, FILE *f);
+void Brush_Write (brush_t *b, CMemFile* pMemFile);
+void Brush_RemoveEmptyFaces ( brush_t *b );
+winding_t* Brush_MakeFaceWinding (brush_t *b, face_t *face);
+
+int AddPlanept (float *f);
+float SetShadeForPlane (plane_t *p);
+
+face_t* Face_Alloc( void );
+void Face_Free( face_t *f );
+face_t* Face_Clone (face_t *f);
+void Face_MakePlane (face_t *f);
+void Face_Draw( face_t *face );
+void Face_TextureVectors (face_t *f, float STfromXYZ[2][4]);
+void SetFaceTexdef (brush_t *b, face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef* pPlugTexdef = NULL );
+
+void Face_FitTexture( face_t * face, int nHeight, int nWidth );
+void Brush_FitTexture( brush_t *b, int nHeight, int nWidth );
+void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue);
+const char* Brush_GetKeyValue(brush_t *b, const char *pKey);
+brush_t *Brush_Alloc();
+const char* Brush_Name(brush_t *b);
diff --git a/q3radiant/BSInput.cpp b/q3radiant/BSInput.cpp
new file mode 100755
index 0000000..8d7cef5
--- /dev/null
+++ b/q3radiant/BSInput.cpp
@@ -0,0 +1,115 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// BSInput.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "BSInput.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBSInput dialog
+
+
+CBSInput::CBSInput(CWnd* pParent /*=NULL*/)
+ : CDialog(CBSInput::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CBSInput)
+ m_fField1 = 0.0f;
+ m_fField2 = 0.0f;
+ m_fField3 = 0.0f;
+ m_fField4 = 0.0f;
+ m_fField5 = 0.0f;
+ m_strField1 = _T("");
+ m_strField2 = _T("");
+ m_strField3 = _T("");
+ m_strField4 = _T("");
+ m_strField5 = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CBSInput::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBSInput)
+ DDX_Text(pDX, IDC_EDIT_FIELD1, m_fField1);
+ DDX_Text(pDX, IDC_EDIT_FIELD2, m_fField2);
+ DDX_Text(pDX, IDC_EDIT_FIELD3, m_fField3);
+ DDX_Text(pDX, IDC_EDIT_FIELD4, m_fField4);
+ DDX_Text(pDX, IDC_EDIT_FIELD5, m_fField5);
+ DDX_Text(pDX, IDC_STATIC_FIELD1, m_strField1);
+ DDX_Text(pDX, IDC_STATIC_FIELD2, m_strField2);
+ DDX_Text(pDX, IDC_STATIC_FIELD3, m_strField3);
+ DDX_Text(pDX, IDC_STATIC_FIELD4, m_strField4);
+ DDX_Text(pDX, IDC_STATIC_FIELD5, m_strField5);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CBSInput, CDialog)
+ //{{AFX_MSG_MAP(CBSInput)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBSInput message handlers
+
+BOOL CBSInput::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ if (m_strField1.GetLength() == 0)
+ {
+ GetDlgItem(IDC_EDIT_FIELD1)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_STATIC_FIELD1)->ShowWindow(SW_HIDE);
+ }
+ if (m_strField2.GetLength() == 0)
+ {
+ GetDlgItem(IDC_EDIT_FIELD2)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_STATIC_FIELD2)->ShowWindow(SW_HIDE);
+ }
+ if (m_strField3.GetLength() == 0)
+ {
+ GetDlgItem(IDC_EDIT_FIELD3)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_STATIC_FIELD3)->ShowWindow(SW_HIDE);
+ }
+ if (m_strField4.GetLength() == 0)
+ {
+ GetDlgItem(IDC_EDIT_FIELD4)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_STATIC_FIELD4)->ShowWindow(SW_HIDE);
+ }
+ if (m_strField5.GetLength() == 0)
+ {
+ GetDlgItem(IDC_EDIT_FIELD5)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_STATIC_FIELD5)->ShowWindow(SW_HIDE);
+ }
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/BSInput.h b/q3radiant/BSInput.h
new file mode 100755
index 0000000..02b2057
--- /dev/null
+++ b/q3radiant/BSInput.h
@@ -0,0 +1,76 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_BSINPUT_H__81DF2A32_A552_11D1_B58E_00AA00A410FC__INCLUDED_)
+#define AFX_BSINPUT_H__81DF2A32_A552_11D1_B58E_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// BSInput.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CBSInput dialog
+
+class CBSInput : public CDialog
+{
+// Construction
+public:
+ CBSInput(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CBSInput)
+ enum { IDD = IDD_DIALOG_INPUT };
+ float m_fField1;
+ float m_fField2;
+ float m_fField3;
+ float m_fField4;
+ float m_fField5;
+ CString m_strField1;
+ CString m_strField2;
+ CString m_strField3;
+ CString m_strField4;
+ CString m_strField5;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBSInput)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CBSInput)
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_BSINPUT_H__81DF2A32_A552_11D1_B58E_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/BSPFILE.H b/q3radiant/BSPFILE.H
new file mode 100755
index 0000000..93c9db0
--- /dev/null
+++ b/q3radiant/BSPFILE.H
@@ -0,0 +1,379 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define MAX_MAP_MODELS 1024
+#define MAX_MAP_BRUSHES 8192
+#define MAX_MAP_ENTITIES 2048
+#define MAX_MAP_PATHS 2048
+#define MAX_MAP_ENTSTRING 0x20000
+#define MAX_MAP_TEXTURES 1024
+#define MAX_MAP_TEXINFO 8192
+
+#define MAX_MAP_PLANES 65536
+#define MAX_MAP_NODES 65536
+#define MAX_MAP_BRUSHSIDES 65536
+#define MAX_MAP_LEAFS 65536
+#define MAX_MAP_VERTS 65536
+#define MAX_MAP_FACES 65536
+#define MAX_MAP_LEAFFACES 65536
+#define MAX_MAP_LEAFBRUSHES 65536
+#define MAX_MAP_PORTALS 65536
+#define MAX_MAP_EDGES 128000
+#define MAX_MAP_SURFEDGES 256000
+#define MAX_MAP_MIPTEX 0x200000
+#define MAX_MAP_LIGHTING 0x200000
+#define MAX_MAP_VISIBILITY 0x100000
+
+// key / value pair sizes
+
+#define MAX_KEY 32
+#define MAX_VALUE 1024
+
+//=============================================================================
+
+#define BSPVERSION 34
+
+typedef struct
+{
+ int fileofs, filelen;
+} lump_t;
+
+#define LUMP_ENTITIES 0
+#define LUMP_PLANES 1
+#define LUMP_TEXTURES 2
+#define LUMP_VERTEXES 3
+#define LUMP_VISIBILITY 4
+#define LUMP_NODES 5
+#define LUMP_TEXINFO 6
+#define LUMP_FACES 7
+#define LUMP_LIGHTING 8
+#define LUMP_LEAFS 9
+#define LUMP_LEAFFACES 10
+#define LUMP_LEAFBRUSHES 11
+#define LUMP_EDGES 12
+#define LUMP_SURFEDGES 13
+#define LUMP_MODELS 14
+#define LUMP_PATHS 15
+#define LUMP_BRUSHES 16
+#define LUMP_BRUSHSIDES 17
+#define LUMP_POP 18
+
+#define HEADER_LUMPS 18
+
+typedef struct
+{
+ int version;
+ lump_t lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+ float mins[3], maxs[3];
+ float origin[3]; // for sounds or lights
+ int headnode;
+ int visleafs; // not including the solid leaf 0
+ int firstface, numfaces;
+} dmodel_t;
+
+typedef struct
+{
+ int nummiptex;
+ int dataofs[4]; // [nummiptex]
+} dmiptexlump_t;
+
+#define MIPLEVELS 4
+typedef struct miptex_s
+{
+ char name[16];
+ unsigned width, height;
+ unsigned offsets[MIPLEVELS]; // four mip maps stored
+ int flags;
+ int value;
+} miptex_t;
+
+
+typedef struct
+{
+ float point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define PLANE_X 0
+#define PLANE_Y 1
+#define PLANE_Z 2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define PLANE_ANYX 3
+#define PLANE_ANYY 4
+#define PLANE_ANYZ 5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+ float normal[3];
+ float dist;
+ int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// lower bits are stronger, and will eat weaker brushes completely
+#define CONTENTS_SOLID 1 // an eye is never valid in a solid
+#define CONTENTS_WINDOW 2 // translucent, but not watery
+#define CONTENTS_LAVA 8
+#define CONTENTS_SLIME 16
+#define CONTENTS_WATER 32
+#define CONTENTS_THINWATER 64 // translucent faces
+
+#define LAST_VISIBLE_CONTENTS 64
+
+// remaining contents are non-visible, and don't eat brushes
+#define CONTENTS_MONSTER 128
+#define CONTENTS_PLAYERCLIP 256
+#define CONTENTS_MONSTERCLIP 512
+
+
+// currents can be added to any other contents, and may be mixed
+#define CONTENTS_CURRENT_0 1024
+#define CONTENTS_CURRENT_90 2048
+#define CONTENTS_CURRENT_180 4096
+#define CONTENTS_CURRENT_270 8192
+#define CONTENTS_CURRENT_UP 16384
+#define CONTENTS_CURRENT_DOWN 32768
+
+#define CONTENTS_ORIGIN 65536 // removed before processing
+
+
+
+// !!! if this is changed, it must be changed in asm_i386.h too !!!
+typedef struct
+{
+ int planenum;
+ int children[2]; // negative numbers are -(leafs+1), not nodes
+ short mins[3]; // for frustom culling
+ short maxs[3];
+ unsigned short firstface;
+ unsigned short numfaces; // counting both sides
+} dnode_t;
+
+typedef struct texinfo_s
+{
+ float vecs[2][4]; // [s/t][xyz offset]
+ int miptex;
+ int flags; // miptex flags + overrides
+ int value; // light emition, etc
+} texinfo_t;
+
+#define TEX_SPECIAL 1 // sky or slime, no lightmap or 256 subdivision
+#define SURF_LIGHT 2
+
+#define SURF_WATER 4
+#define SURF_SLIME 8
+#define SURF_LAVA 16
+#define SURF_WINDOW 32
+
+#define SURF_SKY 64
+#define SURF_MIRROR 128
+
+#define SURF_SLIPPERY 256
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+ unsigned short v[2]; // vertex numbers
+} dedge_t;
+
+#define MAXLIGHTMAPS 4
+typedef struct
+{
+ unsigned short planenum;
+ short side;
+
+ int firstedge; // we must support > 64k edges
+ short numedges;
+ short texinfo;
+
+// lighting info
+ byte styles[MAXLIGHTMAPS];
+ int lightofs; // start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+ int contents; // OR of all brushes
+ int visofs; // -1 = no visibility info
+
+ short mins[3]; // for frustum culling
+ short maxs[3];
+
+ unsigned short firstleafface;
+ unsigned short numleaffaces;
+
+ unsigned short firstleafbrush;
+ unsigned short numleafbrushes;
+} dleaf_t;
+
+
+typedef struct
+{
+ unsigned short planenum; // facing out of the leaf
+ short texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+ int firstside;
+ int numsides;
+ int contents;
+} dbrush_t;
+
+typedef struct
+{
+ float origin[3];
+ float angles[3];
+ int next, prev;
+ int flags;
+ float speed;
+} dpath_t;
+
+//============================================================================
+
+#ifndef QUAKE_GAME
+
+#define ANGLE_UP -1
+#define ANGLE_DOWN -2
+
+
+// the utilities get to be lazy and just use large static arrays
+
+extern int nummodels;
+extern dmodel_t dmodels[MAX_MAP_MODELS];
+
+extern int visdatasize;
+extern byte dvisdata[MAX_MAP_VISIBILITY];
+
+extern int lightdatasize;
+extern byte dlightdata[MAX_MAP_LIGHTING];
+
+extern int texdatasize;
+extern byte dtexdata[MAX_MAP_MIPTEX]; // (dmiptexlump_t)
+
+extern int entdatasize;
+extern char dentdata[MAX_MAP_ENTSTRING];
+
+extern int numleafs;
+extern dleaf_t dleafs[MAX_MAP_LEAFS];
+
+extern int numplanes;
+extern dplane_t dplanes[MAX_MAP_PLANES];
+
+extern int numvertexes;
+extern dvertex_t dvertexes[MAX_MAP_VERTS];
+
+extern int numnodes;
+extern dnode_t dnodes[MAX_MAP_NODES];
+
+extern int numtexinfo;
+extern texinfo_t texinfo[MAX_MAP_TEXINFO];
+
+extern int numfaces;
+extern dface_t dfaces[MAX_MAP_FACES];
+
+extern int numedges;
+extern dedge_t dedges[MAX_MAP_EDGES];
+
+extern int numleaffaces;
+extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
+
+extern int numleafbrushes;
+extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+extern int numsurfedges;
+extern int dsurfedges[MAX_MAP_SURFEDGES];
+
+extern int numpaths;
+extern dpath_t dpaths[MAX_MAP_PATHS];
+
+extern int numbrushes;
+extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
+
+extern int numbrushsides;
+extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
+
+
+void DecompressVis (byte *in, byte *decompressed);
+int CompressVis (byte *vis, byte *dest);
+
+void LoadBSPFile (char *filename);
+void WriteBSPFile (char *filename);
+void PrintBSPFileSizes (void);
+
+//===============
+
+
+typedef struct epair_s
+{
+ struct epair_s *next;
+ char *key;
+ char *value;
+} epair_t;
+
+typedef struct
+{
+ vec3_t origin;
+ int firstbrush;
+ int numbrushes;
+ epair_t *epairs;
+} entity_t;
+
+extern int num_entities;
+extern entity_t entities[MAX_MAP_ENTITIES];
+
+void ParseEntities (void);
+void UnparseEntities (void);
+
+void SetKeyValue (entity_t *ent, char *key, char *value);
+char *ValueForKey (entity_t *ent, char *key);
+// will return "" if not present
+
+vec_t FloatForKey (entity_t *ent, char *key);
+void GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
+
+epair_t *ParseEpair (void);
+
+void PrintEntity (entity_t *ent);
+
+extern int r_leaftovis[MAX_MAP_LEAFS];
+extern int r_vistoleaf[MAX_MAP_LEAFS];
+extern int r_numvisleafs;
+
+#endif
diff --git a/q3radiant/Bmp.cpp b/q3radiant/Bmp.cpp
new file mode 100755
index 0000000..adda9a9
--- /dev/null
+++ b/q3radiant/Bmp.cpp
@@ -0,0 +1,417 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "stdafx.h"
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+
+#include "bmp.h"
+
+
+void Error(char *fmt, ...);
+
+
+static int GetColorCount(int nbits)
+{
+ int ncolors = 0;
+
+ if (nbits < 24)
+ {
+ ncolors = 1 << nbits;
+ }
+
+ return(ncolors);
+}
+
+
+static void BMPLineNone(FILE *f, char *sline, int pixbytes, int width)
+{
+ int nbytes, i, k, j;
+
+ switch (pixbytes)
+ {
+ case 1 :
+ nbytes = (width + 3) / 4;
+ nbytes *= 4;
+
+ fread(sline, width, 1, f);
+ nbytes -= width;
+
+ while (nbytes-- > 0) fgetc(f);
+ return;
+
+ case 3 :
+ nbytes = ((width * 3) + 3) / 4;
+ nbytes *= 4;
+
+ fread(sline, width, 3, f);
+ nbytes -= width * 3;
+
+ while (nbytes-- > 0) fgetc(f);
+
+ // reorder bgr to rgb
+ for (i = 0, j = 0; i < width; i++, j += 3)
+ {
+ k = sline[j];
+ sline[j] = sline[j+2];
+ sline[j+2] = k;
+ }
+
+ return;
+ }
+
+ Error("BMPLineNone failed.");
+}
+
+
+static void BMPLineRLE8(FILE *f, char *sline, int pixbytes, int width)
+{
+ Error("RLE8 not yet supported.");
+}
+
+
+static void BMPLineRLE4(FILE *f, char *sline, int pixbytes, int width)
+{
+ Error("RLE4 not yet supported.");
+}
+
+
+static void BMPLine(FILE *f, char *scanline, int pixbytes, int width, int rle)
+{
+ switch (rle)
+ {
+ case xBI_NONE : BMPLineNone(f, scanline, pixbytes, width); return;
+ case xBI_RLE8 : BMPLineRLE8(f, scanline, pixbytes, width); return;
+ case xBI_RLE4 : BMPLineRLE4(f, scanline, pixbytes, width); return;
+ }
+
+ Error("Unknown compression type.");
+}
+
+
+
+static void PrintHeader(binfo_t *b)
+{
+ printf("biSize : %ld\n", b->biSize);
+ printf("biWidth : %ld\n", b->biWidth);
+ printf("biHeight : %ld\n", b->biHeight);
+ printf("biPlanes : %d\n", b->biPlanes);
+ printf("biBitCount : %d\n", b->biBitCount);
+ printf("biCompression : %ld\n", b->biCompression);
+ printf("biSizeImage : %ld\n", b->biSizeImage);
+ printf("biXPelsPerMeter: %ld\n", b->biXPelsPerMeter);
+ printf("biYPelsPerMeter: %ld\n", b->biYPelsPerMeter);
+ printf("biClrUsed : %ld\n", b->biClrUsed);
+ printf("biClrImportant : %ld\n", b->biClrImportant);
+}
+
+
+void LoadBMP(char *filename, bitmap_t *bit)
+{
+ FILE *f;
+ bmphd_t bhd;
+ binfo_t info;
+ int pxlsize = 1;
+ int rowbytes, i, pixbytes;
+ char *scanline;
+
+ // open file
+ if ((f = fopen(filename, "rb")) == NULL)
+ {
+ Error("Unable to open %s.", filename);
+ }
+
+ // read in bitmap header
+ if (fread(&bhd, sizeof(bhd), 1, f) != 1)
+ {
+ fclose(f);
+ Error("Unable to read in bitmap header.");
+ }
+
+ // make sure we have a valid bitmap file
+ if (bhd.bfType != BMP_SIGNATURE_WORD)
+ {
+ fclose(f);
+ Error("Invalid BMP file: %s", filename);
+ }
+
+ // load in info header
+ if (fread(&info, sizeof(info), 1, f) != 1)
+ {
+ fclose(f);
+ Error("Unable to read bitmap info header.");
+ }
+
+ // make sure this is an info type of bitmap
+ if (info.biSize != sizeof(binfo_t))
+ {
+ fclose(f);
+ Error("We only support the info bitmap type.");
+ }
+
+ // PrintHeader(&info);
+
+ bit->bpp = info.biBitCount;
+ bit->width = info.biWidth;
+ bit->height = info.biHeight;
+ bit->data = NULL;
+ bit->palette = NULL;
+
+ //currently we only read in 8 and 24 bit bmp files
+ if (info.biBitCount == 8) pixbytes = 1;
+ else if (info.biBitCount == 24) pixbytes = 3;
+ else
+ {
+ Error("BPP %d not supported.", info.biBitCount);
+ }
+
+ // if this is an eight bit image load palette
+ if (pixbytes == 1)
+ {
+ drgb_t q;
+
+ bit->palette = reinterpret_cast<rgb_t*>(malloc(sizeof(rgb_t) * 256));
+
+ for (i = 0; i < 256; i++)
+ {
+ if (fread(&q, sizeof(drgb_t), 1, f) != 1)
+ {
+ fclose(f); free(bit->palette);
+ Error("Unable to read palette.");
+ }
+
+ bit->palette[i].r = q.red;
+ bit->palette[i].g = q.green;
+ bit->palette[i].b = q.blue;
+ }
+ }
+
+ // position to start of bitmap
+ fseek(f, bhd.bfOffBits, SEEK_SET);
+
+ // create scanline to read data into
+ rowbytes = ((info.biWidth * pixbytes) + 3) / 4;
+ rowbytes *= 4;
+
+ scanline = reinterpret_cast<char*>(malloc(rowbytes));
+
+ // alloc space for new bitmap
+ bit->data = reinterpret_cast<unsigned char*>(malloc(info.biWidth * pixbytes * info.biHeight));
+
+ // read in image
+ for (i = 0; i < info.biHeight; i++)
+ {
+ BMPLine(f, scanline, pixbytes, info.biWidth, info.biCompression);
+
+ // store line
+ memcpy(&bit->data[info.biWidth * pixbytes * (info.biHeight - i - 1)], scanline, info.biWidth * pixbytes);
+ }
+
+ free(scanline);
+ fclose(f);
+}
+
+
+
+static void BMPEncodeLine(FILE *f, unsigned char *data, int npxls, int pixbytes)
+{
+ int nbytes, i, j, k;
+
+ switch (pixbytes)
+ {
+ case 1 :
+ nbytes = (npxls + 3) / 4;
+ nbytes *= 4;
+
+ fwrite(data, npxls, 1, f);
+ nbytes -= npxls;
+
+ while (nbytes-- > 0) fputc(0, f);
+ return;
+
+ case 3 :
+ // reorder rgb to bgr
+ for (i = 0, j = 0; i < npxls; i++, j+= 3)
+ {
+ k = data[j];
+ data[j] = data[j + 2];
+ data[j + 2] = k;
+ }
+
+ nbytes = ((npxls * 3) + 3) / 4;
+ nbytes *= 4;
+
+ fwrite(data, npxls, 3, f);
+ nbytes -= npxls * 3;
+
+ while (nbytes-- > 0) fputc(0, f);
+ return;
+ }
+
+ Error("BMPEncodeLine Failed.");
+}
+
+
+
+void WriteBMP(char *filename, bitmap_t *bit)
+{
+ FILE *f;
+ bmphd_t header;
+ binfo_t info;
+ drgb_t q; // palette that gets written
+ long bmofs;
+ int w, h, i;
+ int pixbytes;
+
+ if (bit->bpp == 8) pixbytes = 1;
+ else if (bit->bpp == 24) pixbytes = 3;
+
+ else
+ {
+ Error("BPP %d not supported.", bit->bpp);
+ }
+
+
+ if ((f = fopen(filename, "wb")) == NULL)
+ {
+ Error("Unable to open %s.", filename);
+ }
+
+ // write out an empty header as a place holder
+ if (fwrite(&header, sizeof(header), 1, f) != 1)
+ {
+ Error("Unable to fwrite.");
+ }
+
+ // init and write info header
+ info.biSize = sizeof(binfo_t);
+ info.biWidth = bit->width;
+ info.biHeight = bit->height;
+ info.biPlanes = 1;
+ info.biBitCount = bit->bpp;
+ info.biCompression = xBI_NONE;
+ info.biSizeImage = bit->width * bit->height;
+ info.biXPelsPerMeter = 0;
+ info.biYPelsPerMeter = 0;
+ info.biClrUsed = 256;
+ info.biClrImportant = 256;
+
+ if (fwrite(&info, sizeof(binfo_t), 1, f) != 1)
+ {
+ Error("fwrite failed.");
+ }
+
+ // write out palette if we need to
+ if (bit->bpp == 8)
+ {
+ for (i = 0; i < 256; i++)
+ {
+ q.red = bit->palette[i].r;
+ q.green = bit->palette[i].g;
+ q.blue = bit->palette[i].b;
+
+ fwrite(&q, sizeof(q), 1, f);
+ }
+ }
+
+ // save offset to start of bitmap
+ bmofs = ftell(f);
+
+ // output bitmap
+ w = bit->width;
+ h = bit->height;
+
+ for (i = h - 1; i >= 0; i--)
+ {
+ BMPEncodeLine(f, &bit->data[w * pixbytes * i], w, pixbytes);
+ }
+
+ // update and rewrite file header
+ header.bfType = BMP_SIGNATURE_WORD;
+ header.bfSize = ftell(f);
+ header.bfOffBits = bmofs;
+
+ fseek(f, 0L, SEEK_SET);
+ fwrite(&header, sizeof(header), 1, f);
+
+ fclose(f);
+}
+
+
+void NewBMP(int width, int height, int bpp, bitmap_t *bit)
+{
+ int pixbytes;
+
+ if (bpp == 8) pixbytes = 1;
+ else if (bpp == 24) pixbytes = 3;
+
+ else
+ {
+ Error("NewBMP: 8 or 24 bit only.");
+ }
+
+ bit->bpp = bpp;
+ bit->width = width;
+ bit->height = height;
+
+ bit->data = reinterpret_cast<unsigned char*>(malloc(width * height * pixbytes));
+
+ if (bit->data == NULL)
+ {
+ Error("NewBMP: malloc failed.");
+ }
+
+ // see if we need to create a palette
+ if (pixbytes == 1)
+ {
+ bit->palette = (rgb_t *) malloc(768);
+
+ if (bit->palette == NULL)
+ {
+ Error("NewBMP: unable to malloc palette.");
+ }
+ }
+ else
+ {
+ bit->palette = NULL;
+ }
+}
+
+
+
+void FreeBMP(bitmap_t *bitmap)
+{
+ if (bitmap->palette)
+ {
+ free(bitmap->palette);
+ bitmap->palette = NULL;
+ }
+
+ if (bitmap->data)
+ {
+ free(bitmap->data);
+ bitmap->data = NULL;
+ }
+}
+
+
diff --git a/q3radiant/Brush.cpp b/q3radiant/Brush.cpp
new file mode 100755
index 0000000..e7f0168
--- /dev/null
+++ b/q3radiant/Brush.cpp
@@ -0,0 +1,4595 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+
+#include "stdafx.h"
+#include <assert.h>
+#include "qe3.h"
+#include "winding.h"
+
+
+// globals
+
+int g_nBrushId = 0;
+
+const char* Brush_Name(brush_t *b)
+{
+ static char cBuff[1024];
+ b->numberId = g_nBrushId++;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ sprintf(cBuff, "Brush %i", b->numberId);
+ Brush_SetEpair(b, "Name", cBuff);
+ }
+ return cBuff;
+}
+
+brush_t *Brush_Alloc()
+{
+ brush_t *b = (brush_t*)qmalloc(sizeof(brush_t));
+ return b;
+}
+
+
+
+
+void PrintWinding (winding_t *w)
+{
+ int i;
+
+ printf ("-------------\n");
+ for (i=0 ; i<w->numpoints ; i++)
+ printf ("(%5.2f, %5.2f, %5.2f)\n", w->points[i][0]
+ , w->points[i][1], w->points[i][2]);
+}
+
+void PrintPlane (plane_t *p)
+{
+ printf ("(%5.2f, %5.2f, %5.2f) : %5.2f\n", p->normal[0], p->normal[1],
+ p->normal[2], p->dist);
+}
+
+void PrintVector (vec3_t v)
+{
+ printf ("(%5.2f, %5.2f, %5.2f)\n", v[0], v[1], v[2]);
+}
+
+
+/*
+=============================================================================
+
+ TEXTURE COORDINATES
+
+=============================================================================
+*/
+
+
+/*
+==================
+textureAxisFromPlane
+==================
+*/
+vec3_t baseaxis[18] =
+{
+{0,0,1}, {1,0,0}, {0,-1,0}, // floor
+{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling
+{1,0,0}, {0,1,0}, {0,0,-1}, // west wall
+{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall
+{0,1,0}, {1,0,0}, {0,0,-1}, // south wall
+{0,-1,0}, {1,0,0}, {0,0,-1} // north wall
+};
+
+void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
+{
+ int bestaxis;
+ float dot,best;
+ int i;
+
+ best = 0;
+ bestaxis = 0;
+
+ for (i=0 ; i<6 ; i++)
+ {
+ dot = DotProduct (pln->normal, baseaxis[i*3]);
+ if (dot > best)
+ {
+ best = dot;
+ bestaxis = i;
+ }
+ }
+
+ VectorCopy (baseaxis[bestaxis*3+1], xv);
+ VectorCopy (baseaxis[bestaxis*3+2], yv);
+}
+
+
+
+float lightaxis[3] = {0.6, 0.8, 1.0};
+/*
+================
+SetShadeForPlane
+
+Light different planes differently to
+improve recognition
+================
+*/
+float SetShadeForPlane (plane_t *p)
+{
+ int i;
+ float f;
+
+ // axial plane
+ for (i=0 ; i<3 ; i++)
+ if (fabs(p->normal[i]) > 0.9)
+ {
+ f = lightaxis[i];
+ return f;
+ }
+
+ // between two axial planes
+ for (i=0 ; i<3 ; i++)
+ if (fabs(p->normal[i]) < 0.1)
+ {
+ f = (lightaxis[(i+1)%3] + lightaxis[(i+2)%3])/2;
+ return f;
+ }
+
+ // other
+ f= (lightaxis[0] + lightaxis[1] + lightaxis[2]) / 3;
+ return f;
+}
+
+vec3_t vecs[2];
+float shift[2];
+
+/*
+================
+Face_Alloc
+================
+*/
+face_t *Face_Alloc( void )
+{
+ face_t *f = (face_t*)qmalloc( sizeof( *f ) );
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ f->pData = static_cast<void *>( g_SurfaceTable.m_pfnTexdefAlloc( f ) );
+
+ return f;
+}
+
+/*
+================
+Face_Free
+================
+*/
+void Face_Free( face_t *f )
+{
+ assert( f != 0 );
+
+ if ( f->face_winding )
+ {
+ free( f->face_winding );
+ f->face_winding = 0;
+ }
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+#ifdef _DEBUG
+ if ( !f->pData )
+ {
+ Sys_Printf("WARNING: unexpected IPluginTexdef is NULL in Face_Free\n");
+ }
+ else
+#endif
+ GETPLUGINTEXDEF(f)->DecRef();
+ }
+
+ f->texdef.~texdef_t();;
+
+ free( f );
+}
+
+/*
+================
+Face_Clone
+================
+*/
+face_t *Face_Clone (face_t *f)
+{
+ face_t *n;
+
+ n = Face_Alloc();
+ n->texdef = f->texdef;
+
+ memcpy (n->planepts, f->planepts, sizeof(n->planepts));
+
+ // all other fields are derived, and will be set by Brush_Build
+ return n;
+}
+
+/*
+================
+Face_FullClone
+
+makes an exact copy of the face
+================
+*/
+face_t *Face_FullClone (face_t *f)
+{
+ face_t *n;
+
+ n = Face_Alloc();
+ n->texdef = f->texdef;
+ memcpy(n->planepts, f->planepts, sizeof(n->planepts));
+ memcpy(&n->plane, &f->plane, sizeof(plane_t));
+ if (f->face_winding)
+ n->face_winding = Winding_Clone(f->face_winding);
+ else
+ n->face_winding = NULL;
+ n->d_texture = Texture_ForName( n->texdef.name );
+ return n;
+}
+
+/*
+================
+Clamp
+================
+*/
+void Clamp(float& f, int nClamp)
+{
+ float fFrac = f - static_cast<int>(f);
+ f = static_cast<int>(f) % nClamp;
+ f += fFrac;
+}
+
+/*
+================
+Face_MoveTexture
+================
+*/
+void Face_MoveTexture(face_t *f, vec3_t delta)
+{
+ vec3_t vX, vY;
+/*
+#ifdef _DEBUG
+ if (g_PrefsDlg.m_bBrushPrimitMode)
+ Sys_Printf("Warning : Face_MoveTexture not done in brush primitive mode\n");
+#endif
+*/
+ if (g_qeglobals.m_bBrushPrimitMode)
+ Face_MoveTexture_BrushPrimit( f, delta );
+ else
+ {
+ TextureAxisFromPlane(&f->plane, vX, vY);
+
+ vec3_t vDP, vShift;
+ vDP[0] = DotProduct(delta, vX);
+ vDP[1] = DotProduct(delta, vY);
+
+ double fAngle = f->texdef.rotate / 180 * Q_PI;
+ double c = cos(fAngle);
+ double s = sin(fAngle);
+
+ vShift[0] = vDP[0] * c - vDP[1] * s;
+ vShift[1] = vDP[0] * s + vDP[1] * c;
+
+ if (!f->texdef.scale[0])
+ f->texdef.scale[0] = 1;
+ if (!f->texdef.scale[1])
+ f->texdef.scale[1] = 1;
+
+ f->texdef.shift[0] -= vShift[0] / f->texdef.scale[0];
+ f->texdef.shift[1] -= vShift[1] / f->texdef.scale[1];
+
+ // clamp the shifts
+ Clamp(f->texdef.shift[0], f->d_texture->width);
+ Clamp(f->texdef.shift[1], f->d_texture->height);
+ }
+}
+
+/*
+================
+Face_SetColor
+================
+*/
+void Face_SetColor (brush_t *b, face_t *f, float fCurveColor)
+{
+ float shade;
+ qtexture_t *q;
+
+ q = f->d_texture;
+
+ // set shading for face
+ shade = SetShadeForPlane (&f->plane);
+ if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture && !b->owner->eclass->fixedsize)
+ {
+ //if (b->curveBrush)
+ // shade = fCurveColor;
+ f->d_color[0] =
+ f->d_color[1] =
+ f->d_color[2] = shade;
+ }
+ else
+ {
+ f->d_color[0] = shade*q->color[0];
+ f->d_color[1] = shade*q->color[1];
+ f->d_color[2] = shade*q->color[2];
+ }
+}
+
+/*
+================
+Face_TextureVectors
+TTimo: NOTE: this is never to get called while in brush primitives mode
+================
+*/
+void Face_TextureVectors (face_t *f, float STfromXYZ[2][4])
+{
+ vec3_t pvecs[2];
+ int sv, tv;
+ float ang, sinv, cosv;
+ float ns, nt;
+ int i,j;
+ qtexture_t *q;
+ texdef_t *td;
+
+#ifdef _DEBUG
+ //++timo when playing with patches, this sometimes get called and the Warning is displayed
+ // find some way out ..
+ if (g_qeglobals.m_bBrushPrimitMode && !g_qeglobals.bNeedConvert)
+ Sys_Printf("Warning : illegal call of Face_TextureVectors in brush primitive mode\n");
+#endif
+
+ td = &f->texdef;
+ q = f->d_texture;
+
+ memset (STfromXYZ, 0, 8*sizeof(float));
+
+ if (!td->scale[0])
+ td->scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
+ if (!td->scale[1])
+ td->scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
+
+ // get natural texture axis
+ TextureAxisFromPlane(&f->plane, pvecs[0], pvecs[1]);
+
+ // rotate axis
+ if (td->rotate == 0)
+ { sinv = 0 ; cosv = 1; }
+ else if (td->rotate == 90)
+ { sinv = 1 ; cosv = 0; }
+ else if (td->rotate == 180)
+ { sinv = 0 ; cosv = -1; }
+ else if (td->rotate == 270)
+ { sinv = -1 ; cosv = 0; }
+ else
+ {
+ ang = td->rotate / 180 * Q_PI;
+ sinv = sin(ang);
+ cosv = cos(ang);
+ }
+
+ if (pvecs[0][0])
+ sv = 0;
+ else if (pvecs[0][1])
+ sv = 1;
+ else
+ sv = 2;
+
+ if (pvecs[1][0])
+ tv = 0;
+ else if (pvecs[1][1])
+ tv = 1;
+ else
+ tv = 2;
+
+ for (i=0 ; i<2 ; i++) {
+ ns = cosv * pvecs[i][sv] - sinv * pvecs[i][tv];
+ nt = sinv * pvecs[i][sv] + cosv * pvecs[i][tv];
+ STfromXYZ[i][sv] = ns;
+ STfromXYZ[i][tv] = nt;
+ }
+
+ // scale
+ for (i=0 ; i<2 ; i++)
+ for (j=0 ; j<3 ; j++)
+ STfromXYZ[i][j] = STfromXYZ[i][j] / td->scale[i];
+
+ // shift
+ STfromXYZ[0][3] = td->shift[0];
+ STfromXYZ[1][3] = td->shift[1];
+
+ for (j=0 ; j<4 ; j++) {
+ STfromXYZ[0][j] /= q->width;
+ STfromXYZ[1][j] /= q->height;
+ }
+}
+
+/*
+================
+Face_MakePlane
+================
+*/
+void Face_MakePlane (face_t *f)
+{
+ int j;
+ vec3_t t1, t2, t3;
+
+ // convert to a vector / dist plane
+ for (j=0 ; j<3 ; j++)
+ {
+ t1[j] = f->planepts[0][j] - f->planepts[1][j];
+ t2[j] = f->planepts[2][j] - f->planepts[1][j];
+ t3[j] = f->planepts[1][j];
+ }
+
+ CrossProduct(t1,t2, f->plane.normal);
+ if (VectorCompare (f->plane.normal, vec3_origin))
+ printf ("WARNING: brush plane with no normal\n");
+ VectorNormalize (f->plane.normal);
+ f->plane.dist = DotProduct (t3, f->plane.normal);
+}
+
+/*
+================
+EmitTextureCoordinates
+================
+*/
+void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f)
+{
+ float STfromXYZ[2][4];
+
+ Face_TextureVectors (f, STfromXYZ);
+ xyzst[3] = DotProduct (xyzst, STfromXYZ[0]) + STfromXYZ[0][3];
+ xyzst[4] = DotProduct (xyzst, STfromXYZ[1]) + STfromXYZ[1][3];
+}
+
+//==========================================================================
+
+/*
+================
+Brush_MakeFacePlanes
+================
+*/
+void Brush_MakeFacePlanes (brush_t *b)
+{
+ face_t *f;
+
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ Face_MakePlane (f);
+ }
+}
+
+/*
+================
+DrawBrushEntityName
+================
+*/
+void DrawBrushEntityName (brush_t *b)
+{
+ char *name;
+ //float a, s, c;
+ //vec3_t mid;
+ //int i;
+
+ if (!b->owner)
+ return; // during contruction
+
+ if (b->owner == world_entity)
+ return;
+
+ if (b != b->owner->brushes.onext)
+ return; // not key brush
+
+// MERGEME
+#if 0
+ if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES))
+ {
+ // draw the angle pointer
+ a = FloatForKey (b->owner, "angle");
+ if (a)
+ {
+ s = sin (a/180*Q_PI);
+ c = cos (a/180*Q_PI);
+ for (i=0 ; i<3 ; i++)
+ mid[i] = (b->mins[i] + b->maxs[i])*0.5;
+
+ qglBegin (GL_LINE_STRIP);
+ qglVertex3fv (mid);
+ mid[0] += c*8;
+ mid[1] += s*8;
+ mid[2] += s*8;
+ qglVertex3fv (mid);
+ mid[0] -= c*4;
+ mid[1] -= s*4;
+ mid[2] -= s*4;
+ mid[0] -= s*4;
+ mid[1] += c*4;
+ mid[2] += c*4;
+ qglVertex3fv (mid);
+ mid[0] += c*4;
+ mid[1] += s*4;
+ mid[2] += s*4;
+ mid[0] += s*4;
+ mid[1] -= c*4;
+ mid[2] -= c*4;
+ qglVertex3fv (mid);
+ mid[0] -= c*4;
+ mid[1] -= s*4;
+ mid[2] -= s*4;
+ mid[0] += s*4;
+ mid[1] -= c*4;
+ mid[2] -= c*4;
+ qglVertex3fv (mid);
+ qglEnd ();
+ }
+ }
+#endif
+
+ if (g_qeglobals.d_savedinfo.show_names)
+ {
+ name = ValueForKey (b->owner, "classname");
+ qglRasterPos3f (b->mins[0]+4, b->mins[1]+4, b->mins[2]+4);
+ qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
+ }
+}
+
+/*
+=================
+Brush_MakeFaceWinding
+
+returns the visible polygon on a face
+=================
+*/
+winding_t *Brush_MakeFaceWinding (brush_t *b, face_t *face)
+{
+ winding_t *w;
+ face_t *clip;
+ plane_t plane;
+ qboolean past;
+
+ // get a poly that covers an effectively infinite area
+ w = Winding_BaseForPlane (&face->plane);
+
+ // chop the poly by all of the other faces
+ past = false;
+ for (clip = b->brush_faces ; clip && w ; clip=clip->next)
+ {
+ if (clip == face)
+ {
+ past = true;
+ continue;
+ }
+ if (DotProduct (face->plane.normal, clip->plane.normal) > 0.999
+ && fabs(face->plane.dist - clip->plane.dist) < 0.01 )
+ { // identical plane, use the later one
+ if (past)
+ {
+ free (w);
+ return NULL;
+ }
+ continue;
+ }
+
+ // flip the plane, because we want to keep the back side
+ VectorSubtract (vec3_origin,clip->plane.normal, plane.normal);
+ plane.dist = -clip->plane.dist;
+
+ w = Winding_Clip (w, &plane, false);
+ if (!w)
+ return w;
+ }
+
+ if (w->numpoints < 3)
+ {
+ free(w);
+ w = NULL;
+ }
+
+ if (!w)
+ printf ("unused plane\n");
+
+ return w;
+}
+
+/*
+=================
+Brush_SnapPlanepts
+=================
+*/
+void Brush_SnapPlanepts (brush_t *b)
+{
+ int i, j;
+ face_t *f;
+
+ if (g_PrefsDlg.m_bNoClamp)
+ return;
+
+ for (f=b->brush_faces ; f; f=f->next)
+ for (i=0 ; i<3 ; i++)
+ for (j=0 ; j<3 ; j++)
+ f->planepts[i][j] = floor (f->planepts[i][j] + 0.5);
+}
+
+/*
+** Brush_Build
+**
+** Builds a brush rendering data and also sets the min/max bounds
+*/
+// TTimo
+// added a bConvert flag to convert between old and new brush texture formats
+// TTimo
+// brush grouping: update the group treeview if necessary
+void Brush_Build( brush_t *b, bool bSnap, bool bMarkMap, bool bConvert )
+{
+ bool bLocalConvert;
+
+#ifdef _DEBUG
+ if (!g_qeglobals.m_bBrushPrimitMode && bConvert)
+ Sys_Printf("Warning : conversion from brush primitive to old brush format not implemented\n");
+#endif
+
+ // if bConvert is set and g_qeglobals.bNeedConvert is not, that just means we need convert for this brush only
+ if (bConvert && !g_qeglobals.bNeedConvert)
+ {
+ bLocalConvert = true;
+ g_qeglobals.bNeedConvert = true;
+ }
+
+ /*
+ ** build the windings and generate the bounding box
+ */
+ Brush_BuildWindings(b, bSnap);
+
+ Patch_BuildPoints (b);
+
+ /*
+ ** move the points and edges if in select mode
+ */
+ if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
+ SetupVertexSelection ();
+
+ if (b->itemOwner == NULL)
+ Group_AddToProperGroup(b);
+
+ if (bMarkMap)
+ {
+ Sys_MarkMapModified();
+ }
+
+ if (bLocalConvert)
+ g_qeglobals.bNeedConvert = false;
+}
+
+/*
+==============
+Brush_SplitBrushByFace
+
+The incoming brush is NOT freed.
+The incoming face is NOT left referenced.
+==============
+*/
+void Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back)
+{
+ brush_t *b;
+ face_t *nf;
+ vec3_t temp;
+
+ b = Brush_Clone (in);
+ nf = Face_Clone (f);
+
+ nf->texdef = b->brush_faces->texdef;
+ nf->next = b->brush_faces;
+ b->brush_faces = nf;
+
+ Brush_Build( b );
+ Brush_RemoveEmptyFaces ( b );
+ if ( !b->brush_faces )
+ { // completely clipped away
+ Brush_Free (b);
+ *back = NULL;
+ }
+ else
+ {
+ Entity_LinkBrush (in->owner, b);
+ *back = b;
+ }
+
+ b = Brush_Clone (in);
+ nf = Face_Clone (f);
+ // swap the plane winding
+ VectorCopy (nf->planepts[0], temp);
+ VectorCopy (nf->planepts[1], nf->planepts[0]);
+ VectorCopy (temp, nf->planepts[1]);
+
+ nf->texdef = b->brush_faces->texdef;
+ nf->next = b->brush_faces;
+ b->brush_faces = nf;
+
+ Brush_Build( b );
+ Brush_RemoveEmptyFaces ( b );
+ if ( !b->brush_faces )
+ { // completely clipped away
+ Brush_Free (b);
+ *front = NULL;
+ }
+ else
+ {
+ Entity_LinkBrush (in->owner, b);
+ *front = b;
+ }
+}
+
+/*
+=================
+Brush_BestSplitFace
+
+returns the best face to split the brush with.
+return NULL if the brush is convex
+=================
+*/
+face_t *Brush_BestSplitFace(brush_t *b)
+{
+ face_t *face, *f, *bestface;
+ winding_t *front, *back;
+ int splits, tinywindings, value, bestvalue;
+
+ bestvalue = 999999;
+ bestface = NULL;
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ splits = 0;
+ tinywindings = 0;
+ for (f = b->brush_faces; f; f = f->next)
+ {
+ if (f == face) continue;
+ //
+ Winding_SplitEpsilon(f->face_winding, face->plane.normal, face->plane.dist, 0.1, &front, &back);
+
+ if (!front)
+ {
+ Winding_Free(back);
+ }
+ else if (!back)
+ {
+ Winding_Free(front);
+ }
+ else
+ {
+ splits++;
+ if (Winding_IsTiny(front)) tinywindings++;
+ if (Winding_IsTiny(back)) tinywindings++;
+ }
+ }
+ if (splits)
+ {
+ value = splits + 50 * tinywindings;
+ if (value < bestvalue)
+ {
+ bestvalue = value;
+ bestface = face;
+ }
+ }
+ }
+ return bestface;
+}
+
+/*
+=================
+Brush_MakeConvexBrushes
+
+MrE FIXME: this doesn't work because the old
+ Brush_SplitBrushByFace is used
+Turns the brush into a minimal number of convex brushes.
+If the input brush is convex then it will be returned.
+Otherwise the input brush will be freed.
+NOTE: the input brush should have windings for the faces.
+=================
+*/
+brush_t *Brush_MakeConvexBrushes(brush_t *b)
+{
+ brush_t *front, *back, *end;
+ face_t *face;
+
+ b->next = NULL;
+ face = Brush_BestSplitFace(b);
+ if (!face) return b;
+ Brush_SplitBrushByFace(b, face, &front, &back);
+ //this should never happen
+ if (!front && !back) return b;
+ Brush_Free(b);
+ if (!front)
+ return Brush_MakeConvexBrushes(back);
+ b = Brush_MakeConvexBrushes(front);
+ if (back)
+ {
+ for (end = b; end->next; end = end->next);
+ end->next = Brush_MakeConvexBrushes(back);
+ }
+ return b;
+}
+
+/*
+=================
+Brush_Convex
+=================
+*/
+int Brush_Convex(brush_t *b)
+{
+ face_t *face1, *face2;
+
+ for (face1 = b->brush_faces; face1; face1 = face1->next)
+ {
+ if (!face1->face_winding) continue;
+ for (face2 = b->brush_faces; face2; face2 = face2->next)
+ {
+ if (face1 == face2) continue;
+ if (!face2->face_winding) continue;
+ if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
+ face1->plane.normal, face2->plane.normal,
+ face1->plane.dist, face2->plane.dist))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+/*
+=================
+Brush_MoveVertexes_old1
+
+- The input brush must have face windings.
+- The input brush must be a brush with faces that do not intersect.
+- The input brush does not have to be convex.
+- The vertex will not be moved if the movement either causes the
+ brush to have faces that intersect or causes the brush to be
+ flipped inside out.
+ (For instance a tetrahedron can easily be flipped inside out
+ without having faces that intersect.)
+- The created brush does not have to be convex.
+- Returns true if the vertex movement is performed.
+=================
+*/
+
+#define MAX_MOVE_FACES 64
+#define INTERSECT_EPSILON 0.1
+#define POINT_EPSILON 0.3
+
+int Brush_MoveVertex_old1(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
+{
+ face_t *f, *face, *newface, *lastface, *nextface;
+ face_t *movefaces[MAX_MOVE_FACES];
+ int movefacepoints[MAX_MOVE_FACES];
+ winding_t *w, tmpw;
+ int i, j, k, nummovefaces, result;
+ float dot;
+
+ result = false;
+ //
+ tmpw.numpoints = 3;
+ tmpw.maxpoints = 3;
+ VectorAdd(vertex, delta, end);
+ //snap or not?
+ if (bSnap)
+ for (i = 0; i < 3; i++)
+ end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ //chop off triangles from all brush faces that use the to be moved vertex
+ //store pointers to these chopped off triangles in movefaces[]
+ nummovefaces = 0;
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ w = face->face_winding;
+ if (!w) continue;
+ for (i = 0; i < w->numpoints; i++)
+ {
+ if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
+ {
+ if (face->face_winding->numpoints <= 3)
+ {
+ movefacepoints[nummovefaces] = i;
+ movefaces[nummovefaces++] = face;
+ break;
+ }
+ dot = DotProduct(end, face->plane.normal) - face->plane.dist;
+ //if the end point is in front of the face plane
+ if (dot > 0.1)
+ {
+ //fanout triangle subdivision
+ for (k = i; k < i + w->numpoints-3; k++)
+ {
+ VectorCopy(w->points[i], tmpw.points[0]);
+ VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
+ VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
+ //
+ newface = Face_Clone(face);
+ //get the original
+ for (f = face; f->original; f = f->original) ;
+ newface->original = f;
+ //store the new winding
+ if (newface->face_winding) Winding_Free(newface->face_winding);
+ newface->face_winding = Winding_Clone(&tmpw);
+ //get the texture
+ newface->d_texture = Texture_ForName( newface->texdef.name );
+ //add the face to the brush
+ newface->next = b->brush_faces;
+ b->brush_faces = newface;
+ //add this new triangle to the move faces
+ movefacepoints[nummovefaces] = 0;
+ movefaces[nummovefaces++] = newface;
+ }
+ //give the original face a new winding
+ VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
+ VectorCopy(w->points[i], tmpw.points[2]);
+ Winding_Free(face->face_winding);
+ face->face_winding = Winding_Clone(&tmpw);
+ //add the original face to the move faces
+ movefacepoints[nummovefaces] = 2;
+ movefaces[nummovefaces++] = face;
+ }
+ else
+ {
+ //chop a triangle off the face
+ VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[i], tmpw.points[1]);
+ VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
+ //remove the point from the face winding
+ Winding_RemovePoint(w, i);
+ //get texture crap right
+ Face_SetColor(b, face, 1.0);
+ for (j = 0; j < w->numpoints; j++)
+ EmitTextureCoordinates(w->points[j], face->d_texture, face);
+ //make a triangle face
+ newface = Face_Clone(face);
+ //get the original
+ for (f = face; f->original; f = f->original) ;
+ newface->original = f;
+ //store the new winding
+ if (newface->face_winding) Winding_Free(newface->face_winding);
+ newface->face_winding = Winding_Clone(&tmpw);
+ //get the texture
+ newface->d_texture = Texture_ForName( newface->texdef.name );
+ //add the face to the brush
+ newface->next = b->brush_faces;
+ b->brush_faces = newface;
+ //
+ movefacepoints[nummovefaces] = 1;
+ movefaces[nummovefaces++] = newface;
+ }
+ break;
+ }
+ }
+ }
+ //now movefaces contains pointers to triangle faces that
+ //contain the to be moved vertex
+
+ //check if the move is valid
+ int l;
+ vec3_t p1, p2;
+ winding_t *w2;
+ plane_t plane;
+
+ face = NULL;
+ VectorCopy(vertex, tmpw.points[1]);
+ VectorCopy(end, tmpw.points[2]);
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ for (i = 0; i < nummovefaces; i++)
+ {
+ if (face == movefaces[i])
+ break;
+ }
+ if (i < nummovefaces)
+ continue;
+ //the delta vector may not intersect with any of the not move faces
+ if (Winding_VectorIntersect(face->face_winding, &face->plane, vertex, end, INTERSECT_EPSILON))
+ break;
+ //if the end point of the to be moved vertex is near this not move face
+ if (abs(DotProduct(face->plane.normal, end) - face->plane.dist) < 0.5)
+ {
+ //the end point may not be inside or very close to the not move face winding
+ if (Winding_PointInside(face->face_winding, &face->plane, end, 0.5))
+ break;
+ }
+ for (i = 0; i < nummovefaces; i++)
+ {
+ w = movefaces[i]->face_winding;
+ j = movefacepoints[i];
+ for (k = -1; k <= 1; k += 2)
+ {
+ //check if the new edge will not intersect with the not move face
+ VectorCopy(w->points[(j + k + w->numpoints) % w->numpoints], tmpw.points[0]);
+ if (Winding_VectorIntersect(face->face_winding, &face->plane, tmpw.points[0], end, INTERSECT_EPSILON))
+ {
+ //ok the new edge instersects with the not move face
+ //we can't perform the vertex movement
+ //break;
+ }
+ //check if the not move face intersects the "movement winding"
+ Winding_Plane(&tmpw, plane.normal, &plane.dist);
+ w2 = face->face_winding;
+ for (l = 0; l < w2->numpoints; l++)
+ {
+ VectorCopy(w2->points[l], p1);
+ if (Point_Equal(p1, tmpw.points[0], POINT_EPSILON)) continue;
+ VectorCopy(w2->points[(l+1) % w2->numpoints], p2);
+ if (Point_Equal(p2, tmpw.points[0], POINT_EPSILON)) continue;
+ if (Winding_VectorIntersect(&tmpw, &plane, p1, p2, INTERSECT_EPSILON))
+ break;
+ }
+ if (l < w2->numpoints)
+ {
+ //ok this not move face intersects the "movement winding"
+ //we can't perform the vertex movement
+ break;
+ }
+ }
+ if (k <= 1) break;
+ }
+ if (i < nummovefaces)
+ break;
+ }
+ if (!face)
+ {
+ //ok the move was valid
+ //now move all the vertexes of the movefaces
+ for (i = 0; i < nummovefaces; i++)
+ {
+ VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
+ //create new face plane
+ for (j = 0; j < 3; j++)
+ {
+ VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
+ }
+ Face_MakePlane(movefaces[i]);
+ }
+ result = true;
+ }
+ //get texture crap right
+ for (i = 0; i < nummovefaces; i++)
+ {
+ Face_SetColor(b, movefaces[i], 1.0);
+ for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
+ EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
+ }
+
+ //now try to merge faces with their original faces
+ lastface = NULL;
+ for (face = b->brush_faces; face; face = nextface)
+ {
+ nextface = face->next;
+ if (!face->original)
+ {
+ lastface = face;
+ continue;
+ }
+ if (!Plane_Equal(&face->plane, &face->original->plane, false))
+ {
+ lastface = face;
+ continue;
+ }
+ w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
+ if (!w)
+ {
+ lastface = face;
+ continue;
+ }
+ Winding_Free(face->original->face_winding);
+ face->original->face_winding = w;
+ //get texture crap right
+ Face_SetColor(b, face->original, 1.0);
+ for (j = 0; j < face->original->face_winding->numpoints; j++)
+ EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
+ //remove the face that was merged with the original
+ if (lastface) lastface->next = face->next;
+ else b->brush_faces = face->next;
+ Face_Free(face);
+ }
+ return result;
+}
+
+/*
+=================
+Brush_MoveVertexes_old2
+
+- The input brush must be convex
+- The input brush must have face windings.
+- The output brush will be convex.
+- Returns true if the vertex movement is performed.
+=================
+*/
+
+#define MAX_MOVE_FACES 64
+#define INTERSECT_EPSILON 0.1
+#define POINT_EPSILON 0.3
+
+int Brush_MoveVertex_old2(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
+{
+ face_t *f, *face, *newface, *lastface, *nextface;
+ face_t *movefaces[MAX_MOVE_FACES];
+ int movefacepoints[MAX_MOVE_FACES];
+ winding_t *w, tmpw;
+ int i, j, k, nummovefaces, result;
+ float dot;
+
+ result = true;
+ //
+ tmpw.numpoints = 3;
+ tmpw.maxpoints = 3;
+ VectorAdd(vertex, delta, end);
+ //snap or not?
+ if (bSnap)
+ for (i = 0; i < 3; i++)
+ end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ //chop off triangles from all brush faces that use the to be moved vertex
+ //store pointers to these chopped off triangles in movefaces[]
+ nummovefaces = 0;
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ w = face->face_winding;
+ if (!w) continue;
+ for (i = 0; i < w->numpoints; i++)
+ {
+ if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
+ {
+ if (face->face_winding->numpoints <= 3)
+ {
+ movefacepoints[nummovefaces] = i;
+ movefaces[nummovefaces++] = face;
+ break;
+ }
+ dot = DotProduct(end, face->plane.normal) - face->plane.dist;
+ //if the end point is in front of the face plane
+ if (dot > 0.1)
+ {
+ //fanout triangle subdivision
+ for (k = i; k < i + w->numpoints-3; k++)
+ {
+ VectorCopy(w->points[i], tmpw.points[0]);
+ VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
+ VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
+ //
+ newface = Face_Clone(face);
+ //get the original
+ for (f = face; f->original; f = f->original) ;
+ newface->original = f;
+ //store the new winding
+ if (newface->face_winding) Winding_Free(newface->face_winding);
+ newface->face_winding = Winding_Clone(&tmpw);
+ //get the texture
+ newface->d_texture = Texture_ForName( newface->texdef.name );
+ //add the face to the brush
+ newface->next = b->brush_faces;
+ b->brush_faces = newface;
+ //add this new triangle to the move faces
+ movefacepoints[nummovefaces] = 0;
+ movefaces[nummovefaces++] = newface;
+ }
+ //give the original face a new winding
+ VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
+ VectorCopy(w->points[i], tmpw.points[2]);
+ Winding_Free(face->face_winding);
+ face->face_winding = Winding_Clone(&tmpw);
+ //add the original face to the move faces
+ movefacepoints[nummovefaces] = 2;
+ movefaces[nummovefaces++] = face;
+ }
+ else
+ {
+ //chop a triangle off the face
+ VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[i], tmpw.points[1]);
+ VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
+ //remove the point from the face winding
+ Winding_RemovePoint(w, i);
+ //get texture crap right
+ Face_SetColor(b, face, 1.0);
+ for (j = 0; j < w->numpoints; j++)
+ EmitTextureCoordinates(w->points[j], face->d_texture, face);
+ //make a triangle face
+ newface = Face_Clone(face);
+ //get the original
+ for (f = face; f->original; f = f->original) ;
+ newface->original = f;
+ //store the new winding
+ if (newface->face_winding) Winding_Free(newface->face_winding);
+ newface->face_winding = Winding_Clone(&tmpw);
+ //get the texture
+ newface->d_texture = Texture_ForName( newface->texdef.name );
+ //add the face to the brush
+ newface->next = b->brush_faces;
+ b->brush_faces = newface;
+ //
+ movefacepoints[nummovefaces] = 1;
+ movefaces[nummovefaces++] = newface;
+ }
+ break;
+ }
+ }
+ }
+ //now movefaces contains pointers to triangle faces that
+ //contain the to be moved vertex
+
+ //move the vertex
+ for (i = 0; i < nummovefaces; i++)
+ {
+ //move vertex to end position
+ VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
+ //create new face plane
+ for (j = 0; j < 3; j++)
+ {
+ VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
+ }
+ Face_MakePlane(movefaces[i]);
+ }
+ //if the brush is no longer convex
+ if (!Brush_Convex(b))
+ {
+ for (i = 0; i < nummovefaces; i++)
+ {
+ //move the vertex back to the initial position
+ VectorCopy(vertex, movefaces[i]->face_winding->points[movefacepoints[i]]);
+ //create new face plane
+ for (j = 0; j < 3; j++)
+ {
+ VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
+ }
+ Face_MakePlane(movefaces[i]);
+ }
+ result = false;
+ }
+ //get texture crap right
+ for (i = 0; i < nummovefaces; i++)
+ {
+ Face_SetColor(b, movefaces[i], 1.0);
+ for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
+ EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
+ }
+
+ //now try to merge faces with their original faces
+ lastface = NULL;
+ for (face = b->brush_faces; face; face = nextface)
+ {
+ nextface = face->next;
+ if (!face->original)
+ {
+ lastface = face;
+ continue;
+ }
+ if (!Plane_Equal(&face->plane, &face->original->plane, false))
+ {
+ lastface = face;
+ continue;
+ }
+ w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
+ if (!w)
+ {
+ lastface = face;
+ continue;
+ }
+ Winding_Free(face->original->face_winding);
+ face->original->face_winding = w;
+ //get texture crap right
+ Face_SetColor(b, face->original, 1.0);
+ for (j = 0; j < face->original->face_winding->numpoints; j++)
+ EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
+ //remove the face that was merged with the original
+ if (lastface) lastface->next = face->next;
+ else b->brush_faces = face->next;
+ Face_Free(face);
+ }
+ return result;
+}
+
+/*
+=================
+Brush_MoveVertexes
+
+- The input brush must be convex
+- The input brush must have face windings.
+- The output brush will be convex.
+- Returns true if the WHOLE vertex movement is performed.
+=================
+*/
+
+#define MAX_MOVE_FACES 64
+
+int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
+{
+ face_t *f, *face, *newface, *lastface, *nextface;
+ face_t *movefaces[MAX_MOVE_FACES];
+ int movefacepoints[MAX_MOVE_FACES];
+ winding_t *w, tmpw;
+ vec3_t start, mid;
+ plane_t plane;
+ int i, j, k, nummovefaces, result, done;
+ float dot, front, back, frac, smallestfrac;
+
+ result = true;
+ //
+ tmpw.numpoints = 3;
+ tmpw.maxpoints = 3;
+ VectorCopy(vertex, start);
+ VectorAdd(vertex, delta, end);
+ //snap or not?
+ if (bSnap)
+ for (i = 0; i < 3; i++)
+ end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ //
+ VectorCopy(end, mid);
+ //if the start and end are the same
+ if (Point_Equal(start, end, 0.3)) return false;
+ //the end point may not be the same as another vertex
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ w = face->face_winding;
+ if (!w) continue;
+ for (i = 0; i < w->numpoints; i++)
+ {
+ if (Point_Equal(w->points[i], end, 0.3))
+ {
+ VectorCopy(vertex, end);
+ return false;
+ }
+ }
+ }
+ //
+ done = false;
+ while(!done)
+ {
+ //chop off triangles from all brush faces that use the to be moved vertex
+ //store pointers to these chopped off triangles in movefaces[]
+ nummovefaces = 0;
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ w = face->face_winding;
+ if (!w) continue;
+ for (i = 0; i < w->numpoints; i++)
+ {
+ if (Point_Equal(w->points[i], start, 0.2))
+ {
+ if (face->face_winding->numpoints <= 3)
+ {
+ movefacepoints[nummovefaces] = i;
+ movefaces[nummovefaces++] = face;
+ break;
+ }
+ dot = DotProduct(end, face->plane.normal) - face->plane.dist;
+ //if the end point is in front of the face plane
+ if (dot > 0.1)
+ {
+ //fanout triangle subdivision
+ for (k = i; k < i + w->numpoints-3; k++)
+ {
+ VectorCopy(w->points[i], tmpw.points[0]);
+ VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
+ VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
+ //
+ newface = Face_Clone(face);
+ //get the original
+ for (f = face; f->original; f = f->original) ;
+ newface->original = f;
+ //store the new winding
+ if (newface->face_winding) Winding_Free(newface->face_winding);
+ newface->face_winding = Winding_Clone(&tmpw);
+ //get the texture
+ newface->d_texture = Texture_ForName( newface->texdef.name );
+ //add the face to the brush
+ newface->next = b->brush_faces;
+ b->brush_faces = newface;
+ //add this new triangle to the move faces
+ movefacepoints[nummovefaces] = 0;
+ movefaces[nummovefaces++] = newface;
+ }
+ //give the original face a new winding
+ VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
+ VectorCopy(w->points[i], tmpw.points[2]);
+ Winding_Free(face->face_winding);
+ face->face_winding = Winding_Clone(&tmpw);
+ //add the original face to the move faces
+ movefacepoints[nummovefaces] = 2;
+ movefaces[nummovefaces++] = face;
+ }
+ else
+ {
+ //chop a triangle off the face
+ VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[i], tmpw.points[1]);
+ VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
+ //remove the point from the face winding
+ Winding_RemovePoint(w, i);
+ //get texture crap right
+ Face_SetColor(b, face, 1.0);
+ for (j = 0; j < w->numpoints; j++)
+ EmitTextureCoordinates(w->points[j], face->d_texture, face);
+ //make a triangle face
+ newface = Face_Clone(face);
+ //get the original
+ for (f = face; f->original; f = f->original) ;
+ newface->original = f;
+ //store the new winding
+ if (newface->face_winding) Winding_Free(newface->face_winding);
+ newface->face_winding = Winding_Clone(&tmpw);
+ //get the texture
+ newface->d_texture = Texture_ForName( newface->texdef.name );
+ //add the face to the brush
+ newface->next = b->brush_faces;
+ b->brush_faces = newface;
+ //
+ movefacepoints[nummovefaces] = 1;
+ movefaces[nummovefaces++] = newface;
+ }
+ break;
+ }
+ }
+ }
+ //now movefaces contains pointers to triangle faces that
+ //contain the to be moved vertex
+ //
+ done = true;
+ VectorCopy(end, mid);
+ smallestfrac = 1;
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ //check if there is a move face that has this face as the original
+ for (i = 0; i < nummovefaces; i++)
+ {
+ if (movefaces[i]->original == face) break;
+ }
+ if (i >= nummovefaces) continue;
+ //check if the original is not a move face itself
+ for (j = 0; j < nummovefaces; j++)
+ {
+ if (face == movefaces[j]) break;
+ }
+ //if the original is not a move face itself
+ if (j >= nummovefaces)
+ {
+ memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane_t));
+ }
+ else
+ {
+ k = movefacepoints[j];
+ w = movefaces[j]->face_winding;
+ VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[0]);
+ VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[1]);
+ //
+ k = movefacepoints[i];
+ w = movefaces[i]->face_winding;
+ VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[2]);
+ if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
+ {
+ VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[2]);
+ if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
+ //this should never happen otherwise the face merge did a crappy job a previous pass
+ continue;
+ }
+ }
+ //now we've got the plane to check agains
+ front = DotProduct(start, plane.normal) - plane.dist;
+ back = DotProduct(end, plane.normal) - plane.dist;
+ //if the whole move is at one side of the plane
+ if (front < 0.01 && back < 0.01) continue;
+ if (front > -0.01 && back > -0.01) continue;
+ //if there's no movement orthogonal to this plane at all
+ if (fabs(front-back) < 0.001) continue;
+ //ok first only move till the plane is hit
+ frac = front/(front-back);
+ if (frac < smallestfrac)
+ {
+ mid[0] = start[0] + (end[0] - start[0]) * frac;
+ mid[1] = start[1] + (end[1] - start[1]) * frac;
+ mid[2] = start[2] + (end[2] - start[2]) * frac;
+ smallestfrac = frac;
+ }
+ //
+ done = false;
+ }
+
+ //move the vertex
+ for (i = 0; i < nummovefaces; i++)
+ {
+ //move vertex to end position
+ VectorCopy(mid, movefaces[i]->face_winding->points[movefacepoints[i]]);
+ //create new face plane
+ for (j = 0; j < 3; j++)
+ {
+ VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
+ }
+ Face_MakePlane(movefaces[i]);
+ if (VectorLength(movefaces[i]->plane.normal) < 0.1)
+ result = false;
+ }
+ //if the brush is no longer convex
+ if (!result || !Brush_Convex(b))
+ {
+ for (i = 0; i < nummovefaces; i++)
+ {
+ //move the vertex back to the initial position
+ VectorCopy(start, movefaces[i]->face_winding->points[movefacepoints[i]]);
+ //create new face plane
+ for (j = 0; j < 3; j++)
+ {
+ VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
+ }
+ Face_MakePlane(movefaces[i]);
+ }
+ result = false;
+ VectorCopy(start, end);
+ done = true;
+ }
+ else
+ {
+ VectorCopy(mid, start);
+ }
+ //get texture crap right
+ for (i = 0; i < nummovefaces; i++)
+ {
+ Face_SetColor(b, movefaces[i], 1.0);
+ for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
+ EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
+ }
+
+ //now try to merge faces with their original faces
+ lastface = NULL;
+ for (face = b->brush_faces; face; face = nextface)
+ {
+ nextface = face->next;
+ if (!face->original)
+ {
+ lastface = face;
+ continue;
+ }
+ if (!Plane_Equal(&face->plane, &face->original->plane, false))
+ {
+ lastface = face;
+ continue;
+ }
+ w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
+ if (!w)
+ {
+ lastface = face;
+ continue;
+ }
+ Winding_Free(face->original->face_winding);
+ face->original->face_winding = w;
+ //get texture crap right
+ Face_SetColor(b, face->original, 1.0);
+ for (j = 0; j < face->original->face_winding->numpoints; j++)
+ EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
+ //remove the face that was merged with the original
+ if (lastface) lastface->next = face->next;
+ else b->brush_faces = face->next;
+ Face_Free(face);
+ }
+ }
+ return result;
+}
+
+/*
+=================
+Brush_InsertVertexBetween
+=================
+*/
+int Brush_InsertVertexBetween(brush_t *b, vec3_t p1, vec3_t p2)
+{
+ face_t *face;
+ winding_t *w, *neww;
+ vec3_t point;
+ int i, insert;
+
+ if (Point_Equal(p1, p2, 0.4))
+ return false;
+ VectorAdd(p1, p2, point);
+ VectorScale(point, 0.5, point);
+ insert = false;
+ //the end point may not be the same as another vertex
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ w = face->face_winding;
+ if (!w) continue;
+ neww = NULL;
+ for (i = 0; i < w->numpoints; i++)
+ {
+ if (!Point_Equal(w->points[i], p1, 0.1))
+ continue;
+ if (Point_Equal(w->points[(i+1) % w->numpoints], p2, 0.1))
+ {
+ neww = Winding_InsertPoint(w, point, (i+1) % w->numpoints);
+ break;
+ }
+ else if (Point_Equal(w->points[(i-1+w->numpoints) % w->numpoints], p2, 0.3))
+ {
+ neww = Winding_InsertPoint(w, point, i);
+ break;
+ }
+ }
+ if (neww)
+ {
+ Winding_Free(face->face_winding);
+ face->face_winding = neww;
+ insert = true;
+ }
+ }
+ return insert;
+}
+
+
+/*
+=================
+Brush_ResetFaceOriginals
+=================
+*/
+void Brush_ResetFaceOriginals(brush_t *b)
+{
+ face_t *face;
+
+ for (face = b->brush_faces; face; face = face->next)
+ {
+ face->original = NULL;
+ }
+}
+
+/*
+=================
+Brush_Parse
+
+The brush is NOT linked to any list
+=================
+*/
+//++timo FIXME: when using old brush primitives, the test loop for "Brush" and "patchDef2" "patchDef3" is ran
+// before each face parsing. It works, but it's a performance hit
+brush_t *Brush_Parse (void)
+{
+ brush_t *b;
+ face_t *f;
+ int i,j;
+
+ g_qeglobals.d_parsed_brushes++;
+ b = Brush_Alloc();
+
+ do
+ {
+ if (!GetToken (true))
+ break;
+ if (!strcmp (token, "}") )
+ break;
+
+ // handle "Brush" primitive
+ if (strcmpi(token, "brushDef") == 0)
+ {
+ // Timo parsing new brush format
+ g_qeglobals.bPrimitBrushes=true;
+ // check the map is not mixing the two kinds of brushes
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (g_qeglobals.bOldBrushes)
+ Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
+ }
+ //++Timo write new brush primitive -> old conversion code for Q3->Q2 conversions ?
+ else
+ Sys_Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
+
+ BrushPrimit_Parse(b);
+ if (b == NULL)
+ {
+ Warning ("parsing brush primitive");
+ return NULL;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ if ( strcmpi( token, "terrainDef" ) == 0 )
+ {
+ free (b);
+
+ b = Terrain_Parse();
+ if (b == NULL)
+ {
+ Warning ("parsing terrain/brush");
+ return NULL;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ if (strcmpi(token, "patchDef2") == 0 || strcmpi(token, "patchDef3") == 0)
+ {
+ free (b);
+
+ // double string compare but will go away soon
+ b = Patch_Parse(strcmpi(token, "patchDef2") == 0);
+ if (b == NULL)
+ {
+ Warning ("parsing patch/brush");
+ return NULL;
+ }
+ else
+ {
+ continue;
+ }
+ // handle inline patch
+ }
+ else
+ {
+ // Timo parsing old brush format
+ g_qeglobals.bOldBrushes=true;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // check the map is not mixing the two kinds of brushes
+ if (g_qeglobals.bPrimitBrushes)
+ Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
+ // set the "need" conversion flag
+ g_qeglobals.bNeedConvert=true;
+ }
+
+ f = Face_Alloc();
+
+ // add the brush to the end of the chain, so
+ // loading and saving a map doesn't reverse the order
+
+ f->next = NULL;
+ if (!b->brush_faces)
+ {
+ b->brush_faces = f;
+ }
+ else
+ {
+ face_t *scan;
+ for (scan=b->brush_faces ; scan->next ; scan=scan->next)
+ ;
+ scan->next = f;
+ }
+
+ // read the three point plane definition
+ for (i=0 ; i<3 ; i++)
+ {
+ if (i != 0)
+ GetToken (true);
+ if (strcmp (token, "(") )
+ {
+ Warning ("parsing brush");
+ return NULL;
+ }
+
+ for (j=0 ; j<3 ; j++)
+ {
+ GetToken (false);
+ f->planepts[i][j] = atof(token);
+ }
+
+ GetToken (false);
+ if (strcmp (token, ")") )
+ {
+ Warning ("parsing brush");
+ return NULL;
+ }
+ }
+ }
+
+ // Timo
+ // if we have a surface plugin, we'll call the plugin parsing
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ GETPLUGINTEXDEF(f)->ParseTexdef();
+ }
+ else
+ {
+
+ // read the texturedef
+ GetToken (false);
+ f->texdef.SetName(token);
+ if (token[0] == '(')
+ {
+ int i = 32;
+ }
+ GetToken (false);
+ f->texdef.shift[0] = atoi(token);
+ GetToken (false);
+ f->texdef.shift[1] = atoi(token);
+ GetToken (false);
+ f->texdef.rotate = atoi(token);
+ GetToken (false);
+ f->texdef.scale[0] = atof(token);
+ GetToken (false);
+ f->texdef.scale[1] = atof(token);
+
+ // the flags and value field aren't necessarily present
+ f->d_texture = Texture_ForName( f->texdef.name );
+ f->texdef.flags = f->d_texture->flags;
+ f->texdef.value = f->d_texture->value;
+ f->texdef.contents = f->d_texture->contents;
+
+ if (TokenAvailable ())
+ {
+ GetToken (false);
+ f->texdef.contents = atoi(token);
+ GetToken (false);
+ f->texdef.flags = atoi(token);
+ GetToken (false);
+ f->texdef.value = atoi(token);
+ }
+
+ }
+ } while (1);
+
+ return b;
+}
+
+/*
+=================
+QERApp_MapPrintf_FILE
+callback for surface properties plugin
+must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
+=================
+*/
+// carefully initialize !
+FILE * g_File;
+void WINAPI QERApp_MapPrintf_FILE( char *text, ... )
+{
+ va_list argptr;
+ char buf[32768];
+
+ va_start (argptr,text);
+ vsprintf (buf, text,argptr);
+ va_end (argptr);
+
+ fprintf( g_File, buf );
+}
+
+
+/*
+==============
+Brush_SetEpair
+sets an epair for the given brush
+==============
+*/
+void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue)
+{
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (b->patchBrush)
+ {
+ Patch_SetEpair(b->pPatch, pKey, pValue);
+ }
+ else if (b->terrainBrush)
+ {
+ Terrain_SetEpair(b->pTerrain, pKey, pValue);
+ }
+ else
+ {
+ SetKeyValue(b->epairs, pKey, pValue);
+ }
+ }
+ else
+ {
+ Sys_Printf("Can only set key/values in Brush primitive mode\n");
+ }
+}
+
+/*
+=================
+Brush_GetKeyValue
+=================
+*/
+const char* Brush_GetKeyValue(brush_t *b, const char *pKey)
+{
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (b->patchBrush)
+ {
+ return Patch_GetKeyValue(b->pPatch, pKey);
+ }
+ else if (b->terrainBrush)
+ {
+ return Terrain_GetKeyValue(b->pTerrain, pKey);
+ }
+ else
+ {
+ return ValueForKey(b->epairs, pKey);
+ }
+ }
+ else
+ {
+ Sys_Printf("Can only set brush/patch key/values in Brush primitive mode\n");
+ }
+ return "";
+}
+
+/*
+=================
+Brush_Write
+save all brushes as Brush primitive format
+=================
+*/
+void Brush_Write (brush_t *b, FILE *f)
+{
+ epair_t *ep;
+ face_t *fa;
+ char *pname;
+ int i;
+
+ if (b->patchBrush)
+ {
+ Patch_Write(b->pPatch, f);
+ return;
+ }
+ if ( b->pTerrain )
+ {
+ Terrain_Write(b->pTerrain, f);
+ return;
+ }
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // save brush primitive format
+ fprintf (f, "{\nbrushDef\n{\n");
+ // brush epairs
+ if (b->epairs)
+ for (ep = b->epairs ; ep ; ep=ep->next)
+ fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
+ for (fa=b->brush_faces ; fa ; fa=fa->next)
+ {
+ // save planepts
+ for (i=0 ; i<3 ; i++)
+ {
+ fprintf(f, "( ");
+ for (int j = 0; j < 3; j++)
+ if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
+ fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
+ else
+ fprintf(f, "%f ", fa->planepts[i][j]);
+ fprintf(f, ") ");
+ }
+ // save texture coordinates
+ fprintf(f,"( ( ");
+ for (i=0 ; i<3 ; i++)
+ if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
+ fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
+ else
+ fprintf(f,"%f ",fa->brushprimit_texdef.coords[0][i]);
+ fprintf(f,") ( ");
+ for (i=0 ; i<3 ; i++)
+ if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
+ fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
+ else
+ fprintf(f,"%f ",fa->brushprimit_texdef.coords[1][i]);
+ fprintf(f,") ) ");
+ // save texture attribs
+ //++timo surface properties plugin not implemented for brush primitives
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ Sys_Printf("WARNING: surface properties plugin not supported with brush primitives (yet)\n");
+
+ char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
+ fprintf(f, "%s ", pName );
+ fprintf(f, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
+ }
+ fprintf (f, "}\n}\n");
+ }
+ else
+ {
+ fprintf (f, "{\n");
+ for (fa=b->brush_faces ; fa ; fa=fa->next)
+ {
+ for (i=0 ; i<3 ; i++)
+ {
+ fprintf(f, "( ");
+ for (int j = 0; j < 3; j++)
+ {
+ if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
+ fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
+ else
+ fprintf(f, "%f ", fa->planepts[i][j]);
+ }
+ fprintf(f, ") ");
+ }
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ g_File = f;
+#ifdef _DEBUG
+ if (!fa->pData)
+ Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
+ else
+#endif
+ GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_FILE );
+ }
+ else
+ {
+ pname = fa->texdef.name;
+ if (pname[0] == 0)
+ pname = "unnamed";
+
+ fprintf (f, "%s %i %i %i ", pname,
+ (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
+ (int)fa->texdef.rotate);
+
+ if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
+ fprintf (f, "%i ", (int)fa->texdef.scale[0]);
+ else
+ fprintf (f, "%f ", (float)fa->texdef.scale[0]);
+ if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
+ fprintf (f, "%i", (int)fa->texdef.scale[1]);
+ else
+ fprintf (f, "%f", (float)fa->texdef.scale[1]);
+
+ fprintf (f, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
+ }
+ fprintf (f, "\n");
+ }
+ fprintf (f, "}\n");
+ }
+}
+
+/*
+=================
+QERApp_MapPrintf_MEMFILE
+callback for surface properties plugin
+must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
+=================
+*/
+// carefully initialize !
+CMemFile * g_pMemFile;
+void WINAPI QERApp_MapPrintf_MEMFILE( char *text, ... )
+{
+ va_list argptr;
+ char buf[32768];
+
+ va_start (argptr,text);
+ vsprintf (buf, text,argptr);
+ va_end (argptr);
+
+ MemFile_fprintf( g_pMemFile, buf );
+}
+
+/*
+=================
+Brush_Write to a CMemFile*
+save all brushes as Brush primitive format
+=================
+*/
+void Brush_Write (brush_t *b, CMemFile *pMemFile)
+{
+ epair_t *ep;
+ face_t *fa;
+ char *pname;
+ int i;
+
+ if (b->patchBrush)
+ {
+ Patch_Write(b->pPatch, pMemFile);
+ return;
+ }
+ if (b->terrainBrush)
+ {
+ Terrain_Write(b->pTerrain, pMemFile);
+ return;
+ }
+ //++timo NOTE: it's not very difficult to add since the surface properties plugin
+ // writes throught a printf-style function prototype
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ Sys_Printf("WARNING: Brush_Write to a CMemFile and Surface Properties plugin not done\n");
+ }
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // brush primitive format
+ MemFile_fprintf (pMemFile, "{\nBrushDef\n{\n");
+ // brush epairs
+ if (b->epairs)
+ for( ep = b->epairs ; ep ; ep=ep->next )
+ MemFile_fprintf (pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value );
+ for (fa=b->brush_faces ; fa ; fa=fa->next)
+ {
+ // save planepts
+ for (i=0 ; i<3 ; i++)
+ {
+ MemFile_fprintf(pMemFile, "( ");
+ for (int j = 0; j < 3; j++)
+ if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
+ MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
+ else
+ MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
+ MemFile_fprintf(pMemFile, ") ");
+ }
+ // save texture coordinates
+ MemFile_fprintf(pMemFile,"( ( ");
+ for (i=0 ; i<3 ; i++)
+ if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
+ MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
+ else
+ MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[0][i]);
+ MemFile_fprintf(pMemFile,") ( ");
+ for (i=0 ; i<3 ; i++)
+ if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
+ MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
+ else
+ MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[1][i]);
+ MemFile_fprintf(pMemFile,") ) ");
+ // save texture attribs
+ char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
+ MemFile_fprintf(pMemFile, "%s ", pName);
+ MemFile_fprintf(pMemFile, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
+ }
+ MemFile_fprintf (pMemFile, "}\n}\n");
+ }
+ else
+ {
+ // old brushes format
+ // also handle surface properties plugin
+ MemFile_fprintf (pMemFile, "{\n");
+ for (fa=b->brush_faces ; fa ; fa=fa->next)
+ {
+ for (i=0 ; i<3 ; i++)
+ {
+ MemFile_fprintf(pMemFile, "( ");
+ for (int j = 0; j < 3; j++)
+ {
+ if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
+ MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
+ else
+ MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
+ }
+ MemFile_fprintf(pMemFile, ") ");
+ }
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ g_pMemFile = pMemFile;
+#ifdef _DEBUG
+ if (!fa->pData)
+ Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
+ else
+#endif
+ GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_MEMFILE );
+ }
+ else
+ {
+ pname = fa->texdef.name;
+ if (pname[0] == 0)
+ pname = "unnamed";
+
+ MemFile_fprintf (pMemFile, "%s %i %i %i ", pname,
+ (int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
+ (int)fa->texdef.rotate);
+
+ if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
+ MemFile_fprintf (pMemFile, "%i ", (int)fa->texdef.scale[0]);
+ else
+ MemFile_fprintf (pMemFile, "%f ", (float)fa->texdef.scale[0]);
+ if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
+ MemFile_fprintf (pMemFile, "%i", (int)fa->texdef.scale[1]);
+ else
+ MemFile_fprintf (pMemFile, "%f", (float)fa->texdef.scale[1]);
+
+ MemFile_fprintf (pMemFile, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
+ }
+ MemFile_fprintf (pMemFile, "\n");
+ }
+ MemFile_fprintf (pMemFile, "}\n");
+ }
+
+
+}
+
+
+/*
+=============
+Brush_Create
+
+Create non-textured blocks for entities
+The brush is NOT linked to any list
+=============
+*/
+brush_t *Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef)
+{
+ int i, j;
+ vec3_t pts[4][2];
+ face_t *f;
+ brush_t *b;
+
+ // brush primitive mode : convert texdef to brushprimit_texdef ?
+ // most of the time texdef is empty
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // check texdef is empty .. if there are cases it's not we need to write some conversion code
+ if (texdef->shift[0]!=0 || texdef->shift[1]!=0 || texdef->scale[0]!=0 || texdef->scale[1]!=0 || texdef->rotate!=0)
+ Sys_Printf("Warning : non-zero texdef detected in Brush_Create .. need brush primitive conversion\n");
+ }
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (maxs[i] < mins[i])
+ Error ("Brush_InitSolid: backwards");
+ }
+
+ b = Brush_Alloc();
+
+ pts[0][0][0] = mins[0];
+ pts[0][0][1] = mins[1];
+
+ pts[1][0][0] = mins[0];
+ pts[1][0][1] = maxs[1];
+
+ pts[2][0][0] = maxs[0];
+ pts[2][0][1] = maxs[1];
+
+ pts[3][0][0] = maxs[0];
+ pts[3][0][1] = mins[1];
+
+ for (i=0 ; i<4 ; i++)
+ {
+ pts[i][0][2] = mins[2];
+ pts[i][1][0] = pts[i][0][0];
+ pts[i][1][1] = pts[i][0][1];
+ pts[i][1][2] = maxs[2];
+ }
+
+ for (i=0 ; i<4 ; i++)
+ {
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+ j = (i+1)%4;
+
+ VectorCopy (pts[j][1], f->planepts[0]);
+ VectorCopy (pts[i][1], f->planepts[1]);
+ VectorCopy (pts[i][0], f->planepts[2]);
+ }
+
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorCopy (pts[0][1], f->planepts[0]);
+ VectorCopy (pts[1][1], f->planepts[1]);
+ VectorCopy (pts[2][1], f->planepts[2]);
+
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorCopy (pts[2][0], f->planepts[0]);
+ VectorCopy (pts[1][0], f->planepts[1]);
+ VectorCopy (pts[0][0], f->planepts[2]);
+
+ return b;
+}
+
+/*
+=============
+Brush_CreatePyramid
+
+Create non-textured pyramid for light entities
+The brush is NOT linked to any list
+=============
+*/
+brush_t *Brush_CreatePyramid (vec3_t mins, vec3_t maxs, texdef_t *texdef)
+{
+ //++timo handle new brush primitive ? return here ??
+ return Brush_Create(mins, maxs, texdef);
+
+ for (int i=0 ; i<3 ; i++)
+ if (maxs[i] < mins[i])
+ Error ("Brush_InitSolid: backwards");
+
+ brush_t* b = Brush_Alloc();
+
+ vec3_t corners[4];
+
+ float fMid = Q_rint(mins[2] + (Q_rint((maxs[2] - mins[2]) / 2)));
+
+ corners[0][0] = mins[0];
+ corners[0][1] = mins[1];
+ corners[0][2] = fMid;
+
+ corners[1][0] = mins[0];
+ corners[1][1] = maxs[1];
+ corners[1][2] = fMid;
+
+ corners[2][0] = maxs[0];
+ corners[2][1] = maxs[1];
+ corners[2][2] = fMid;
+
+ corners[3][0] = maxs[0];
+ corners[3][1] = mins[1];
+ corners[3][2] = fMid;
+
+ vec3_t top, bottom;
+
+ top[0] = Q_rint(mins[0] + ((maxs[0] - mins[0]) / 2));
+ top[1] = Q_rint(mins[1] + ((maxs[1] - mins[1]) / 2));
+ top[2] = Q_rint(maxs[2]);
+
+ VectorCopy(top, bottom);
+ bottom[2] = mins[2];
+
+ // sides
+ for (i = 0; i < 4; i++)
+ {
+ face_t* f = Face_Alloc();
+ f->texdef = *texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+ int j = (i+1)%4;
+
+ VectorCopy (top, f->planepts[0]);
+ VectorCopy (corners[i], f->planepts[1]);
+ VectorCopy(corners[j], f->planepts[2]);
+
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorCopy (bottom, f->planepts[2]);
+ VectorCopy (corners[i], f->planepts[1]);
+ VectorCopy(corners[j], f->planepts[0]);
+ }
+
+ return b;
+}
+
+
+
+
+/*
+=============
+Brush_MakeSided
+
+Makes the current brush have the given number of 2d sides
+=============
+*/
+void Brush_MakeSided (int sides)
+{
+ int i, axis;
+ vec3_t mins, maxs;
+ brush_t *b;
+ texdef_t *texdef;
+ face_t *f;
+ vec3_t mid;
+ float width;
+ float sv, cv;
+
+ if (sides < 3)
+ {
+ Sys_Status ("Bad sides number", 0);
+ return;
+ }
+
+ if (sides >= MAX_POINTS_ON_WINDING-4)
+ {
+ Sys_Printf("too many sides.\n");
+ return;
+ }
+
+ if (!QE_SingleBrush ())
+ {
+ Sys_Status ("Must have a single brush selected", 0 );
+ return;
+ }
+
+ b = selected_brushes.next;
+ VectorCopy (b->mins, mins);
+ VectorCopy (b->maxs, maxs);
+ texdef = &g_qeglobals.d_texturewin.texdef;
+
+ Brush_Free (b);
+
+ if (g_pParentWnd->ActiveXY())
+ {
+ switch(g_pParentWnd->ActiveXY()->GetViewType())
+ {
+ case XY: axis = 2; break;
+ case XZ: axis = 1; break;
+ case YZ: axis = 0; break;
+ }
+ }
+ else
+ {
+ axis = 2;
+ }
+
+ // find center of brush
+ width = 8;
+ for (i = 0; i < 3; i++)
+ {
+ mid[i] = (maxs[i] + mins[i]) * 0.5;
+ if (i == axis) continue;
+ if ((maxs[i] - mins[i]) * 0.5 > width)
+ width = (maxs[i] - mins[i]) * 0.5;
+ }
+
+ b = Brush_Alloc();
+
+ // create top face
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ f->planepts[2][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[2][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[2][axis] = maxs[axis];
+ f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = maxs[axis];
+ f->planepts[0][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[0][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[0][axis] = maxs[axis];
+
+ // create bottom face
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ f->planepts[0][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[0][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[0][axis] = mins[axis];
+ f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = mins[axis];
+ f->planepts[2][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[2][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[2][axis] = mins[axis];
+
+ for (i=0 ; i<sides ; i++)
+ {
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ sv = sin (i*3.14159265*2/sides);
+ cv = cos (i*3.14159265*2/sides);
+
+ f->planepts[0][(axis+1)%3] = floor(mid[(axis+1)%3]+width*cv+0.5);
+ f->planepts[0][(axis+2)%3] = floor(mid[(axis+2)%3]+width*sv+0.5);
+ f->planepts[0][axis] = mins[axis];
+
+ f->planepts[1][(axis+1)%3] = f->planepts[0][(axis+1)%3];
+ f->planepts[1][(axis+2)%3] = f->planepts[0][(axis+2)%3];
+ f->planepts[1][axis] = maxs[axis];
+
+ f->planepts[2][(axis+1)%3] = floor(f->planepts[0][(axis+1)%3] - width*sv + 0.5);
+ f->planepts[2][(axis+2)%3] = floor(f->planepts[0][(axis+2)%3] + width*cv + 0.5);
+ f->planepts[2][axis] = maxs[axis];
+ }
+
+ Brush_AddToList (b, &selected_brushes);
+
+ Entity_LinkBrush (world_entity, b);
+
+ Brush_Build( b );
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+
+/*
+=============
+Brush_Free
+
+Frees the brush with all of its faces and display list.
+Unlinks the brush from whichever chain it is in.
+Decrements the owner entity's brushcount.
+Removes owner entity if this was the last brush
+unless owner is the world.
+Removes from groups
+=============
+*/
+void Brush_Free (brush_t *b, bool bRemoveNode)
+{
+ face_t *f, *next;
+ epair_t *ep, *enext;
+
+ // remove from group
+ if (bRemoveNode)
+ Group_RemoveBrush(b);
+
+ // free the patch if it's there
+ if (b->patchBrush)
+ {
+ Patch_Delete(b->pPatch);
+ }
+
+ if( b->terrainBrush )
+ {
+ Terrain_Delete( b->pTerrain );
+ }
+
+ // free faces
+ for (f=b->brush_faces ; f ; f=next)
+ {
+ next = f->next;
+ Face_Free( f );
+ }
+
+ //Timo : free brush epairs
+ for (ep = b->epairs ; ep ; ep=enext )
+ {
+ enext = ep->next;
+ free (ep->key);
+ free (ep->value);
+ free (ep);
+ }
+
+ // unlink from active/selected list
+ if (b->next)
+ Brush_RemoveFromList (b);
+
+ // unlink from entity list
+ if (b->onext)
+ Entity_UnlinkBrush (b);
+
+ free (b);
+}
+
+/*
+=============
+Face_MemorySize
+=============
+*/
+int Face_MemorySize(face_t *f )
+{
+ int size = 0;
+
+ if (f->face_winding)
+ {
+ size += _msize(f->face_winding);
+ }
+ //f->texdef.~texdef_t();;
+ size += _msize(f);
+ return size;
+}
+
+/*
+=============
+Brush_MemorySize
+=============
+*/
+int Brush_MemorySize(brush_t *b)
+{
+ face_t *f;
+ epair_t *ep;
+ int size = 0;
+
+ //
+ if (b->patchBrush)
+ {
+ size += Patch_MemorySize(b->pPatch);
+ }
+ if (b->terrainBrush)
+ {
+ size += Terrain_MemorySize(b->pTerrain);
+ }
+ //
+ for (f = b->brush_faces; f; f = f->next)
+ {
+ size += Face_MemorySize(f);
+ }
+ //
+ for (ep = b->epairs; ep; ep = ep->next )
+ {
+ size += _msize(ep->key);
+ size += _msize(ep->value);
+ size += _msize(ep);
+ }
+ size += _msize(b);
+ return size;
+}
+
+
+/*
+============
+Brush_Clone
+
+Does NOT add the new brush to any lists
+============
+*/
+brush_t *Brush_Clone (brush_t *b)
+{
+ brush_t *n = NULL;
+ face_t *f, *nf;
+
+ if (b->patchBrush)
+ {
+ patchMesh_t *p = Patch_Duplicate(b->pPatch);
+ Brush_RemoveFromList(p->pSymbiot);
+ Entity_UnlinkBrush(p->pSymbiot);
+ n = p->pSymbiot;
+ }
+ else if (b->terrainBrush)
+ {
+ terrainMesh_t *p = Terrain_Duplicate(b->pTerrain);
+ Brush_RemoveFromList(p->pSymbiot);
+ Entity_UnlinkBrush(p->pSymbiot);
+ n = p->pSymbiot;
+ }
+ else
+ {
+ n = Brush_Alloc();
+ n->numberId = g_nBrushId++;
+ n->owner = b->owner;
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ nf = Face_Clone( f );
+ nf->next = n->brush_faces;
+ n->brush_faces = nf;
+ }
+ }
+
+ return n;
+}
+
+
+
+/*
+============
+Brush_Clone
+
+Does NOT add the new brush to any lists
+============
+*/
+brush_t *Brush_FullClone(brush_t *b)
+{
+ brush_t *n = NULL;
+ face_t *f, *nf, *f2, *nf2;
+ int j;
+
+ if (b->patchBrush)
+ {
+ patchMesh_t *p = Patch_Duplicate(b->pPatch);
+ Brush_RemoveFromList(p->pSymbiot);
+ Entity_UnlinkBrush(p->pSymbiot);
+ n = p->pSymbiot;
+ n->owner = b->owner;
+ Brush_Build(n);
+ }
+ else if (b->terrainBrush)
+ {
+ terrainMesh_t *p = Terrain_Duplicate(b->pTerrain);
+ Brush_RemoveFromList(p->pSymbiot);
+ Entity_UnlinkBrush(p->pSymbiot);
+ n = p->pSymbiot;
+ n->owner = b->owner;
+ Brush_Build(n);
+ }
+ else
+ {
+ n = Brush_Alloc();
+ n->numberId = g_nBrushId++;
+ n->owner = b->owner;
+ VectorCopy(b->mins, n->mins);
+ VectorCopy(b->maxs, n->maxs);
+ //
+ for (f = b->brush_faces; f; f = f->next)
+ {
+ if (f->original) continue;
+ nf = Face_FullClone(f);
+ nf->next = n->brush_faces;
+ n->brush_faces = nf;
+ //copy all faces that have the original set to this face
+ for (f2 = b->brush_faces; f2; f2 = f2->next)
+ {
+ if (f2->original == f)
+ {
+ nf2 = Face_FullClone(f2);
+ nf2->next = n->brush_faces;
+ n->brush_faces = nf2;
+ //set original
+ nf2->original = nf;
+ }
+ }
+ }
+ for (nf = n->brush_faces; nf; nf = nf->next)
+ {
+ Face_SetColor(n, nf, 1.0);
+ if (nf->face_winding)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ EmitBrushPrimitTextureCoordinates(nf,nf->face_winding);
+ else
+ {
+ for (j = 0; j < nf->face_winding->numpoints; j++)
+ EmitTextureCoordinates(nf->face_winding->points[j], nf->d_texture, nf);
+ }
+ }
+ }
+ }
+ return n;
+}
+
+/*
+==============
+Brush_Ray
+
+Itersects a ray with a brush
+Returns the face hit and the distance along the ray the intersection occured at
+Returns NULL and 0 if not hit at all
+==============
+*/
+face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist)
+{
+ face_t *f, *firstface;
+ vec3_t p1, p2;
+ float frac, d1, d2;
+ int i;
+
+ VectorCopy (origin, p1);
+ for (i=0 ; i<3 ; i++)
+ p2[i] = p1[i] + dir[i]*16384;
+
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
+ d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
+ if (d1 >= 0 && d2 >= 0)
+ {
+ *dist = 0;
+ return NULL; // ray is on front side of face
+ }
+ if (d1 <=0 && d2 <= 0)
+ continue;
+ // clip the ray to the plane
+ frac = d1 / (d1 - d2);
+ if (d1 > 0)
+ {
+ firstface = f;
+ for (i=0 ; i<3 ; i++)
+ p1[i] = p1[i] + frac *(p2[i] - p1[i]);
+ }
+ else
+ {
+ for (i=0 ; i<3 ; i++)
+ p2[i] = p1[i] + frac *(p2[i] - p1[i]);
+ }
+ }
+
+ // find distance p1 is along dir
+ VectorSubtract (p1, origin, p1);
+ d1 = DotProduct (p1, dir);
+
+ *dist = d1;
+
+ return firstface;
+}
+
+//PGM
+face_t *Brush_Point (vec3_t origin, brush_t *b)
+{
+ face_t *f;
+ float d1;
+
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ d1 = DotProduct (origin, f->plane.normal) - f->plane.dist;
+ if (d1 > 0)
+ {
+ return NULL; // point is on front side of face
+ }
+ }
+
+ return b->brush_faces;
+}
+//PGM
+
+
+void Brush_AddToList (brush_t *b, brush_t *list)
+{
+ if (b->next || b->prev)
+ Error ("Brush_AddToList: allready linked");
+
+ if (list == &selected_brushes || list == &active_brushes)
+ {
+ if (b->patchBrush && list == &selected_brushes)
+ {
+ Patch_Select(b->pPatch);
+ }
+ if (b->terrainBrush && list == &selected_brushes) {
+ Terrain_Select(b->pTerrain);
+ }
+ }
+ b->next = list->next;
+ list->next->prev = b;
+ list->next = b;
+ b->prev = list;
+
+ // TTimo messaging
+ DispatchRadiantMsg( RADIANT_SELECTION );
+}
+
+void Brush_RemoveFromList (brush_t *b)
+{
+ if (!b->next || !b->prev)
+ Error ("Brush_RemoveFromList: not linked");
+
+ if (b->patchBrush)
+ {
+ Patch_Deselect(b->pPatch);
+ //Patch_Deselect(b->nPatchID);
+ }
+ if (b->terrainBrush)
+ {
+ Terrain_Deselect(b->pTerrain);
+ }
+
+ b->next->prev = b->prev;
+ b->prev->next = b->next;
+ b->next = b->prev = NULL;
+}
+
+/*
+===============
+SetFaceTexdef
+
+Doesn't set the curve flags
+
+NOTE : ( TTimo )
+ never trust f->d_texture here, f->texdef and f->d_texture are out of sync when called by Brush_SetTexture
+ use Texture_ForName() to find the right shader
+ FIXME : send the right shader ( qtexture_t * ) in the parameters ?
+
+TTimo: surface plugin, added an IPluginTexdef* parameter
+ if not NULL, get ->Copy() of it into the face ( and remember to hook )
+ if NULL, ask for a default
+===============
+*/
+void SetFaceTexdef (brush_t *b, face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pPlugTexdef) {
+ int oldFlags;
+ int oldContents;
+ face_t *tf;
+
+ oldFlags = f->texdef.flags;
+ oldContents = f->texdef.contents;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ f->texdef = *texdef;
+ ConvertTexMatWithQTexture( brushprimit_texdef, NULL, &f->brushprimit_texdef, Texture_ForName( f->texdef.name ) );
+ }
+ else
+ if (bFitScale)
+ {
+ f->texdef = *texdef;
+ // fit the scaling of the texture on the actual plane
+ vec3_t p1,p2,p3; // absolute coordinates
+ // compute absolute coordinates
+ ComputeAbsolute(f,p1,p2,p3);
+ // compute the scale
+ vec3_t vx,vy;
+ VectorSubtract(p2,p1,vx);
+ VectorNormalize(vx);
+ VectorSubtract(p3,p1,vy);
+ VectorNormalize(vy);
+ // assign scale
+ VectorScale(vx,texdef->scale[0],vx);
+ VectorScale(vy,texdef->scale[1],vy);
+ VectorAdd(p1,vx,p2);
+ VectorAdd(p1,vy,p3);
+ // compute back shift scale rot
+ AbsoluteToLocal(f->plane,f,p1,p2,p3);
+ }
+ else
+ f->texdef = *texdef;
+ f->texdef.flags = (f->texdef.flags & ~SURF_KEEP) | (oldFlags & SURF_KEEP);
+ f->texdef.contents = (f->texdef.contents & ~CONTENTS_KEEP) | (oldContents & CONTENTS_KEEP);
+
+ // surface plugin
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+#ifdef _DEBUG
+ if (!f->pData)
+ Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in SetFaceTexdef\n");
+ else
+#endif
+ GETPLUGINTEXDEF(f)->DecRef();
+ IPluginTexdef *pTexdef = NULL;
+ if ( pPlugTexdef )
+ {
+ pTexdef = pPlugTexdef->Copy();
+ pTexdef->Hook( f );
+ }
+ else
+ pTexdef = g_SurfaceTable.m_pfnTexdefAlloc( f );
+ f->pData = pTexdef;
+ }
+
+ // if this is a curve face, set all other curve faces to the same texdef
+ if (f->texdef.flags & SURF_CURVE)
+ {
+ for (tf = b->brush_faces ; tf ; tf = tf->next)
+ {
+ if (tf->texdef.flags & SURF_CURVE)
+ tf->texdef = f->texdef;
+ }
+ }
+}
+
+
+void Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef* pTexdef)
+{
+ for (face_t* f = b->brush_faces ; f ; f = f->next)
+ {
+ SetFaceTexdef (b, f, texdef, brushprimit_texdef, bFitScale, pTexdef);
+ }
+ Brush_Build( b );
+ if (b->patchBrush)
+ {
+ //++timo clean
+// Sys_Printf("WARNING: Brush_SetTexture needs surface plugin code for patches\n");
+ Patch_SetTexture(b->pPatch, texdef, pTexdef );
+ }
+ if (b->terrainBrush)
+ {
+ Terrain_SetTexture(b->pTerrain, texdef);
+ }
+
+}
+
+
+qboolean ClipLineToFace (vec3_t p1, vec3_t p2, face_t *f)
+{
+ float d1, d2, fr;
+ int i;
+ float *v;
+
+ d1 = DotProduct (p1, f->plane.normal) - f->plane.dist;
+ d2 = DotProduct (p2, f->plane.normal) - f->plane.dist;
+
+ if (d1 >= 0 && d2 >= 0)
+ return false; // totally outside
+ if (d1 <= 0 && d2 <= 0)
+ return true; // totally inside
+
+ fr = d1 / (d1 - d2);
+
+ if (d1 > 0)
+ v = p1;
+ else
+ v = p2;
+
+ for (i=0 ; i<3 ; i++)
+ v[i] = p1[i] + fr*(p2[i] - p1[i]);
+
+ return true;
+}
+
+
+int AddPlanept (float *f)
+{
+ int i;
+
+ for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
+ if (g_qeglobals.d_move_points[i] == f)
+ return 0;
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = f;
+ return 1;
+}
+
+/*
+==============
+Brush_SelectFaceForDragging
+
+Adds the faces planepts to move_points, and
+rotates and adds the planepts of adjacent face if shear is set
+==============
+*/
+void Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear)
+{
+ int i;
+ face_t *f2;
+ winding_t *w;
+ float d;
+ brush_t *b2;
+ int c;
+
+ if (b->owner->eclass->fixedsize)
+ return;
+
+ c = 0;
+ for (i=0 ; i<3 ; i++)
+ c += AddPlanept (f->planepts[i]);
+ if (c == 0)
+ return; // allready completely added
+
+ // select all points on this plane in all brushes the selection
+ for (b2=selected_brushes.next ; b2 != &selected_brushes ; b2 = b2->next)
+ {
+ if (b2 == b)
+ continue;
+ for (f2=b2->brush_faces ; f2 ; f2=f2->next)
+ {
+ for (i=0 ; i<3 ; i++)
+ if (fabs(DotProduct(f2->planepts[i], f->plane.normal)
+ -f->plane.dist) > ON_EPSILON)
+ break;
+ if (i==3)
+ { // move this face as well
+ Brush_SelectFaceForDragging (b2, f2, shear);
+ break;
+ }
+ }
+ }
+
+
+ // if shearing, take all the planes adjacent to
+ // selected faces and rotate their points so the
+ // edge clipped by a selcted face has two of the points
+ if (!shear)
+ return;
+
+ for (f2=b->brush_faces ; f2 ; f2=f2->next)
+ {
+ if (f2 == f)
+ continue;
+ w = Brush_MakeFaceWinding (b, f2);
+ if (!w)
+ continue;
+
+ // any points on f will become new control points
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ d = DotProduct (w->points[i], f->plane.normal)
+ - f->plane.dist;
+ if (d > -ON_EPSILON && d < ON_EPSILON)
+ break;
+ }
+
+ //
+ // if none of the points were on the plane,
+ // leave it alone
+ //
+ if (i != w->numpoints)
+ {
+ if (i == 0)
+ { // see if the first clockwise point was the
+ // last point on the winding
+ d = DotProduct (w->points[w->numpoints-1]
+ , f->plane.normal) - f->plane.dist;
+ if (d > -ON_EPSILON && d < ON_EPSILON)
+ i = w->numpoints - 1;
+ }
+
+ AddPlanept (f2->planepts[0]);
+
+ VectorCopy (w->points[i], f2->planepts[0]);
+ if (++i == w->numpoints)
+ i = 0;
+
+ // see if the next point is also on the plane
+ d = DotProduct (w->points[i]
+ , f->plane.normal) - f->plane.dist;
+ if (d > -ON_EPSILON && d < ON_EPSILON)
+ AddPlanept (f2->planepts[1]);
+
+ VectorCopy (w->points[i], f2->planepts[1]);
+ if (++i == w->numpoints)
+ i = 0;
+
+ // the third point is never on the plane
+
+ VectorCopy (w->points[i], f2->planepts[2]);
+ }
+
+ free(w);
+ }
+}
+
+/*
+==============
+Brush_SideSelect
+
+The mouse click did not hit the brush, so grab one or more side
+planes for dragging
+==============
+*/
+void Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir
+ , qboolean shear)
+{
+ face_t *f, *f2;
+ vec3_t p1, p2;
+
+ //if (b->patchBrush)
+ // return;
+ //Patch_SideSelect(b->nPatchID, origin, dir);
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ VectorCopy (origin, p1);
+ VectorMA (origin, 16384, dir, p2);
+
+ for (f2=b->brush_faces ; f2 ; f2=f2->next)
+ {
+ if (f2 == f)
+ continue;
+ ClipLineToFace (p1, p2, f2);
+ }
+
+ if (f2)
+ continue;
+
+ if (VectorCompare (p1, origin))
+ continue;
+ if (ClipLineToFace (p1, p2, f))
+ continue;
+
+ Brush_SelectFaceForDragging (b, f, shear);
+ }
+
+
+}
+
+void Brush_BuildWindings( brush_t *b, bool bSnap )
+{
+ winding_t *w;
+ face_t *face;
+ vec_t v;
+
+ if (bSnap)
+ Brush_SnapPlanepts( b );
+
+ // clear the mins/maxs bounds
+ b->mins[0] = b->mins[1] = b->mins[2] = 99999;
+ b->maxs[0] = b->maxs[1] = b->maxs[2] = -99999;
+
+ Brush_MakeFacePlanes (b);
+
+ face = b->brush_faces;
+
+ float fCurveColor = 1.0;
+
+ for ( ; face ; face=face->next)
+ {
+ int i, j;
+ free(face->face_winding);
+ w = face->face_winding = Brush_MakeFaceWinding (b, face);
+ face->d_texture = Texture_ForName( face->texdef.name );
+
+ if (!w)
+ continue;
+
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ // add to bounding box
+ for (j=0 ; j<3 ; j++)
+ {
+ v = w->points[i][j];
+ if (v > b->maxs[j])
+ b->maxs[j] = v;
+ if (v < b->mins[j])
+ b->mins[j] = v;
+ }
+ }
+ // setup s and t vectors, and set color
+ //if (!g_PrefsDlg.m_bGLLighting)
+ //{
+ Face_SetColor (b, face, fCurveColor);
+ //}
+
+ fCurveColor -= .10;
+ if (fCurveColor <= 0)
+ fCurveColor = 1.0;
+
+ // computing ST coordinates for the windings
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (g_qeglobals.bNeedConvert)
+ {
+ // we have parsed old brushes format and need conversion
+ // convert old brush texture representation to new format
+ FaceToBrushPrimitFace(face);
+#ifdef _DEBUG
+ // use old texture coordinates code to check against
+ for (i=0 ; i<w->numpoints ; i++)
+ EmitTextureCoordinates( w->points[i], face->d_texture, face);
+#endif
+ }
+ // use new texture representation to compute texture coordinates
+ // in debug mode we will check against old code and warn if there are differences
+ EmitBrushPrimitTextureCoordinates(face,w);
+ }
+ else
+ {
+ for (i=0 ; i<w->numpoints ; i++)
+ EmitTextureCoordinates( w->points[i], face->d_texture, face);
+ }
+ }
+}
+
+/*
+==================
+Brush_RemoveEmptyFaces
+
+Frees any overconstraining faces
+==================
+*/
+void Brush_RemoveEmptyFaces ( brush_t *b )
+{
+ face_t *f, *next;
+
+ f = b->brush_faces;
+ b->brush_faces = NULL;
+
+ for ( ; f ; f=next)
+ {
+ next = f->next;
+ if (!f->face_winding)
+ Face_Free (f);
+ else
+ {
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+ }
+
+ }
+}
+
+void Brush_SnapToGrid(brush_t *pb)
+{
+ for (face_t *f = pb->brush_faces ; f; f = f->next)
+ {
+ for (int i = 0 ;i < 3 ;i++)
+ {
+ for (int j = 0 ;j < 3 ; j++)
+ {
+ f->planepts[i][j] = floor (f->planepts[i][j] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ }
+ }
+ }
+ Brush_Build(pb);
+}
+
+void Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild)
+{
+ for (face_t* f=b->brush_faces ; f ; f=f->next)
+ {
+ for (int i=0 ; i<3 ; i++)
+ {
+ VectorRotate(f->planepts[i], vAngle, vOrigin, f->planepts[i]);
+ }
+ }
+ if (bBuild)
+ {
+ Brush_Build(b, false, false);
+ }
+}
+
+void Brush_Center(brush_t *b, vec3_t vNewCenter)
+{
+ vec3_t vMid;
+ // get center of the brush
+ for (int j = 0; j < 3; j++)
+ {
+ vMid[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
+ }
+ // calc distance between centers
+ VectorSubtract(vNewCenter, vMid, vMid);
+ Brush_Move(b, vMid, true);
+
+}
+
+// only designed for fixed size entity brushes
+void Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax)
+{
+ brush_t *b2 = Brush_Create(vMin, vMax, &b->brush_faces->texdef);
+
+ face_t *next;
+ for (face_t *f=b->brush_faces ; f ; f=next)
+ {
+ next = f->next;
+ Face_Free( f );
+ }
+
+ b->brush_faces = b2->brush_faces;
+
+ // unlink from active/selected list
+ if (b2->next)
+ Brush_RemoveFromList (b2);
+ free(b2);
+ Brush_Build(b, true);
+}
+
+
+eclass_t* HasModel(brush_t *b)
+{
+ vec3_t vMin, vMax;
+ vMin[0] = vMin[1] = vMin[2] = 9999;
+ vMax[0] = vMax[1] = vMax[2] = -9999;
+
+ if (b->owner->md3Class != NULL)
+ {
+ return b->owner->md3Class;
+ }
+
+ if (Eclass_hasModel(b->owner->eclass, vMin, vMax))
+ {
+ return b->owner->eclass;
+ }
+
+ eclass_t *e = NULL;
+ // FIXME: entity needs to track whether a cache hit failed and not ask again
+ if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
+ {
+ char *pModel = ValueForKey(b->owner, "model");
+ if (pModel != NULL && strlen(pModel) > 0)
+ {
+ e = GetCachedModel(b->owner, pModel, vMin, vMax);
+ if (e != NULL)
+ {
+ // we need to scale the brush to the proper size based on the model load
+ // recreate brush just like in load/save
+
+ VectorAdd (vMin, b->owner->origin, vMin);
+ VectorAdd (vMax, b->owner->origin, vMax);
+
+ Brush_Resize(b, vMin, vMax);
+
+/*
+ //
+ vec3_t vTemp, vTemp2;
+ VectorSubtract(b->maxs, b->mins, vTemp);
+ VectorSubtract(vMax, vMin, vTemp2);
+ for (int i = 0; i < 3; i++)
+ {
+ if (vTemp[i] != 0)
+ {
+ vTemp2[i] /= vTemp[i];
+ }
+ }
+ vec3_t vMid, vMid2;
+ vMid[0] = vMid[1] = vMid[2] = 0.0;
+ vMid2[0] = vMid2[1] = vMid2[2] = 0.0;
+
+ for (int j = 0; j < 3; j++)
+ {
+ vMid2[j] = b->mins[j] + abs((b->maxs[j] - b->mins[j]) * 0.5);
+ }
+
+ //VectorSubtract(vMid2, vMid, vMid2);
+
+ for (face_t* f=b->brush_faces ; f ; f=f->next)
+ {
+ for (int i=0 ; i<3 ; i++)
+ {
+
+ // scale
+ VectorSubtract(f->planepts[i], vMid2, f->planepts[i]);
+ f->planepts[i][0] *= vTemp2[0];
+ f->planepts[i][1] *= vTemp2[1];
+ f->planepts[i][2] *= vTemp2[2];
+ VectorAdd(f->planepts[i], vMid2, f->planepts[i]);
+ }
+ }
+
+ //Brush_Center(b, b->owner->origin);
+
+ //Brush_SnapToGrid(b);
+/*
+ float a = FloatForKey (b->owner, "angle");
+ if (a)
+ {
+ vec3_t vAngle;
+ vAngle[0] = vAngle[1] = 0;
+ vAngle[2] = a;
+ Brush_Rotate(b, vAngle, b->owner->origin);
+ }
+ else
+ {
+ Brush_Build(b, true);
+*/
+// }
+
+ b->bModelFailed = false;
+ }
+ else
+ {
+ b->bModelFailed = true;
+ }
+ }
+ }
+ return e;
+}
+
+static bool g_bInPaintedModel = false;
+static bool g_bDoIt = false;
+bool PaintedModel(brush_t *b, bool bOkToTexture)
+{
+ if (g_bInPaintedModel)
+ {
+ return true;
+ }
+
+ if (g_PrefsDlg.m_nEntityShowState == ENTITY_BOX || b->bModelFailed)
+ {
+ return false;
+ }
+ else if (!IsBrushSelected(b) && (g_PrefsDlg.m_nEntityShowState & ENTITY_SELECTED_ONLY))
+ {
+ return false;
+ }
+
+ g_bInPaintedModel = true;
+ bool bReturn = false;
+
+ eclass_t *pEclass = HasModel(b);
+
+ if (pEclass)
+ {
+ qglPushAttrib(GL_ALL_ATTRIB_BITS);
+ entitymodel *model = pEclass->model;
+
+
+ float a = FloatForKey (b->owner, "angle");
+ while (model != NULL)
+ {
+ if (bOkToTexture == false || g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME || model->nTextureBind == -1) // skinned
+ {
+ qglDisable( GL_CULL_FACE );
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ qglDisable(GL_TEXTURE_2D);
+ qglColor3fv(pEclass->color);
+ }
+ else
+ {
+ qglColor3f(1, 1, 1);
+ qglEnable(GL_TEXTURE_2D);
+ qglBindTexture( GL_TEXTURE_2D, model->nTextureBind );
+ }
+ vec3_t v;
+
+ int i,j;
+ VectorAdd(b->maxs, b->mins, v);
+ VectorScale(v, 0.5, v);
+ VectorCopy(b->owner->origin, v);
+
+
+ //for (i = 0; i < 3; i++)
+ //{
+ // v[i] -= (pEclass->mins[i] - b->mins[i]);
+ //}
+
+ //if (model->nModelPosition)
+ //{
+ //v[2] = b->mins[2] - (pEclass->mins[2]);
+ //}
+
+ float s, c;
+ if (a)
+ {
+ s = sin (a/180*Q_PI);
+ c = cos (a/180*Q_PI);
+ }
+
+ vec3_t vSin;
+ vec3_t vCos;
+ VectorClear(vSin);
+ VectorClear(vCos);
+ for ( j = 0; j < 3; j++)
+ {
+ if (b->owner->vRotation[j])
+ {
+ vSin[j] = sin(b->owner->vRotation[j]/180*Q_PI);
+ vCos[j] = cos(b->owner->vRotation[j]/180*Q_PI);
+ }
+ }
+
+
+ qglBegin (GL_TRIANGLES);
+
+ vec5_t vTest[3];
+ for (i = 0; i < model->nTriCount; i++)
+ {
+ for (j = 0; j < 3; j++)
+ {
+#if 1
+ float x = model->pTriList[i].v[j][0] + v[0];
+ float y = model->pTriList[i].v[j][1] + v[1];
+ if (a)
+ {
+ float x2 = (((x - v[0]) * c) - ((y - v[1]) * s)) + v[0];
+ float y2 = (((x - v[0]) * s) + ((y - v[1]) * c)) + v[1];
+ x = x2;
+ y = y2;
+ }
+ //qglTexCoord2f (pEclass->pTriList[i].st[j][0] / pEclass->nSkinWidth, pEclass->pTriList[i].st[j][1] / pEclass->nSkinHeight);
+ qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
+ qglVertex3f(x, y, model->pTriList[i].v[j][2] + v[2]);
+#else
+ float x = model->pTriList[i].v[j][0] + v[0];
+ float y = model->pTriList[i].v[j][1] + v[1];
+ float z = model->pTriList[i].v[j][2] + v[2];
+
+ if (b->owner->vRotation[0])
+ {
+ float y2 = (((y - v[1]) * vCos[0]) - ((z - v[2]) * vSin[0])) + v[1];
+ float z2 = (((y - v[1]) * vSin[0]) + ((z - v[2]) * vCos[0])) + v[2];
+ y = y2;
+ z = z2;
+ }
+ if (b->owner->vRotation[1])
+ {
+ float z2 = (((z - v[2]) * vCos[1]) - ((x - v[0]) * vSin[1])) + v[2];
+ float x2 = (((z - v[2]) * vSin[1]) + ((x - v[0]) * vCos[1])) + v[0];
+ x = x2;
+ z = z2;
+ }
+ if (b->owner->vRotation[2])
+ {
+ float x2 = (((x - v[0]) * vCos[2]) - ((y - v[1]) * vSin[2])) + v[0];
+ float y2 = (((x - v[0]) * vSin[2]) + ((y - v[1]) * vCos[2])) + v[1];
+ x = x2;
+ y = y2;
+ }
+ qglTexCoord2f (model->pTriList[i].st[j][0], model->pTriList[i].st[j][1]);
+ qglVertex3f(x, y, z);
+#endif
+ if (g_bDoIt)
+ {
+ vTest[j][0] = x;
+ vTest[j][1] = y;
+ vTest[j][2] = model->pTriList[i].v[j][2] + v[2];
+ vTest[j][3] = model->pTriList[i].st[j][0];
+ vTest[j][4] = model->pTriList[i].st[j][1];
+ }
+
+ }
+ if (g_bDoIt)
+ {
+ Patch_FromTriangle(vTest[0], vTest[1], vTest[2]);
+ }
+ }
+ qglEnd();
+ if (g_PrefsDlg.m_nEntityShowState & ENTITY_WIREFRAME) // skinned
+ {
+ qglEnable(GL_CULL_FACE );
+ qglEnable(GL_TEXTURE_2D);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ }
+ else
+ {
+ qglDisable(GL_TEXTURE_2D);
+ }
+ model = model->pNext;
+ }
+
+ if (g_bDoIt)
+ {
+ g_bDoIt = false;
+ }
+
+ vec3_t vColor;
+ VectorScale(pEclass->color, 0.50, vColor);
+
+ vec3_t vCenter, vMin, vMax;
+ VectorCopy(b->owner->origin, vCenter);
+
+ qglColor3fv(vColor);
+ qglPointSize(4);
+
+ qglBegin(GL_POINTS);
+ qglVertex3fv(b->owner->origin);
+ qglEnd();
+
+ qglBegin(GL_LINES);
+ vCenter[0] -= 8;
+ qglVertex3fv(vCenter);
+ vCenter[0] += 16;
+ qglVertex3fv(vCenter);
+ vCenter[0] -= 8;
+ vCenter[1] -= 8;
+ qglVertex3fv(vCenter);
+ vCenter[1] += 16;
+ qglVertex3fv(vCenter);
+ vCenter[1] -= 8;
+ vCenter[2] -= 8;
+ qglVertex3fv(vCenter);
+ vCenter[2] += 16;
+ qglVertex3fv(vCenter);
+ vCenter[2] -= 8;
+ qglEnd();
+
+ VectorCopy(vCenter, vMin);
+ VectorCopy(vCenter, vMax);
+ vMin[0] -= 4;
+ vMin[1] -= 4;
+ vMin[2] -= 4;
+ vMax[0] += 4;
+ vMax[1] += 4;
+ vMax[2] += 4;
+
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f(vMin[0],vMin[1],vMin[2]);
+ qglVertex3f(vMax[0],vMin[1],vMin[2]);
+ qglVertex3f(vMax[0],vMax[1],vMin[2]);
+ qglVertex3f(vMin[0],vMax[1],vMin[2]);
+ qglEnd();
+
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f(vMin[0],vMin[1],vMax[2]);
+ qglVertex3f(vMax[0],vMin[1],vMax[2]);
+ qglVertex3f(vMax[0],vMax[1],vMax[2]);
+ qglVertex3f(vMin[0],vMax[1],vMax[2]);
+ qglEnd();
+
+ qglBegin(GL_LINES);
+ qglVertex3f(vMin[0],vMin[1],vMin[2]);
+ qglVertex3f(vMin[0],vMin[1],vMax[2]);
+ qglVertex3f(vMin[0],vMax[1],vMax[2]);
+ qglVertex3f(vMin[0],vMax[1],vMin[2]);
+ qglVertex3f(vMax[0],vMin[1],vMin[2]);
+ qglVertex3f(vMax[0],vMin[1],vMax[2]);
+ qglVertex3f(vMax[0],vMax[1],vMax[2]);
+ qglVertex3f(vMax[0],vMax[1],vMin[2]);
+ qglEnd();
+
+
+ if (g_PrefsDlg.m_nEntityShowState & ENTITY_BOXED)
+ {
+ qglColor3fv(pEclass->color);
+
+ vec3_t mins, maxs;
+ VectorCopy(b->mins, mins);
+ VectorCopy(b->maxs, maxs);
+/*
+ if (a)
+ {
+ vec3_t vAngle;
+ vAngle[0] = vAngle[1] = 0;
+ vAngle[2] = a;
+ VectorRotate(mins, vAngle, b->owner->origin, mins);
+ VectorRotate(maxs, vAngle, b->owner->origin, maxs);
+ }
+*/
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f(mins[0],mins[1],mins[2]);
+ qglVertex3f(maxs[0],mins[1],mins[2]);
+ qglVertex3f(maxs[0],maxs[1],mins[2]);
+ qglVertex3f(mins[0],maxs[1],mins[2]);
+ qglEnd();
+
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f(mins[0],mins[1],maxs[2]);
+ qglVertex3f(maxs[0],mins[1],maxs[2]);
+ qglVertex3f(maxs[0],maxs[1],maxs[2]);
+ qglVertex3f(mins[0],maxs[1],maxs[2]);
+ qglEnd();
+
+ qglBegin(GL_LINES);
+ qglVertex3f(mins[0],mins[1],mins[2]);
+ qglVertex3f(mins[0],mins[1],maxs[2]);
+ qglVertex3f(mins[0],maxs[1],maxs[2]);
+ qglVertex3f(mins[0],maxs[1],mins[2]);
+ qglVertex3f(maxs[0],mins[1],mins[2]);
+ qglVertex3f(maxs[0],mins[1],maxs[2]);
+ qglVertex3f(maxs[0],maxs[1],maxs[2]);
+ qglVertex3f(maxs[0],maxs[1],mins[2]);
+ qglEnd();
+ }
+ qglPopAttrib();
+ bReturn = true;
+ }
+ else
+ {
+ b->bModelFailed = true;
+ }
+
+ g_bInPaintedModel = false;
+ return bReturn;
+}
+/*
+//++timo moved out to mahlib.h
+//++timo remove
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
+{
+ float angle;
+ static float sr, sp, sy, cr, cp, cy;
+ // static to help MS compiler fp bugs
+
+ angle = angles[YAW] * Q_PI / 180;
+ sy = sin(angle);
+ cy = cos(angle);
+ angle = angles[PITCH] * Q_PI / 180;
+ sp = sin(angle);
+ cp = cos(angle);
+ angle = angles[ROLL] * Q_PI / 180;
+ sr = sin(angle);
+ cr = cos(angle);
+
+ if (forward)
+ {
+ forward[0] = cp*cy;
+ forward[1] = cp*sy;
+ forward[2] = -sp;
+ }
+ if (right)
+ {
+ right[0] = (-1*sr*sp*cy+-1*cr*-sy);
+ right[1] = (-1*sr*sp*sy+-1*cr*cy);
+ right[2] = -1*sr*cp;
+ }
+ if (up)
+ {
+ up[0] = (cr*sp*cy+-sr*-sy);
+ up[1] = (cr*sp*sy+-sr*cy);
+ up[2] = cr*cp;
+ }
+}
+*/
+void FacingVectors (entity_t *e, vec3_t forward, vec3_t right, vec3_t up)
+{
+ int angleVal;
+ vec3_t angles;
+
+ angleVal = IntForKey(e, "angle");
+ if (angleVal == -1) // up
+ {
+ VectorSet(angles, 270, 0, 0);
+ }
+ else if(angleVal == -2) // down
+ {
+ VectorSet(angles, 90, 0, 0);
+ }
+ else
+ {
+ VectorSet(angles, 0, angleVal, 0);
+ }
+
+ AngleVectors(angles, forward, right, up);
+}
+
+void Brush_DrawFacingAngle (brush_t *b, entity_t *e)
+{
+ vec3_t forward, right, up;
+ vec3_t endpoint, tip1, tip2;
+ vec3_t start;
+ float dist;
+
+ VectorAdd(e->brushes.onext->mins, e->brushes.onext->maxs, start);
+ VectorScale(start, 0.5, start);
+ dist = (b->maxs[0] - start[0]) * 2.5;
+
+ FacingVectors (e, forward, right, up);
+ VectorMA (start, dist, forward, endpoint);
+
+ dist = (b->maxs[0] - start[0]) * 0.5;
+ VectorMA (endpoint, -dist, forward, tip1);
+ VectorMA (tip1, -dist, up, tip1);
+ VectorMA (tip1, 2*dist, up, tip2);
+
+ qglColor4f (1, 1, 1, 1);
+ qglLineWidth (4);
+ qglBegin (GL_LINES);
+ qglVertex3fv (start);
+ qglVertex3fv (endpoint);
+ qglVertex3fv (endpoint);
+ qglVertex3fv (tip1);
+ qglVertex3fv (endpoint);
+ qglVertex3fv (tip2);
+ qglEnd ();
+ qglLineWidth (1);
+}
+
+void DrawLight(brush_t *b)
+{
+ vec3_t vTriColor;
+ bool bTriPaint = false;
+
+ vTriColor[0] = vTriColor[2] = 1.0;
+ vTriColor[1] = 1.0;
+ bTriPaint = true;
+ CString strColor = ValueForKey(b->owner, "_color");
+ if (strColor.GetLength() > 0)
+ {
+ float fR, fG, fB;
+ int n = sscanf(strColor,"%f %f %f", &fR, &fG, &fB);
+ if (n == 3)
+ {
+ vTriColor[0] = fR;
+ vTriColor[1] = fG;
+ vTriColor[2] = fB;
+ }
+ }
+ qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
+
+ vec3_t vCorners[4];
+ float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
+
+ vCorners[0][0] = b->mins[0];
+ vCorners[0][1] = b->mins[1];
+ vCorners[0][2] = fMid;
+
+ vCorners[1][0] = b->mins[0];
+ vCorners[1][1] = b->maxs[1];
+ vCorners[1][2] = fMid;
+
+ vCorners[2][0] = b->maxs[0];
+ vCorners[2][1] = b->maxs[1];
+ vCorners[2][2] = fMid;
+
+ vCorners[3][0] = b->maxs[0];
+ vCorners[3][1] = b->mins[1];
+ vCorners[3][2] = fMid;
+
+ vec3_t vTop, vBottom;
+
+ vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
+ vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
+ vTop[2] = b->maxs[2];
+
+ VectorCopy(vTop, vBottom);
+ vBottom[2] = b->mins[2];
+
+ vec3_t vSave;
+ VectorCopy(vTriColor, vSave);
+
+ qglBegin(GL_TRIANGLE_FAN);
+ qglVertex3fv(vTop);
+ for (int i = 0; i <= 3; i++)
+ {
+ vTriColor[0] *= 0.95;
+ vTriColor[1] *= 0.95;
+ vTriColor[2] *= 0.95;
+ qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
+ qglVertex3fv(vCorners[i]);
+ }
+ qglVertex3fv(vCorners[0]);
+ qglEnd();
+
+ VectorCopy(vSave, vTriColor);
+ vTriColor[0] *= 0.95;
+ vTriColor[1] *= 0.95;
+ vTriColor[2] *= 0.95;
+
+ qglBegin(GL_TRIANGLE_FAN);
+ qglVertex3fv(vBottom);
+ qglVertex3fv(vCorners[0]);
+ for (i = 3; i >= 0; i--)
+ {
+ vTriColor[0] *= 0.95;
+ vTriColor[1] *= 0.95;
+ vTriColor[2] *= 0.95;
+ qglColor3f(vTriColor[0], vTriColor[1], vTriColor[2]);
+ qglVertex3fv(vCorners[i]);
+ }
+ qglEnd();
+
+ // check for DOOM lights
+ CString str = ValueForKey(b->owner, "light_right");
+ if (str.GetLength() > 0) {
+ vec3_t vRight, vUp, vTarget, vTemp;
+ GetVectorForKey (b->owner, "light_right", vRight);
+ GetVectorForKey (b->owner, "light_up", vUp);
+ GetVectorForKey (b->owner, "light_target", vTarget);
+
+ qglColor3f(0, 1, 0);
+ qglBegin(GL_LINE_LOOP);
+ VectorAdd(vTarget, b->owner->origin, vTemp);
+ VectorAdd(vTemp, vRight, vTemp);
+ VectorAdd(vTemp, vUp, vTemp);
+ qglVertex3fv(b->owner->origin);
+ qglVertex3fv(vTemp);
+ VectorAdd(vTarget, b->owner->origin, vTemp);
+ VectorAdd(vTemp, vUp, vTemp);
+ VectorSubtract(vTemp, vRight, vTemp);
+ qglVertex3fv(b->owner->origin);
+ qglVertex3fv(vTemp);
+ VectorAdd(vTarget, b->owner->origin, vTemp);
+ VectorAdd(vTemp, vRight, vTemp);
+ VectorSubtract(vTemp, vUp, vTemp);
+ qglVertex3fv(b->owner->origin);
+ qglVertex3fv(vTemp);
+ VectorAdd(vTarget, b->owner->origin, vTemp);
+ VectorSubtract(vTemp, vUp, vTemp);
+ VectorSubtract(vTemp, vRight, vTemp);
+ qglVertex3fv(b->owner->origin);
+ qglVertex3fv(vTemp);
+ qglEnd();
+
+ }
+
+}
+
+void Brush_Draw( brush_t *b )
+{
+ face_t *face;
+ int i, order;
+ qtexture_t *prev = 0;
+ winding_t *w;
+
+ if ( b->owner && ( b->owner->eclass->nShowFlags & ECLASS_PLUGINENTITY ) )
+ {
+ b->owner->pPlugEnt->CamRender();
+ return;
+ }
+
+ // (TTimo) NOTE: added by build 173, I check after pPlugEnt so it doesn't interfere ?
+ if (b->hiddenBrush)
+ {
+ return;
+ }
+
+ if (b->patchBrush)
+ {
+ //Patch_DrawCam(b->nPatchID);
+ Patch_DrawCam(b->pPatch);
+ //if (!g_bPatchShowBounds)
+ return;
+ }
+
+ if (b->terrainBrush)
+ {
+ Terrain_DrawCam(b->pTerrain);
+ return;
+ }
+
+ int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
+
+ if (b->owner->eclass->fixedsize)
+ {
+
+ if (!(g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES) && (b->owner->eclass->nShowFlags & ECLASS_ANGLE))
+ {
+ Brush_DrawFacingAngle(b, b->owner);
+ }
+
+ if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
+ {
+ DrawLight(b);
+ return;
+ }
+ if (nDrawMode == cd_texture || nDrawMode == cd_light)
+ qglDisable (GL_TEXTURE_2D);
+
+ // if we are wireframing models
+ bool bp = (b->bModelFailed) ? false : PaintedModel(b, true);
+
+ if (nDrawMode == cd_texture || nDrawMode == cd_light)
+ qglEnable (GL_TEXTURE_2D);
+
+ if (bp)
+ return;
+ }
+
+ // guarantee the texture will be set first
+ prev = NULL;
+ for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
+ {
+ w = face->face_winding;
+ if (!w)
+ {
+ continue; // freed face
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
+ {
+ if (strstr(face->texdef.name, "caulk"))
+ {
+ continue;
+ }
+ }
+
+#if 0
+ if (b->alphaBrush)
+ {
+ if (!(face->texdef.flags & SURF_ALPHA))
+ continue;
+ //--qglPushAttrib(GL_ALL_ATTRIB_BITS);
+ qglDisable(GL_CULL_FACE);
+ //--qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ //--qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ //--qglDisable(GL_DEPTH_TEST);
+ //--qglBlendFunc (GL_SRC_ALPHA, GL_DST_ALPHA);
+ //--qglEnable (GL_BLEND);
+ }
+#endif
+
+ if ((nDrawMode == cd_texture || nDrawMode == cd_light) && face->d_texture != prev)
+ {
+ // set the texture for this face
+ prev = face->d_texture;
+ qglBindTexture( GL_TEXTURE_2D, face->d_texture->texture_number );
+ }
+
+
+
+ if (!b->patchBrush)
+ {
+ if (face->texdef.flags & SURF_TRANS33)
+ qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.33 );
+ else if ( face->texdef.flags & SURF_TRANS66)
+ qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.66 );
+ else
+ qglColor3fv( face->d_color );
+ }
+ else
+ {
+ qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], 0.13 );
+ }
+
+ // shader drawing stuff
+ if (face->d_texture->bFromShader)
+ {
+ // setup shader drawing
+ qglColor4f ( face->d_color[0], face->d_color[1], face->d_color[2], face->d_texture->fTrans );
+
+ }
+
+ // draw the polygon
+
+ //if (nDrawMode == cd_light)
+ //{
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglNormal3fv(face->plane.normal);
+ }
+ //}
+
+ qglBegin(GL_POLYGON);
+ //if (nDrawMode == cd_light)
+
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ if (nDrawMode == cd_texture || nDrawMode == cd_light)
+ qglTexCoord2fv( &w->points[i][3] );
+ qglVertex3fv(w->points[i]);
+ }
+ qglEnd();
+ }
+
+#if 0
+ if (b->alphaBrush)
+ {
+ //--qglPopAttrib();
+ qglEnable(GL_CULL_FACE);
+ //--qglDisable (GL_BLEND);
+ //--qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ }
+#endif
+
+ if (b->owner->eclass->fixedsize && (nDrawMode == cd_texture || nDrawMode == cd_light))
+ qglEnable (GL_TEXTURE_2D);
+
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+}
+
+
+
+void Face_Draw( face_t *f )
+{
+ int i;
+
+ if ( f->face_winding == 0 )
+ return;
+ qglBegin( GL_POLYGON );
+ for ( i = 0 ; i < f->face_winding->numpoints; i++)
+ qglVertex3fv( f->face_winding->points[i] );
+ qglEnd();
+}
+
+void Brush_DrawXY(brush_t *b, int nViewType)
+{
+ face_t *face;
+ int order;
+ winding_t *w;
+ int i;
+
+ if (b->hiddenBrush)
+ {
+ return;
+ }
+
+ if (b->patchBrush)
+ {
+ //Patch_DrawXY(b->nPatchID);
+ Patch_DrawXY(b->pPatch);
+ if (!g_bPatchShowBounds)
+ return;
+ }
+
+ if (b->terrainBrush)
+ {
+ Terrain_DrawXY(b->pTerrain, b->owner);
+ }
+
+
+ if (b->owner->eclass->fixedsize)
+ {
+ if (g_PrefsDlg.m_bNewLightDraw && (b->owner->eclass->nShowFlags & ECLASS_LIGHT))
+ {
+ vec3_t vCorners[4];
+ float fMid = b->mins[2] + (b->maxs[2] - b->mins[2]) / 2;
+
+ vCorners[0][0] = b->mins[0];
+ vCorners[0][1] = b->mins[1];
+ vCorners[0][2] = fMid;
+
+ vCorners[1][0] = b->mins[0];
+ vCorners[1][1] = b->maxs[1];
+ vCorners[1][2] = fMid;
+
+ vCorners[2][0] = b->maxs[0];
+ vCorners[2][1] = b->maxs[1];
+ vCorners[2][2] = fMid;
+
+ vCorners[3][0] = b->maxs[0];
+ vCorners[3][1] = b->mins[1];
+ vCorners[3][2] = fMid;
+
+ vec3_t vTop, vBottom;
+
+ vTop[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) / 2);
+ vTop[1] = b->mins[1] + ((b->maxs[1] - b->mins[1]) / 2);
+ vTop[2] = b->maxs[2];
+
+ VectorCopy(vTop, vBottom);
+ vBottom[2] = b->mins[2];
+
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ qglBegin(GL_TRIANGLE_FAN);
+ qglVertex3fv(vTop);
+ qglVertex3fv(vCorners[0]);
+ qglVertex3fv(vCorners[1]);
+ qglVertex3fv(vCorners[2]);
+ qglVertex3fv(vCorners[3]);
+ qglVertex3fv(vCorners[0]);
+ qglEnd();
+ qglBegin(GL_TRIANGLE_FAN);
+ qglVertex3fv(vBottom);
+ qglVertex3fv(vCorners[0]);
+ qglVertex3fv(vCorners[3]);
+ qglVertex3fv(vCorners[2]);
+ qglVertex3fv(vCorners[1]);
+ qglVertex3fv(vCorners[0]);
+ qglEnd();
+ DrawBrushEntityName (b);
+ return;
+ }
+ else if (b->owner->eclass->nShowFlags & ECLASS_MISCMODEL)
+ {
+ if (PaintedModel(b, false))
+ return;
+ }
+ }
+
+ for (face = b->brush_faces,order = 0 ; face ; face=face->next, order++)
+ {
+ // only draw polygons facing in a direction we care about
+ if (nViewType == XY)
+ {
+ if (face->plane.normal[2] <= 0)
+ continue;
+ }
+ else
+ {
+ if (nViewType == XZ)
+ {
+ if (face->plane.normal[1] <= 0)
+ continue;
+ }
+ else
+ {
+ if (face->plane.normal[0] <= 0)
+ continue;
+ }
+ }
+
+ w = face->face_winding;
+ if (!w)
+ continue;
+
+ //if (b->alphaBrush && !(face->texdef.flags & SURF_ALPHA))
+ // continue;
+
+ // draw the polygon
+ qglBegin(GL_LINE_LOOP);
+ for (i=0 ; i<w->numpoints ; i++)
+ qglVertex3fv(w->points[i]);
+ qglEnd();
+ }
+
+ DrawBrushEntityName (b);
+
+}
+
+/*
+============
+Brush_Move
+============
+*/
+void Brush_Move (brush_t *b, const vec3_t move, bool bSnap)
+{
+ int i;
+ face_t *f;
+
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ vec3_t vTemp;
+ VectorCopy(move, vTemp);
+
+ if (g_PrefsDlg.m_bTextureLock)
+ Face_MoveTexture(f, vTemp);
+
+ for (i=0 ; i<3 ; i++)
+ VectorAdd (f->planepts[i], move, f->planepts[i]);
+ }
+ Brush_Build( b, bSnap );
+
+
+ if (b->patchBrush)
+ {
+ //Patch_Move(b->nPatchID, move);
+ Patch_Move(b->pPatch, move);
+ }
+
+ if (b->terrainBrush)
+ {
+ Terrain_Move(b->pTerrain, move);
+ }
+
+
+ // PGM - keep the origin vector up to date on fixed size entities.
+ if(b->owner->eclass->fixedsize)
+ {
+ VectorAdd(b->owner->origin, move, b->owner->origin);
+ //VectorAdd(b->maxs, b->mins, b->owner->origin);
+ //VectorScale(b->owner->origin, 0.5, b->owner->origin);
+ }
+}
+
+
+
+void Brush_Print(brush_t* b)
+{
+ int nFace = 0;
+ for (face_t* f = b->brush_faces ; f ; f=f->next)
+ {
+ Sys_Printf("Face %i\n", nFace++);
+ Sys_Printf("%f %f %f\n", f->planepts[0][0], f->planepts[0][1], f->planepts[0][2]);
+ Sys_Printf("%f %f %f\n", f->planepts[1][0], f->planepts[1][1], f->planepts[1][2]);
+ Sys_Printf("%f %f %f\n", f->planepts[2][0], f->planepts[2][1], f->planepts[2][2]);
+ }
+ }
+
+
+
+/*
+=============
+Brush_MakeSided
+
+Makes the current brushhave the given number of 2d sides and turns it into a cone
+=============
+*/
+void Brush_MakeSidedCone(int sides)
+{
+ int i;
+ vec3_t mins, maxs;
+ brush_t *b;
+ texdef_t *texdef;
+ face_t *f;
+ vec3_t mid;
+ float width;
+ float sv, cv;
+
+ if (sides < 3)
+ {
+ Sys_Status ("Bad sides number", 0);
+ return;
+ }
+
+ if (!QE_SingleBrush ())
+ {
+ Sys_Status ("Must have a single brush selected", 0 );
+ return;
+ }
+
+ b = selected_brushes.next;
+ VectorCopy (b->mins, mins);
+ VectorCopy (b->maxs, maxs);
+ texdef = &g_qeglobals.d_texturewin.texdef;
+
+ Brush_Free (b);
+
+ // find center of brush
+ width = 8;
+ for (i=0 ; i<2 ; i++)
+ {
+ mid[i] = (maxs[i] + mins[i])*0.5;
+ if (maxs[i] - mins[i] > width)
+ width = maxs[i] - mins[i];
+ }
+ width /= 2;
+
+ b = Brush_Alloc();
+
+ // create bottom face
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ f->planepts[0][0] = mins[0];f->planepts[0][1] = mins[1];f->planepts[0][2] = mins[2];
+ f->planepts[1][0] = maxs[0];f->planepts[1][1] = mins[1];f->planepts[1][2] = mins[2];
+ f->planepts[2][0] = maxs[0];f->planepts[2][1] = maxs[1];f->planepts[2][2] = mins[2];
+
+ for (i=0 ; i<sides ; i++)
+ {
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ sv = sin (i*3.14159265*2/sides);
+ cv = cos (i*3.14159265*2/sides);
+
+
+ f->planepts[0][0] = floor(mid[0]+width*cv+0.5);
+ f->planepts[0][1] = floor(mid[1]+width*sv+0.5);
+ f->planepts[0][2] = mins[2];
+
+ f->planepts[1][0] = mid[0];
+ f->planepts[1][1] = mid[1];
+ f->planepts[1][2] = maxs[2];
+
+ f->planepts[2][0] = floor(f->planepts[0][0] - width * sv + 0.5);
+ f->planepts[2][1] = floor(f->planepts[0][1] + width * cv + 0.5);
+ f->planepts[2][2] = maxs[2];
+
+ }
+
+ Brush_AddToList (b, &selected_brushes);
+
+ Entity_LinkBrush (world_entity, b);
+
+ Brush_Build( b );
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+/*
+=============
+Brush_MakeSided
+
+Makes the current brushhave the given number of 2d sides and turns it into a sphere
+=============
+
+*/
+void Brush_MakeSidedSphere(int sides)
+{
+ int i,j;
+ vec3_t mins, maxs;
+ brush_t *b;
+ texdef_t *texdef;
+ face_t *f;
+ vec3_t mid;
+
+ if (sides < 4)
+ {
+ Sys_Status ("Bad sides number", 0);
+ return;
+ }
+
+ if (!QE_SingleBrush ())
+ {
+ Sys_Status ("Must have a single brush selected", 0 );
+ return;
+ }
+
+ b = selected_brushes.next;
+ VectorCopy (b->mins, mins);
+ VectorCopy (b->maxs, maxs);
+ texdef = &g_qeglobals.d_texturewin.texdef;
+
+ Brush_Free (b);
+
+ // find center of brush
+ float radius = 8;
+ for (i=0 ; i<2 ; i++)
+ {
+ mid[i] = (maxs[i] + mins[i])*0.5;
+ if (maxs[i] - mins[i] > radius)
+ radius = maxs[i] - mins[i];
+ }
+ radius /= 2;
+
+ b = Brush_Alloc();
+
+ float dt = float(2 * Q_PI / sides);
+ float dp = float(Q_PI / sides);
+ float t,p;
+ for(i=0; i <= sides-1; i++)
+ {
+ for(j=0;j <= sides-2; j++)
+ {
+ t = i * dt;
+ p = float(j * dp - Q_PI / 2);
+
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorPolar(f->planepts[0], radius, t, p);
+ VectorPolar(f->planepts[1], radius, t, p + dp);
+ VectorPolar(f->planepts[2], radius, t + dt, p + dp);
+
+ for (int k = 0; k < 3; k++)
+ VectorAdd(f->planepts[k], mid, f->planepts[k]);
+ }
+ }
+
+ p = float((sides - 1) * dp - Q_PI / 2);
+ for(i = 0; i <= sides-1; i++)
+ {
+ t = i * dt;
+
+ f = Face_Alloc();
+ f->texdef = *texdef;
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorPolar(f->planepts[0], radius, t, p);
+ VectorPolar(f->planepts[1], radius, t + dt, p + dp);
+ VectorPolar(f->planepts[2], radius, t + dt, p);
+
+ for (int k = 0; k < 3; k++)
+ VectorAdd(f->planepts[k], mid, f->planepts[k]);
+ }
+
+ Brush_AddToList (b, &selected_brushes);
+
+ Entity_LinkBrush (world_entity, b);
+
+ Brush_Build( b );
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Face_FitTexture( face_t * face, int nHeight, int nWidth )
+{
+ winding_t *w;
+ vec3_t mins,maxs;
+ int i;
+ float width, height, temp;
+ float rot_width, rot_height;
+ float cosv,sinv,ang;
+ float min_t, min_s, max_t, max_s;
+ float s,t;
+ vec3_t vecs[2];
+ vec3_t coords[4];
+ texdef_t *td;
+
+ if (nHeight < 1)
+ {
+ nHeight = 1;
+ }
+ if (nWidth < 1)
+ {
+ nWidth = 1;
+ }
+
+ ClearBounds (mins, maxs);
+
+ td = &face->texdef;
+ w = face->face_winding;
+ if (!w)
+ {
+ return;
+ }
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ AddPointToBounds( w->points[i], mins, maxs );
+ }
+ //
+ // get the current angle
+ //
+ ang = td->rotate / 180 * Q_PI;
+ sinv = sin(ang);
+ cosv = cos(ang);
+
+ // get natural texture axis
+ TextureAxisFromPlane(&face->plane, vecs[0], vecs[1]);
+
+ min_s = DotProduct( mins, vecs[0] );
+ min_t = DotProduct( mins, vecs[1] );
+ max_s = DotProduct( maxs, vecs[0] );
+ max_t = DotProduct( maxs, vecs[1] );
+ width = max_s - min_s;
+ height = max_t - min_t;
+ coords[0][0] = min_s;
+ coords[0][1] = min_t;
+ coords[1][0] = max_s;
+ coords[1][1] = min_t;
+ coords[2][0] = min_s;
+ coords[2][1] = max_t;
+ coords[3][0] = max_s;
+ coords[3][1] = max_t;
+ min_s = min_t = 99999;
+ max_s = max_t = -99999;
+ for (i=0; i<4; i++)
+ {
+ s = cosv * coords[i][0] - sinv * coords[i][1];
+ t = sinv * coords[i][0] + cosv * coords[i][1];
+ if (i&1)
+ {
+ if (s > max_s)
+ {
+ max_s = s;
+ }
+ }
+ else
+ {
+ if (s < min_s)
+ {
+ min_s = s;
+ }
+ if (i<2)
+ {
+ if (t < min_t)
+ {
+ min_t = t;
+ }
+ }
+ else
+ {
+ if (t > max_t)
+ {
+ max_t = t;
+ }
+ }
+ }
+ }
+ rot_width = (max_s - min_s);
+ rot_height = (max_t - min_t);
+ td->scale[0] = -(rot_width/((float)(face->d_texture->width*nWidth)));
+ td->scale[1] = -(rot_height/((float)(face->d_texture->height*nHeight)));
+
+ td->shift[0] = min_s/td->scale[0];
+ temp = (int)(td->shift[0] / (face->d_texture->width*nWidth));
+ temp = (temp+1)*face->d_texture->width*nWidth;
+ td->shift[0] = (int)(temp - td->shift[0])%(face->d_texture->width*nWidth);
+
+ td->shift[1] = min_t/td->scale[1];
+ temp = (int)(td->shift[1] / (face->d_texture->height*nHeight));
+ temp = (temp+1)*(face->d_texture->height*nHeight);
+ td->shift[1] = (int)(temp - td->shift[1])%(face->d_texture->height*nHeight);
+}
+
+void Brush_FitTexture( brush_t *b, int nHeight, int nWidth )
+{
+ face_t *face;
+
+ for (face = b->brush_faces ; face ; face=face->next)
+ {
+ Face_FitTexture( face, nHeight, nWidth );
+ }
+}
+
+
diff --git a/q3radiant/BrushScript.cpp b/q3radiant/BrushScript.cpp
new file mode 100755
index 0000000..6a0614a
--- /dev/null
+++ b/q3radiant/BrushScript.cpp
@@ -0,0 +1,672 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// BrushScript stuff
+//
+#include "stdafx.h"
+#include "qe3.h"
+#include "BSInput.h"
+#include "DialogInfo.h"
+
+
+//
+struct SVariableDef
+{
+ CString m_strName;
+ CString m_strInput;
+ float m_fValue;
+};
+
+struct SVecVariableDef
+{
+ CString m_strName;
+ CString m_strInput;
+ vec3_t m_vValue;
+};
+
+
+
+const int MAX_VARIABLES = 64;
+
+brush_t* g_pHold1 = NULL;
+brush_t* g_pHold2 = NULL;
+brush_t* g_pHold3 = NULL;
+bool g_bRotateAroundSelection;
+int g_nVariableCount;
+int g_nVecVariableCount;
+int g_nLoopCounter;
+float g_fDefault = 9999.9;
+vec3_t g_vDefault;
+bool g_bStartLoop;
+char* g_pLooper;
+bool g_bKeepGoing;
+
+SVariableDef g_Variables[MAX_VARIABLES];
+SVecVariableDef g_VecVariables[MAX_VARIABLES];
+
+void InitForScriptRun()
+{
+ g_pHold1 = NULL;
+ g_pHold2 = NULL;
+ g_pHold3 = NULL;
+ g_bRotateAroundSelection = true;
+ g_nVariableCount = 0;
+ g_nVecVariableCount = 0;
+ g_nLoopCounter = 0;
+ g_bStartLoop = false;
+ g_pLooper = NULL;
+ g_bKeepGoing = true;
+}
+
+void AddVariable(const char* pName, float fValue, const char* pInput = NULL)
+{
+ if (g_nVariableCount < MAX_VARIABLES)
+ {
+ g_Variables[g_nVariableCount].m_strName = pName;
+ g_Variables[g_nVariableCount].m_strName.MakeLower();
+ g_Variables[g_nVariableCount].m_fValue = fValue;
+ if (pInput)
+ g_Variables[g_nVariableCount].m_strInput = pInput;
+ g_nVariableCount++;
+ }
+ else
+ g_pParentWnd->MessageBox("Maximum script variable limit reached!");
+}
+
+float VariableValue(const char* pName)
+{
+ CString strName = pName;
+ strName.MakeLower();
+ for (int n = 0; n < g_nVariableCount; n++)
+ {
+ if (strName == g_Variables[n].m_strName)
+ return g_Variables[n].m_fValue;
+ }
+ //strName.Format("Reference to non-existant varirable %s", pName);
+ //g_pParentWnd->MessageBox(strName);
+ return g_fDefault;
+}
+
+void SetVariableValue(const char* pName, float fValue)
+{
+ CString strName = pName;
+ strName.MakeLower();
+ for (int n = 0; n < g_nVariableCount; n++)
+ {
+ if (strName == g_Variables[n].m_strName)
+ g_Variables[n].m_fValue = fValue;
+ }
+}
+
+
+
+void AddVectorVariable(const char* pName, const char* pInput = NULL)
+{
+ if (g_nVecVariableCount < MAX_VARIABLES)
+ {
+ g_VecVariables[g_nVecVariableCount].m_strName = pName;
+ g_VecVariables[g_nVecVariableCount].m_strName.MakeLower();
+ if (pInput)
+ g_VecVariables[g_nVariableCount].m_strInput = pInput;
+ g_nVecVariableCount++;
+ }
+ else
+ g_pParentWnd->MessageBox("Maximum script variable limit reached!");
+}
+
+void VectorVariableValue(const char* pName, vec3_t& v)
+{
+ CString strName = pName;
+ strName.MakeLower();
+ for (int n = 0; n < g_nVecVariableCount; n++)
+ {
+ if (strName == g_VecVariables[n].m_strName)
+ {
+ VectorCopy(g_VecVariables[n].m_vValue, v);
+ return;
+ }
+ }
+ strName.Format("Reference to non-existant variable %s", pName);
+ g_pParentWnd->MessageBox(strName);
+}
+
+void SetVectorVariableValue(const char* pName, vec3_t v)
+{
+ CString strName = pName;
+ strName.MakeLower();
+ for (int n = 0; n < g_nVecVariableCount; n++)
+ {
+ if (strName == g_VecVariables[n].m_strName)
+ VectorCopy(v, g_VecVariables[n].m_vValue);
+ }
+}
+
+
+
+
+
+// commands
+//
+// _CopySelected(nHoldPos)
+// copies selected brush to hold spot 1, 2 or 3
+//
+// _MoveSelected(x, y, z)
+// moves selected brush by coords provided
+//
+// _RotateSelected(x, y, z)
+// rotates selected brush by coords provided
+//
+// _MoveHold(nHoldPos, x, y, z)
+// moves brush in hold pos by coords provided
+//
+// _RotateHold(nHoldPos, x, y, z)
+// rotates brush in hold pos by coords provided
+//
+// _CopyToMap(nHoldPos)
+// copies hold brush to map
+//
+// _CopyAndSelect(nHoldPos)
+// copies hold brush to map and selects it
+//
+// _Input(VarName1, ... VarNamennn)
+// inputs a list of values from the user
+//
+
+typedef void (PFNScript)(char*&);
+
+
+struct SBrushScript
+{
+ const char* m_pName;
+ PFNScript* m_pProc;
+};
+
+
+const char* GetParam(char*& pBuffer)
+{
+ static CString strParam;
+ bool bStringMode = false;
+
+ while (*pBuffer != NULL && isspace(*pBuffer)) // skip and whitespace
+ pBuffer++;
+
+ if (*pBuffer == '(') // if it's an opening paren, skip it
+ pBuffer++;
+
+ if (*pBuffer == '\"') // string ?
+ {
+ pBuffer++;
+ bStringMode = true;
+ }
+
+ strParam = "";
+
+ if (bStringMode)
+ {
+ while (*pBuffer != NULL && *pBuffer != '\"')
+ strParam += *pBuffer++;
+ }
+ else
+ {
+ while (*pBuffer != NULL && *pBuffer != ' ' && *pBuffer != ')' && *pBuffer != ',')
+ strParam += *pBuffer++;
+ }
+
+ if (*pBuffer != NULL) // skip last char
+ pBuffer++;
+
+ if (strParam.GetLength() > 0)
+ {
+ if (strParam.GetAt(0) == '$') // ? variable name
+ {
+ float f = VariableValue(strParam);
+ if (f != g_fDefault)
+ strParam.Format("%f", f);
+ }
+ }
+
+ return strParam;
+}
+
+brush_t* CopyBrush(brush_t* p)
+{
+ brush_t* pCopy = Brush_Clone(p);
+ //Brush_AddToList (pCopy, &active_brushes);
+ //Entity_LinkBrush (world_entity, pCopy);
+ Brush_Build(pCopy, false);
+ return pCopy;
+}
+
+
+void CopySelected(char*& pBuffer)
+{
+ // expects one param
+ CString strParam = GetParam(pBuffer);
+ int n = atoi(strParam);
+
+ brush_t* pCopy = NULL;
+ if (selected_brushes.next != &selected_brushes &&
+ selected_brushes.next->next == &selected_brushes)
+ pCopy = selected_brushes.next;
+
+ if (pCopy)
+ {
+ if (n == 1)
+ {
+ //if (g_pHold1)
+ //Brush_Free(g_pHold1);
+ g_pHold1 = CopyBrush(pCopy);
+ }
+ else if (n == 2)
+ {
+ //if (g_pHold2)
+ //Brush_Free(g_pHold2);
+ g_pHold2 = CopyBrush(pCopy);
+ }
+ else
+ {
+ //if (g_pHold3)
+ //Brush_Free(g_pHold3);
+ g_pHold3 = CopyBrush(pCopy);
+ }
+ }
+}
+
+void MoveSelected(char*& pBuffer)
+{
+ vec3_t v;
+ CString strParam = GetParam(pBuffer);
+ v[0] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[1] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[2] = atof(strParam);
+ Select_Move(v, false);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void RotateSelected(char*& pBuffer)
+{
+ vec3_t v;
+
+ if (g_bRotateAroundSelection)
+ {
+ Select_GetTrueMid(v);
+ VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin());
+ }
+
+ CString strParam = GetParam(pBuffer);
+ v[0] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[1] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[2] = atof(strParam);
+ for (int i = 0; i < 3; i++)
+ if (v[i] != 0.0)
+ Select_RotateAxis(i, v[i], false , true);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void MoveHold(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ brush_t* pBrush = NULL;
+ int nHold = atoi(strParam);
+ if (nHold == 1)
+ pBrush = g_pHold1;
+ else if (nHold == 2)
+ pBrush = g_pHold2;
+ else
+ pBrush = g_pHold3;
+
+ if (pBrush)
+ {
+ vec3_t v;
+ strParam = GetParam(pBuffer);
+ v[0] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[1] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[2] = atof(strParam);
+ Brush_Move (pBrush, v, false);
+ }
+}
+
+void RotateHold(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ brush_t* pBrush = NULL;
+ int nHold = atoi(strParam);
+ if (nHold == 1)
+ pBrush = g_pHold1;
+ else if (nHold == 2)
+ pBrush = g_pHold2;
+ else
+ pBrush = g_pHold3;
+
+ if (pBrush)
+ {
+ vec3_t v;
+ strParam = GetParam(pBuffer);
+ v[0] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[1] = atof(strParam);
+ strParam = GetParam(pBuffer);
+ v[2] = atof(strParam);
+ for (int i = 0; i < 3; i++)
+ if (v[i] != 0.0)
+ Select_RotateAxis(i, v[i]);
+ }
+}
+
+void CopyToMap(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ brush_t* pBrush = NULL;
+ int nHold = atoi(strParam);
+ if (nHold == 1)
+ pBrush = g_pHold1;
+ else if (nHold == 2)
+ pBrush = g_pHold2;
+ else
+ pBrush = g_pHold3;
+
+ if (pBrush)
+ {
+ Brush_AddToList(pBrush, &active_brushes);
+ Entity_LinkBrush (world_entity, pBrush);
+ Brush_Build(pBrush, false);
+ Sys_UpdateWindows(W_ALL);
+ }
+}
+
+void CopyAndSelect(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ brush_t* pBrush = NULL;
+ int nHold = atoi(strParam);
+ if (nHold == 1)
+ pBrush = g_pHold1;
+ else if (nHold == 2)
+ pBrush = g_pHold2;
+ else
+ pBrush = g_pHold3;
+
+ if (pBrush)
+ {
+ Select_Deselect();
+ Brush_AddToList(pBrush, &active_brushes);
+ Entity_LinkBrush (world_entity, pBrush);
+ Brush_Build(pBrush, false);
+ Select_Brush(pBrush);
+ Sys_UpdateWindows(W_ALL);
+ }
+}
+
+void Input(char*& pBuffer)
+{
+ CBSInput dlg;
+ bool bGo = false;
+ for (int n = 0; n < g_nVariableCount; n++)
+ {
+ if (g_Variables[n].m_strInput.GetLength() > 0)
+ {
+ bGo = true;
+ if (n < 5)
+ {
+ switch (n)
+ {
+ case 0 : dlg.m_strField1 = g_Variables[n].m_strInput; break;
+ case 1 : dlg.m_strField2 = g_Variables[n].m_strInput; break;
+ case 2 : dlg.m_strField3 = g_Variables[n].m_strInput; break;
+ case 3 : dlg.m_strField4 = g_Variables[n].m_strInput; break;
+ case 4 : dlg.m_strField5 = g_Variables[n].m_strInput; break;
+ }
+ }
+ }
+ }
+ if (bGo)
+ {
+ if (dlg.DoModal() == IDOK)
+ {
+ for (int n = 0; n < g_nVariableCount; n++)
+ {
+ if (g_Variables[n].m_strInput.GetLength() > 0)
+ {
+ if (n < 5)
+ {
+ switch (n)
+ {
+ case 0 : g_Variables[n].m_fValue = dlg.m_fField1; break;
+ case 1 : g_Variables[n].m_fValue = dlg.m_fField2; break;
+ case 2 : g_Variables[n].m_fValue = dlg.m_fField3; break;
+ case 3 : g_Variables[n].m_fValue = dlg.m_fField4; break;
+ case 4 : g_Variables[n].m_fValue = dlg.m_fField5; break;
+ }
+ }
+ }
+ }
+ }
+ else g_bKeepGoing = false;
+ }
+}
+
+bool g_bWaiting;
+void _3DPointDone(bool b, int n)
+{
+ g_bWaiting = false;
+}
+
+void _3DPointInput(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ CString strParam2 = GetParam(pBuffer);
+ ShowInfoDialog(strParam2);
+ AddVectorVariable(strParam, strParam2);
+ g_bWaiting = true;
+ AcquirePath(2, &_3DPointDone);
+ while (g_bWaiting)
+ {
+ MSG msg;
+ if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ HideInfoDialog();
+ SetVectorVariableValue(strParam, g_PathPoints[0]);
+}
+
+void SetRotateOrigin(char*& pBuffer)
+{
+ vec3_t v;
+ CString strParam = GetParam(pBuffer);
+ VectorVariableValue(strParam, v);
+ VectorCopy(v, g_pParentWnd->ActiveXY()->RotateOrigin());
+ g_bRotateAroundSelection = false;
+}
+
+void InputVar(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ CString strParam2 = GetParam(pBuffer);
+ AddVariable(strParam, 0.0, strParam2);
+}
+
+void LoopCount(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ g_nLoopCounter = atoi(strParam);
+ if (g_nLoopCounter == 0)
+ g_nLoopCounter = VariableValue(strParam);
+ if (g_nLoopCounter > 0)
+ g_pLooper = pBuffer;
+}
+
+void LoopRun(char*& pBuffer)
+{
+ if (g_bStartLoop == true)
+ {
+ g_nLoopCounter--;
+ if (g_nLoopCounter == 0)
+ {
+ g_bStartLoop = false;
+ GetParam(pBuffer);
+ }
+ else
+ pBuffer = g_pLooper;
+ }
+ else
+ {
+ if (g_pLooper && g_nLoopCounter > 0)
+ {
+ g_bStartLoop = true;
+ pBuffer = g_pLooper;
+ }
+ else
+ {
+ GetParam(pBuffer);
+ }
+ }
+}
+
+
+void ConfirmMessage(char*& pBuffer)
+{
+ CString strParam = GetParam(pBuffer);
+ if (g_pParentWnd->MessageBox(strParam, "Script Info", MB_OKCANCEL) == IDCANCEL)
+ g_bKeepGoing = false;
+}
+
+void Spherize(char*& pBuffer)
+{
+ g_bScreenUpdates = false;
+ for (int n = 0; n < 120; n += 36)
+ {
+ for (int i = 0; i < 360; i += 36)
+ {
+ Select_RotateAxis(0, i, false , true);
+ CSG_Subtract();
+ }
+ Select_RotateAxis(2, n, false , true);
+ }
+ g_bScreenUpdates = true;
+}
+
+void RunIt(char*& pBuffer);
+SBrushScript g_ScriptCmds[] =
+{
+ {"_CopySelected", &CopySelected},
+ {"_MoveSelected", &MoveSelected},
+ {"_RotateSelected", &RotateSelected},
+ {"_MoveHold", &MoveHold},
+ {"_RotateHold", &RotateHold},
+ {"_CopyToMap", &CopyToMap},
+ {"_CopyAndSelect", &CopyAndSelect},
+ {"_Input", &Input},
+ {"_3DPointInput", &_3DPointInput},
+ {"_SetRotateOrigin", &SetRotateOrigin},
+ {"_InputVar", &InputVar},
+ {"_LoopCount", &LoopCount},
+ {"_LoopRun", &LoopRun},
+ {"_ConfirmMessage", &ConfirmMessage},
+ {"_Spherize", &Spherize},
+ {"_RunScript", RunIt}
+};
+
+const int g_nScriptCmdCount = sizeof(g_ScriptCmds) / sizeof(SBrushScript);
+
+void RunScript(char* pBuffer)
+{
+ g_pHold1 = NULL;
+ g_pHold2 = NULL;
+ g_pHold3 = NULL;
+
+ while (g_bKeepGoing && pBuffer && *pBuffer)
+ {
+ while (*pBuffer != NULL && *pBuffer != '_')
+ pBuffer++;
+
+ char* pTemp = pBuffer;
+ int nLen = 0;
+ while (*pTemp != NULL && *pTemp != '(')
+ {
+ pTemp++;
+ nLen++;
+ }
+ if (*pBuffer != NULL)
+ {
+ bool bFound = false;
+ for (int i = 0; i < g_nScriptCmdCount; i++)
+ {
+ //if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, strlen(g_ScriptCmds[i].m_pName)) == 0)
+ if (strnicmp(g_ScriptCmds[i].m_pName, pBuffer, nLen) == 0)
+ {
+ pBuffer += strlen(g_ScriptCmds[i].m_pName);
+ g_ScriptCmds[i].m_pProc(pBuffer);
+ if (g_bStartLoop)
+ {
+ }
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound)
+ pBuffer++;
+ }
+ }
+}
+
+
+void RunScriptByName(char* pBuffer, bool bInit)
+{
+ if (bInit)
+ InitForScriptRun();
+ char* pScript = new char[4096];
+ CString strINI = g_strAppPath;
+ strINI += "\\scripts.ini";
+ GetPrivateProfileSection(pBuffer, pScript, 16384, strINI);
+ CString strScript;
+ char* pWorkScript = pScript;
+ while (*pWorkScript != NULL)
+ {
+ strScript += pWorkScript;
+ pWorkScript += strlen(pWorkScript) + 1;
+ }
+ RunScript(strScript.GetBuffer(0));
+}
+
+
+void RunIt(char*& pBuffer)
+{
+ brush_t* p1 = g_pHold1;
+ brush_t* p2 = g_pHold2;
+ brush_t* p3 = g_pHold3;
+
+ CString strParam = GetParam(pBuffer);
+ RunScriptByName(strParam.GetBuffer(0), false);
+
+ g_pHold3 = p3;
+ g_pHold2 = p2;
+ g_pHold1 = p1;
+}
+
diff --git a/q3radiant/CAMERA.H b/q3radiant/CAMERA.H
new file mode 100755
index 0000000..a1fbfa1
--- /dev/null
+++ b/q3radiant/CAMERA.H
@@ -0,0 +1,51 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+// window system independent camera view code
+
+typedef enum
+{
+ cd_wire,
+ cd_solid,
+ cd_texture,
+ cd_light,
+ cd_blend
+} camera_draw_mode;
+
+typedef struct
+{
+ int width, height;
+
+ qboolean timing;
+
+ vec3_t origin;
+ vec3_t angles;
+
+ camera_draw_mode draw_mode;
+
+ vec3_t color; // background
+
+ vec3_t forward, right, up; // move matrix
+
+ vec3_t vup, vpn, vright; // view matrix
+} camera_t;
+
diff --git a/q3radiant/CSG.CPP b/q3radiant/CSG.CPP
new file mode 100755
index 0000000..eef0b14
--- /dev/null
+++ b/q3radiant/CSG.CPP
@@ -0,0 +1,686 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "stdafx.h"
+#include "qe3.h"
+#include "winding.h"
+
+
+/*
+=============
+CSG_MakeHollow
+=============
+*/
+
+void Brush_Scale(brush_t* b)
+{
+ for (face_t* f = b->brush_faces ; f ; f=f->next)
+ {
+ for (int i=0 ; i<3 ; i++)
+ {
+ VectorScale (f->planepts[i], g_qeglobals.d_gridsize, f->planepts[i]);
+ }
+ }
+}
+
+void CSG_MakeHollow (void)
+{
+ brush_t *b, *front, *back, *next;
+ face_t *f;
+ face_t split;
+ vec3_t move;
+ int i;
+
+ for (b = selected_brushes.next ; b != &selected_brushes ; b=next)
+ {
+ next = b->next;
+
+ if (b->owner->eclass->fixedsize || b->patchBrush || b->terrainBrush || b->hiddenBrush)
+ continue;
+
+ for (f = b->brush_faces ; f ; f=f->next)
+ {
+ split = *f;
+ VectorScale (f->plane.normal, g_qeglobals.d_gridsize, move);
+ for (i=0 ; i<3 ; i++)
+ VectorSubtract (split.planepts[i], move, split.planepts[i]);
+
+ Brush_SplitBrushByFace (b, &split, &front, &back);
+ if (back)
+ Brush_Free (back);
+ if (front)
+ Brush_AddToList (front, &selected_brushes);
+ }
+ Brush_Free (b);
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+/*
+=============
+Brush_Merge
+
+ Returns a new brush that is created by merging brush1 and brush2.
+ May return NULL if brush1 and brush2 do not create a convex brush when merged.
+ The input brushes brush1 and brush2 stay intact.
+
+ if onlyshape is true then the merge is allowed based on the shape only
+ otherwise the texture/shader references of faces in the same plane have to
+ be the same as well.
+=============
+*/
+brush_t *Brush_Merge(brush_t *brush1, brush_t *brush2, int onlyshape)
+{
+ int i, shared;
+ brush_t *newbrush;
+ face_t *face1, *face2, *newface, *f;
+
+ // check for bounding box overlapp
+ for (i = 0; i < 3; i++)
+ {
+ if (brush1->mins[i] > brush2->maxs[i] + ON_EPSILON
+ || brush1->maxs[i] < brush2->mins[i] - ON_EPSILON)
+ {
+ // never merge if the brushes overlap
+ return NULL;
+ }
+ }
+ //
+ shared = 0;
+ // check if the new brush would be convex... flipped planes make a brush non-convex
+ for (face1 = brush1->brush_faces; face1; face1 = face1->next)
+ {
+ // don't check the faces of brush 1 and 2 touching each other
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ if (Plane_Equal(&face1->plane, &face2->plane, true))
+ {
+ shared++;
+ // there may only be ONE shared side
+ if (shared > 1)
+ return NULL;
+ break;
+ }
+ }
+ // if this face plane is shared
+ if (face2) continue;
+ //
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ // don't check the faces of brush 1 and 2 touching each other
+ for (f = brush1->brush_faces; f; f = f->next)
+ {
+ if (Plane_Equal(&face2->plane, &f->plane, true)) break;
+ }
+ if (f)
+ continue;
+ //
+ if (Plane_Equal(&face1->plane, &face2->plane, false))
+ {
+ //if the texture/shader references should be the same but are not
+ if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL;
+ continue;
+ }
+ //
+ if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
+ face1->plane.normal, face2->plane.normal,
+ face1->plane.dist, face2->plane.dist))
+ {
+ return NULL;
+ } //end if
+ } //end for
+ } //end for
+ //
+ newbrush = Brush_Alloc();
+ //
+ for (face1 = brush1->brush_faces; face1; face1 = face1->next)
+ {
+ // don't add the faces of brush 1 and 2 touching each other
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ if (Plane_Equal(&face1->plane, &face2->plane, true))
+ break;
+ }
+ if (face2)
+ continue;
+ // don't add faces with the same plane twice
+ for (f = newbrush->brush_faces; f; f = f->next)
+ {
+ if (Plane_Equal(&face1->plane, &f->plane, false))
+ break;
+ if (Plane_Equal(&face1->plane, &f->plane, true))
+ break;
+ }
+ if (f)
+ continue;
+ //
+ newface = Face_Alloc();
+ newface->texdef = face1->texdef;
+ VectorCopy(face1->planepts[0], newface->planepts[0]);
+ VectorCopy(face1->planepts[1], newface->planepts[1]);
+ VectorCopy(face1->planepts[2], newface->planepts[2]);
+ newface->plane = face1->plane;
+ newface->next = newbrush->brush_faces;
+ newbrush->brush_faces = newface;
+ }
+ //
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ // don't add the faces of brush 1 and 2 touching each other
+ for (face1 = brush1->brush_faces; face1; face1 = face1->next)
+ {
+ if (Plane_Equal(&face2->plane, &face1->plane, true))
+ break;
+ }
+ if (face1)
+ continue;
+ // don't add faces with the same plane twice
+ for (f = newbrush->brush_faces; f; f = f->next)
+ {
+ if (Plane_Equal(&face2->plane, &f->plane, false))
+ break;
+ if (Plane_Equal(&face2->plane, &f->plane, true))
+ break;
+ }
+ if (f)
+ continue;
+ //
+ newface = Face_Alloc();
+ newface->texdef = face2->texdef;
+ VectorCopy(face2->planepts[0], newface->planepts[0]);
+ VectorCopy(face2->planepts[1], newface->planepts[1]);
+ VectorCopy(face2->planepts[2], newface->planepts[2]);
+ newface->plane = face2->plane;
+ newface->next = newbrush->brush_faces;
+ newbrush->brush_faces = newface;
+ }
+ // link the new brush to an entity
+ Entity_LinkBrush (brush1->owner, newbrush);
+ // build windings for the faces
+ Brush_BuildWindings( newbrush, false);
+ return newbrush;
+}
+
+/*
+=============
+Brush_MergeListPairs
+
+ Returns a list with merged brushes.
+ Tries to merge brushes pair wise.
+ The input list is destroyed.
+ Input and output should be a single linked list using .next
+=============
+*/
+brush_t *Brush_MergeListPairs(brush_t *brushlist, int onlyshape)
+{
+ int nummerges, merged;
+ brush_t *b1, *b2, *tail, *newbrush, *newbrushlist;
+ brush_t *lastb2;
+
+ if (!brushlist) return NULL;
+
+ nummerges = 0;
+ do
+ {
+ for (tail = brushlist; tail; tail = tail->next)
+ {
+ if (!tail->next) break;
+ }
+ merged = 0;
+ newbrushlist = NULL;
+ for (b1 = brushlist; b1; b1 = brushlist)
+ {
+ lastb2 = b1;
+ for (b2 = b1->next; b2; b2 = b2->next)
+ {
+ newbrush = Brush_Merge(b1, b2, onlyshape);
+ if (newbrush)
+ {
+ tail->next = newbrush;
+ lastb2->next = b2->next;
+ brushlist = brushlist->next;
+ b1->next = b1->prev = NULL;
+ b2->next = b2->prev = NULL;
+ Brush_Free(b1);
+ Brush_Free(b2);
+ for (tail = brushlist; tail; tail = tail->next)
+ {
+ if (!tail->next) break;
+ } //end for
+ merged++;
+ nummerges++;
+ break;
+ }
+ lastb2 = b2;
+ }
+ //if b1 can't be merged with any of the other brushes
+ if (!b2)
+ {
+ brushlist = brushlist->next;
+ //keep b1
+ b1->next = newbrushlist;
+ newbrushlist = b1;
+ }
+ }
+ brushlist = newbrushlist;
+ } while(merged);
+ return newbrushlist;
+}
+
+/*
+=============
+Brush_MergeList
+
+ Tries to merge all brushes in the list into one new brush.
+ The input brush list stays intact.
+ Returns NULL if no merged brush can be created.
+ To create a new brush the brushes in the list may not overlap and
+ the outer faces of the brushes together should make a new convex brush.
+
+ if onlyshape is true then the merge is allowed based on the shape only
+ otherwise the texture/shader references of faces in the same plane have to
+ be the same as well.
+=============
+*/
+brush_t *Brush_MergeList(brush_t *brushlist, int onlyshape)
+{
+ brush_t *brush1, *brush2, *brush3, *newbrush;
+ face_t *face1, *face2, *face3, *newface, *f;
+
+ if (!brushlist) return NULL;
+ for (brush1 = brushlist; brush1; brush1 = brush1->next)
+ {
+ // check if the new brush would be convex... flipped planes make a brush concave
+ for (face1 = brush1->brush_faces; face1; face1 = face1->next)
+ {
+ // don't check face1 if it touches another brush
+ for (brush2 = brushlist; brush2; brush2 = brush2->next)
+ {
+ if (brush2 == brush1) continue;
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ if (Plane_Equal(&face1->plane, &face2->plane, true))
+ {
+ break;
+ }
+ }
+ if (face2) break;
+ }
+ // if face1 touches another brush
+ if (brush2) continue;
+ //
+ for (brush2 = brush1->next; brush2; brush2 = brush2->next)
+ {
+ // don't check the faces of brush 2 touching another brush
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ for (brush3 = brushlist; brush3; brush3 = brush3->next)
+ {
+ if (brush3 == brush2) continue;
+ for (face3 = brush3->brush_faces; face3; face3 = face3->next)
+ {
+ if (Plane_Equal(&face2->plane, &face3->plane, true)) break;
+ }
+ if (face3) break;
+ }
+ // if face2 touches another brush
+ if (brush3) continue;
+ //
+ if (Plane_Equal(&face1->plane, &face2->plane, false))
+ {
+ //if the texture/shader references should be the same but are not
+ if (!onlyshape && stricmp(face1->texdef.name, face2->texdef.name) != 0) return NULL;
+ continue;
+ }
+ //
+ if (Winding_PlanesConcave(face1->face_winding, face2->face_winding,
+ face1->plane.normal, face2->plane.normal,
+ face1->plane.dist, face2->plane.dist))
+ {
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+ //
+ newbrush = Brush_Alloc();
+ //
+ for (brush1 = brushlist; brush1; brush1 = brush1->next)
+ {
+ for (face1 = brush1->brush_faces; face1; face1 = face1->next)
+ {
+ // don't add face1 to the new brush if it touches another brush
+ for (brush2 = brushlist; brush2; brush2 = brush2->next)
+ {
+ if (brush2 == brush1) continue;
+ for (face2 = brush2->brush_faces; face2; face2 = face2->next)
+ {
+ if (Plane_Equal(&face1->plane, &face2->plane, true))
+ {
+ break;
+ }
+ }
+ if (face2) break;
+ }
+ if (brush2) continue;
+ // don't add faces with the same plane twice
+ for (f = newbrush->brush_faces; f; f = f->next)
+ {
+ if (Plane_Equal(&face1->plane, &f->plane, false))
+ break;
+ if (Plane_Equal(&face1->plane, &f->plane, true))
+ break;
+ }
+ if (f)
+ continue;
+ //
+ newface = Face_Alloc();
+ newface->texdef = face1->texdef;
+ VectorCopy(face1->planepts[0], newface->planepts[0]);
+ VectorCopy(face1->planepts[1], newface->planepts[1]);
+ VectorCopy(face1->planepts[2], newface->planepts[2]);
+ newface->plane = face1->plane;
+ newface->next = newbrush->brush_faces;
+ newbrush->brush_faces = newface;
+ }
+ }
+ // link the new brush to an entity
+ Entity_LinkBrush (brushlist->owner, newbrush);
+ // build windings for the faces
+ Brush_BuildWindings( newbrush, false);
+ return newbrush;
+}
+
+/*
+=============
+Brush_Subtract
+
+ Returns a list of brushes that remain after B is subtracted from A.
+ May by empty if A is contained inside B.
+ The originals are undisturbed.
+=============
+*/
+brush_t *Brush_Subtract(brush_t *a, brush_t *b)
+{
+ // a - b = out (list)
+ brush_t *front, *back;
+ brush_t *in, *out, *next;
+ face_t *f;
+
+ in = a;
+ out = NULL;
+ for (f = b->brush_faces; f && in; f = f->next)
+ {
+ Brush_SplitBrushByFace(in, f, &front, &back);
+ if (in != a) Brush_Free(in);
+ if (front)
+ { // add to list
+ front->next = out;
+ out = front;
+ }
+ in = back;
+ }
+ //NOTE: in != a just in case brush b has no faces
+ if (in && in != a)
+ {
+ Brush_Free(in);
+ }
+ else
+ { //didn't really intersect
+ for (b = out; b; b = next)
+ {
+ next = b->next;
+ b->next = b->prev = NULL;
+ Brush_Free(b);
+ }
+ return a;
+ }
+ return out;
+}
+
+/*
+=============
+CSG_Subtract
+=============
+*/
+void CSG_Subtract (void)
+{
+ brush_t *b, *s, *fragments, *nextfragment, *frag, *next, *snext;
+ brush_t fragmentlist;
+ int i, numfragments, numbrushes;
+
+ Sys_Printf ("Subtracting...\n");
+
+ if (selected_brushes.next == &selected_brushes)
+ {
+ Sys_Printf("No brushes selected.\n");
+ return;
+ }
+
+ fragmentlist.next = &fragmentlist;
+ fragmentlist.prev = &fragmentlist;
+
+ numfragments = 0;
+ numbrushes = 0;
+ for (b = selected_brushes.next ; b != &selected_brushes ; b=next)
+ {
+ next = b->next;
+
+ if (b->owner->eclass->fixedsize)
+ continue; // can't use texture from a fixed entity, so don't subtract
+
+ // chop all fragments further up
+ for (s = fragmentlist.next; s != &fragmentlist; s = snext)
+ {
+ snext = s->next;
+
+ for (i=0 ; i<3 ; i++)
+ if (b->mins[i] >= s->maxs[i] - ON_EPSILON
+ || b->maxs[i] <= s->mins[i] + ON_EPSILON)
+ break;
+ if (i != 3)
+ continue; // definately don't touch
+ fragments = Brush_Subtract(s, b);
+ // if the brushes did not really intersect
+ if (fragments == s)
+ continue;
+ // try to merge fragments
+ fragments = Brush_MergeListPairs(fragments, true);
+ // add the fragments to the list
+ for (frag = fragments; frag; frag = nextfragment)
+ {
+ nextfragment = frag->next;
+ frag->next = NULL;
+ frag->owner = s->owner;
+ Brush_AddToList(frag, &fragmentlist);
+ }
+ // free the original brush
+ Brush_Free(s);
+ }
+
+ // chop any active brushes up
+ for (s = active_brushes.next; s != &active_brushes; s = snext)
+ {
+ snext = s->next;
+
+ if (s->owner->eclass->fixedsize || s->patchBrush || s->terrainBrush || s->hiddenBrush)
+ continue;
+
+ //face_t *pFace = s->brush_faces;
+ if (s->brush_faces->d_texture->bFromShader && (s->brush_faces->d_texture->nShaderFlags & QER_NOCARVE))
+ {
+ continue;
+ }
+
+ for (i=0 ; i<3 ; i++)
+ if (b->mins[i] >= s->maxs[i] - ON_EPSILON
+ || b->maxs[i] <= s->mins[i] + ON_EPSILON)
+ break;
+ if (i != 3)
+ continue; // definately don't touch
+
+ fragments = Brush_Subtract(s, b);
+ // if the brushes did not really intersect
+ if (fragments == s)
+ continue;
+ //
+ Undo_AddBrush(s);
+ // one extra brush chopped up
+ numbrushes++;
+ // try to merge fragments
+ fragments = Brush_MergeListPairs(fragments, true);
+ // add the fragments to the list
+ for (frag = fragments; frag; frag = nextfragment)
+ {
+ nextfragment = frag->next;
+ frag->next = NULL;
+ frag->owner = s->owner;
+ Brush_AddToList(frag, &fragmentlist);
+ }
+ // free the original brush
+ Brush_Free(s);
+ }
+ }
+
+ // move all fragments to the active brush list
+ for (frag = fragmentlist.next; frag != &fragmentlist; frag = nextfragment)
+ {
+ nextfragment = frag->next;
+ numfragments++;
+ Brush_RemoveFromList(frag);
+ Brush_AddToList(frag, &active_brushes);
+ Undo_EndBrush(frag);
+ }
+
+ if (numfragments == 0)
+ {
+ Sys_Printf("Selected brush%s did not intersect with any other brushes.\n",
+ (selected_brushes.next->next == &selected_brushes) ? "":"es");
+ return;
+ }
+ Sys_Printf("done. (created %d fragment%s out of %d brush%s)\n", numfragments, (numfragments == 1)?"":"s",
+ numbrushes, (numbrushes == 1)?"":"es");
+ Sys_UpdateWindows(W_ALL);
+}
+
+/*
+=============
+CSG_Merge
+=============
+*/
+void CSG_Merge(void)
+{
+ brush_t *b, *next, *newlist, *newbrush;
+ struct entity_s *owner;
+
+ Sys_Printf ("Merging...\n");
+
+ if (selected_brushes.next == &selected_brushes)
+ {
+ Sys_Printf("No brushes selected.\n");
+ return;
+ }
+
+ if (selected_brushes.next->next == &selected_brushes)
+ {
+ Sys_Printf("At least two brushes have to be selected.\n");
+ return;
+ }
+
+ owner = selected_brushes.next->owner;
+
+ for (b = selected_brushes.next; b != &selected_brushes; b = next)
+ {
+ next = b->next;
+
+ if (b->owner->eclass->fixedsize)
+ {
+ // can't use texture from a fixed entity, so don't subtract
+ Sys_Printf("Cannot add fixed size entities.\n");
+ return;
+ }
+
+ if (b->patchBrush)
+ {
+ Sys_Printf("Cannot add patches.\n");
+ return;
+ }
+ if (b->terrainBrush)
+ {
+ Sys_Printf("Cannot add terrains.\n");
+ return;
+ }
+
+ if (b->brush_faces->d_texture->bFromShader && (b->brush_faces->d_texture->nShaderFlags & QER_NOCARVE))
+ {
+ Sys_Printf("Cannot add brushes using shaders that don't allows CSG operations.\n");
+ return;
+ }
+
+ if (b->owner != owner)
+ {
+ Sys_Printf("Cannot add brushes from different entities.\n");
+ return;
+ }
+
+ }
+
+ newlist = NULL;
+ for (b = selected_brushes.next; b != &selected_brushes; b = next)
+ {
+ next = b->next;
+
+ Brush_RemoveFromList(b);
+ b->next = newlist;
+ b->prev = NULL;
+ newlist = b;
+ }
+
+ newbrush = Brush_MergeList(newlist, true);
+ // if the new brush would not be convex
+ if (!newbrush)
+ {
+ // add the brushes back into the selection
+ for (b = newlist; b; b = next)
+ {
+ next = b->next;
+ b->next = NULL;
+ b->prev = NULL;
+ Brush_AddToList(b, &selected_brushes);
+ }
+ Sys_Printf("Cannot add a set of brushes with a concave hull.\n");
+ return;
+ }
+ // free the original brushes
+ for (b = newlist; b; b = next)
+ {
+ next = b->next;
+ b->next = NULL;
+ b->prev = NULL;
+ Brush_Free(b);
+ }
+ Brush_AddToList(newbrush, &selected_brushes);
+
+ Sys_Printf ("done.\n");
+ Sys_UpdateWindows (W_ALL);
+}
diff --git a/q3radiant/CamWnd.cpp b/q3radiant/CamWnd.cpp
new file mode 100755
index 0000000..0ea352d
--- /dev/null
+++ b/q3radiant/CamWnd.cpp
@@ -0,0 +1,1165 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// CamWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "XYWnd.h"
+#include "CamWnd.h"
+#include "qe3.h"
+#include "splines/splines.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+extern void DrawPathLines();
+
+int g_nAngleSpeed = 300;
+int g_nMoveSpeed = 400;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCamWnd
+IMPLEMENT_DYNCREATE(CCamWnd, CWnd);
+
+CCamWnd::CCamWnd()
+{
+ m_pXYFriend = NULL;
+ m_nNumTransBrushes = 0;
+ memset(&m_Camera, 0, sizeof(camera_t));
+ m_pSide_select = NULL;
+ m_bClipMode = false;
+ Cam_Init();
+}
+
+CCamWnd::~CCamWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CCamWnd, CWnd)
+ //{{AFX_MSG_MAP(CCamWnd)
+ ON_WM_KEYDOWN()
+ ON_WM_PAINT()
+ ON_WM_DESTROY()
+ ON_WM_CLOSE()
+ ON_WM_MOUSEMOVE()
+ ON_WM_LBUTTONDOWN()
+ ON_WM_LBUTTONUP()
+ ON_WM_MBUTTONDOWN()
+ ON_WM_MBUTTONUP()
+ ON_WM_RBUTTONDOWN()
+ ON_WM_RBUTTONUP()
+ ON_WM_CREATE()
+ ON_WM_SIZE()
+ ON_WM_NCCALCSIZE()
+ ON_WM_KILLFOCUS()
+ ON_WM_SETFOCUS()
+ ON_WM_KEYUP()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+LONG WINAPI CamWndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ RECT rect;
+
+ GetClientRect(hWnd, &rect);
+
+ switch (uMsg)
+ {
+ case WM_KILLFOCUS:
+ case WM_SETFOCUS:
+ SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
+ return 0;
+
+ case WM_NCCALCSIZE:// don't let windows copy pixels
+ DefWindowProc (hWnd, uMsg, wParam, lParam);
+ return WVR_REDRAW;
+
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CCamWnd message handlers
+
+BOOL CCamWnd::PreCreateWindow(CREATESTRUCT& cs)
+{
+ WNDCLASS wc;
+ HINSTANCE hInstance = AfxGetInstanceHandle();
+ if (::GetClassInfo(hInstance, CAMERA_WINDOW_CLASS, &wc) == FALSE)
+ {
+ // Register a new class
+ memset (&wc, 0, sizeof(wc));
+ wc.style = CS_NOCLOSE | CS_OWNDC;
+ wc.lpszClassName = CAMERA_WINDOW_CLASS;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.lpfnWndProc = CamWndProc;
+ if (AfxRegisterClass(&wc) == FALSE)
+ Error ("CCamWnd RegisterClass: failed");
+ }
+
+ cs.lpszClass = CAMERA_WINDOW_CLASS;
+ cs.lpszName = "CAM";
+ if (cs.style != QE3_CHILDSTYLE)
+ cs.style = QE3_SPLITTER_STYLE;
+
+ BOOL bResult = CWnd::PreCreateWindow(cs);
+
+ // See if the class already exists and if not then we need
+ // to register our new window class.
+ return bResult;
+
+}
+
+
+void CCamWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
+}
+
+
+brush_t* g_pSplitList = NULL;
+
+void CCamWnd::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+ bool bPaint = true;
+ if (!qwglMakeCurrent( dc.m_hDC, g_qeglobals.d_hglrcBase ))
+ {
+ Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
+ Sys_Printf("Please restart Q3Radiant if the camera view is not working\n");
+ }
+ else
+ {
+ QE_CheckOpenGLForErrors();
+ g_pSplitList = NULL;
+ if (g_bClipMode)
+ {
+ if (g_Clip1.Set() && g_Clip2.Set())
+ {
+ g_pSplitList = ( (g_pParentWnd->ActiveXY()->GetViewType() == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
+ }
+ }
+ Cam_Draw ();
+ QE_CheckOpenGLForErrors();
+ qwglSwapBuffers(dc.m_hDC);
+ }
+}
+
+
+void CCamWnd::SetXYFriend(CXYWnd * pWnd)
+{
+ m_pXYFriend = pWnd;
+}
+
+void CCamWnd::OnDestroy()
+{
+ QEW_StopGL(GetSafeHwnd(), g_qeglobals.d_hglrcBase, g_qeglobals.d_hdcBase );
+ CWnd::OnDestroy();
+}
+
+void CCamWnd::OnClose()
+{
+ CWnd::OnClose();
+}
+
+extern void Select_ShiftTexture(int x, int y);
+extern void Select_RotateTexture(int amt);
+extern void Select_ScaleTexture(int x, int y);
+void CCamWnd::OnMouseMove(UINT nFlags, CPoint point)
+{
+ CRect r;
+ GetClientRect(r);
+ if (GetCapture() == this && (GetKeyState(VK_MENU) & 0x8000) && !((GetKeyState(VK_SHIFT) & 0x8000) || (GetKeyState(VK_CONTROL) & 0x8000)))
+ {
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ Select_RotateTexture(point.y - m_ptLastCursor.y);
+ else
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ Select_ScaleTexture(point.x - m_ptLastCursor.x, m_ptLastCursor.y - point.y);
+ else
+ Select_ShiftTexture(point.x - m_ptLastCursor.x, m_ptLastCursor.y - point.y);
+ }
+ else
+ {
+ Cam_MouseMoved(point.x, r.bottom - 1 - point.y, nFlags);
+ }
+ m_ptLastCursor = point;
+}
+
+void CCamWnd::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ m_ptLastCursor = point;
+ OriginalMouseDown(nFlags, point);
+}
+
+void CCamWnd::OnLButtonUp(UINT nFlags, CPoint point)
+{
+ OriginalMouseUp(nFlags, point);
+}
+
+void CCamWnd::OnMButtonDown(UINT nFlags, CPoint point)
+{
+ OriginalMouseDown(nFlags, point);
+}
+
+void CCamWnd::OnMButtonUp(UINT nFlags, CPoint point)
+{
+ OriginalMouseUp(nFlags, point);
+}
+
+void CCamWnd::OnRButtonDown(UINT nFlags, CPoint point)
+{
+ OriginalMouseDown(nFlags, point);
+}
+
+void CCamWnd::OnRButtonUp(UINT nFlags, CPoint point)
+{
+ OriginalMouseUp(nFlags, point);
+}
+
+int CCamWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ g_qeglobals.d_hdcBase = GetDC()->m_hDC;
+ QEW_SetupPixelFormat(g_qeglobals.d_hdcBase, true);
+
+ if ((g_qeglobals.d_hglrcBase = qwglCreateContext(g_qeglobals.d_hdcBase)) == 0)
+ Error("wglCreateContext failed");
+
+ if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ Error ("wglMakeCurrent failed");
+
+
+ //
+ // create GL font
+ //
+ HFONT hfont = ::CreateFont(
+ 12, // logical height of font
+ 6, // logical average character width
+ 0, // angle of escapement
+ 0, // base-line orientation angle
+ 0, // font weight
+ 0, // italic attribute flag
+ 0, // underline attribute flag
+ 0, // strikeout attribute flag
+ 0, // character set identifier
+ 0, // output precision
+ 0, // clipping precision
+ 0, // output quality
+ 0, // pitch and family
+ "system font" // pointer to typeface name string
+ );
+
+ if (!hfont)
+ Error( "couldn't create font" );
+
+ ::SelectObject(g_qeglobals.d_hdcBase, hfont);
+
+ if ((g_qeglobals.d_font_list = qglGenLists (256)) == 0)
+ Error( "couldn't create font dlists" );
+
+ // create the bitmap display lists
+ // we're making images of glyphs 0 thru 255
+
+ if (g_PrefsDlg.m_bBuggyICD)
+ {
+ if ( !qwglUseFontBitmaps (g_qeglobals.d_hdcBase, 1, 255, g_qeglobals.d_font_list-1) )
+ Error( "wglUseFontBitmaps faileD" );
+ }
+ else
+ {
+ if ( !qwglUseFontBitmaps (g_qeglobals.d_hdcBase, 1, 255, g_qeglobals.d_font_list) )
+ Error( "wglUseFontBitmaps faileD" );
+ }
+
+ // indicate start of glyph display lists
+ qglListBase (g_qeglobals.d_font_list);
+
+ // report OpenGL information
+ Sys_Printf ("GL_VENDOR: %s\n", qglGetString (GL_VENDOR));
+ Sys_Printf ("GL_RENDERER: %s\n", qglGetString (GL_RENDERER));
+ Sys_Printf ("GL_VERSION: %s\n", qglGetString (GL_VERSION));
+ Sys_Printf ("GL_EXTENSIONS: %s\n", qglGetString (GL_EXTENSIONS));
+
+ g_qeglobals.d_hwndCamera = GetSafeHwnd();
+
+ return 0;
+}
+
+void CCamWnd::OriginalMouseUp(UINT nFlags, CPoint point)
+{
+ CRect r;
+ GetClientRect(r);
+ Cam_MouseUp(point.x, r.bottom - 1 - point.y, nFlags);
+ if (!(nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+}
+
+void CCamWnd::OriginalMouseDown(UINT nFlags, CPoint point)
+{
+ //if (GetTopWindow()->GetSafeHwnd() != GetSafeHwnd())
+ // BringWindowToTop();
+ CRect r;
+ GetClientRect(r);
+ SetFocus();
+ SetCapture();
+ //if (!(GetKeyState(VK_MENU) & 0x8000))
+ Cam_MouseDown (point.x, r.bottom - 1 - point.y, nFlags);
+}
+
+void CCamWnd::Cam_Init()
+{
+ //m_Camera.draw_mode = cd_texture;
+ m_Camera.timing = false;
+ m_Camera.origin[0] = 0;
+ m_Camera.origin[1] = 20;
+ m_Camera.origin[2] = 46;
+ m_Camera.color[0] = 0.3;
+ m_Camera.color[1] = 0.3;
+ m_Camera.color[2] = 0.3;
+}
+
+void CCamWnd::Cam_BuildMatrix()
+{
+ float xa, ya;
+ float matrix[4][4];
+ int i;
+
+ xa = m_Camera.angles[0]/180*Q_PI;
+ ya = m_Camera.angles[1]/180*Q_PI;
+
+ // the movement matrix is kept 2d
+
+ m_Camera.forward[0] = cos(ya);
+ m_Camera.forward[1] = sin(ya);
+ m_Camera.right[0] = m_Camera.forward[1];
+ m_Camera.right[1] = -m_Camera.forward[0];
+
+ qglGetFloatv (GL_PROJECTION_MATRIX, &matrix[0][0]);
+
+ for (i=0 ; i<3 ; i++)
+ {
+ m_Camera.vright[i] = matrix[i][0];
+ m_Camera.vup[i] = matrix[i][1];
+ m_Camera.vpn[i] = matrix[i][2];
+ }
+
+ VectorNormalize (m_Camera.vright);
+ VectorNormalize (m_Camera.vup);
+ VectorNormalize (m_Camera.vpn);
+}
+
+
+
+void CCamWnd::Cam_ChangeFloor (qboolean up)
+{
+ brush_t *b;
+ float d, bestd, current;
+ vec3_t start, dir;
+
+ start[0] = m_Camera.origin[0];
+ start[1] = m_Camera.origin[1];
+ start[2] = 8192;
+ dir[0] = dir[1] = 0;
+ dir[2] = -1;
+
+ current = 8192 - (m_Camera.origin[2] - 48);
+ if (up)
+ bestd = 0;
+ else
+ bestd = 16384;
+
+ for (b=active_brushes.next ; b != &active_brushes ; b=b->next)
+ {
+ if ( b->pTerrain && !Terrain_Ray( start, dir, b, &d ) )
+ continue;
+ if ( !b->pTerrain && !Brush_Ray (start, dir, b, &d) )
+ continue;
+ if (up && d < current && d > bestd)
+ bestd = d;
+ if (!up && d > current && d < bestd)
+ bestd = d;
+ }
+
+ if (bestd == 0 || bestd == 16384)
+ return;
+
+ m_Camera.origin[2] += current - bestd;
+ Sys_UpdateWindows (W_CAMERA|W_Z_OVERLAY);
+}
+
+
+void CCamWnd::Cam_PositionDrag()
+{
+ int x, y;
+ Sys_GetCursorPos (&x, &y);
+ if (x != m_ptCursor.x || y != m_ptCursor.y)
+ {
+ x -= m_ptCursor.x;
+ VectorMA (m_Camera.origin, x, m_Camera.vright, m_Camera.origin);
+ y -= m_ptCursor.y;
+ m_Camera.origin[2] -= y;
+ SetCursorPos(m_ptCursor.x, m_ptCursor.y);
+ Sys_UpdateWindows (W_CAMERA | W_XY_OVERLAY);
+ }
+}
+
+
+void CCamWnd::Cam_MouseControl (float dtime)
+{
+ int xl, xh;
+ int yl, yh;
+ float xf, yf;
+ if (g_PrefsDlg.m_nMouseButtons == 2)
+ {
+ if (m_nCambuttonstate != (MK_RBUTTON | MK_SHIFT))
+ return;
+ }
+ else
+ {
+ if (m_nCambuttonstate != MK_RBUTTON)
+ return;
+ }
+
+ xf = (float)(m_ptButton.x - m_Camera.width/2) / (m_Camera.width/2);
+ yf = (float)(m_ptButton.y - m_Camera.height/2) / (m_Camera.height/2);
+
+
+ xl = m_Camera.width/3;
+ xh = xl*2;
+ yl = m_Camera.height/3;
+ yh = yl*2;
+
+ //Sys_Printf("xf-%f yf-%f xl-%i xh-i% yl-i% yh-i%\n",xf,yf,xl,xh,yl,yh);
+#if 0
+ // strafe
+ if (buttony < yl && (buttonx < xl || buttonx > xh))
+ VectorMA (camera.origin, xf*dtime*g_nMoveSpeed, camera.right, camera.origin);
+ else
+#endif
+ {
+ xf *= 1.0 - fabs(yf);
+ if (xf < 0)
+ {
+ xf += 0.1;
+ if (xf > 0)
+ xf = 0;
+ }
+ else
+ {
+ xf -= 0.1;
+ if (xf < 0)
+ xf = 0;
+ }
+
+ VectorMA (m_Camera.origin, yf*dtime*g_nMoveSpeed, m_Camera.forward, m_Camera.origin);
+ m_Camera.angles[YAW] += xf*-dtime*g_nAngleSpeed;
+ }
+
+#if 0
+ if (g_PrefsDlg.m_bQE4Painting)
+ {
+ MSG msg;
+ if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+#endif
+
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+ g_pParentWnd->PostMessage(WM_TIMER, 0, 0);
+
+}
+
+
+
+void CCamWnd::Cam_MouseDown(int x, int y, int buttons)
+{
+ vec3_t dir;
+ float f, r, u;
+ int i;
+
+ //
+ // calc ray direction
+ //
+ u = (float)(y - m_Camera.height/2) / (m_Camera.width/2);
+ r = (float)(x - m_Camera.width/2) / (m_Camera.width/2);
+ f = 1;
+
+ for (i=0 ; i<3 ; i++)
+ dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
+ VectorNormalize (dir);
+
+ GetCursorPos(&m_ptCursor);
+
+ m_nCambuttonstate = buttons;
+ m_ptButton.x = x;
+ m_ptButton.y = y;
+
+ // LBUTTON = manipulate selection
+ // shift-LBUTTON = select
+ // middle button = grab texture
+ // ctrl-middle button = set entire brush to texture
+ // ctrl-shift-middle button = set single face to texture
+ int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+ if ((buttons == MK_LBUTTON)
+ || (buttons == (MK_LBUTTON | MK_SHIFT))
+ || (buttons == (MK_LBUTTON | MK_CONTROL))
+ || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT))
+ || (buttons == nMouseButton)
+ || (buttons == (nMouseButton|MK_SHIFT))
+ || (buttons == (nMouseButton|MK_CONTROL))
+ || (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL)))
+ {
+
+ if (g_PrefsDlg.m_nMouseButtons == 2 && (buttons == (MK_RBUTTON | MK_SHIFT)))
+ Cam_MouseControl (0.1);
+ else
+ {
+ // something global needs to track which window is responsible for stuff
+ Patch_SetView(W_CAMERA);
+ Drag_Begin (x, y, buttons, m_Camera.vright, m_Camera.vup, m_Camera.origin, dir);
+ }
+ return;
+ }
+
+ if (buttons == MK_RBUTTON)
+ {
+ Cam_MouseControl (0.1);
+ return;
+ }
+}
+
+
+void CCamWnd::Cam_MouseUp (int x, int y, int buttons)
+{
+ m_nCambuttonstate = 0;
+ Drag_MouseUp (buttons);
+}
+
+
+void CCamWnd::Cam_MouseMoved (int x, int y, int buttons)
+{
+ m_nCambuttonstate = buttons;
+ if (!buttons) {
+ if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) ) {
+ vec3_t dir;
+ float f, r, u;
+ int i;
+
+ //
+ // calc ray direction
+ //
+ u = (float)(y - m_Camera.height/2) / (m_Camera.width/2);
+ r = (float)(x - m_Camera.width/2) / (m_Camera.width/2);
+ f = 1;
+
+ for (i=0 ; i<3 ; i++)
+ dir[i] = m_Camera.vpn[i] * f + m_Camera.vright[i] * r + m_Camera.vup[i] * u;
+ VectorNormalize (dir);
+
+ m_ptButton.x = x;
+ m_ptButton.y = y;
+
+ Terrain_SelectPointByRay( m_Camera.origin, dir, buttons );
+
+ Sys_UpdateWindows(W_CAMERA);
+ }
+
+ return;
+ }
+ m_ptButton.x = x;
+ m_ptButton.y = y;
+
+ if (buttons == (MK_RBUTTON|MK_CONTROL) )
+ {
+ Cam_PositionDrag ();
+ Sys_UpdateWindows (W_XY|W_CAMERA|W_Z);
+ return;
+ }
+
+ GetCursorPos(&m_ptCursor);
+
+ if (buttons & (MK_LBUTTON | MK_MBUTTON) )
+ {
+ Drag_MouseMoved (x, y, buttons);
+ Sys_UpdateWindows (W_XY|W_CAMERA|W_Z);
+ }
+}
+
+
+void CCamWnd::InitCull()
+{
+ int i;
+
+ VectorSubtract (m_Camera.vpn, m_Camera.vright, m_vCull1);
+ VectorAdd (m_Camera.vpn, m_Camera.vright, m_vCull2);
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (m_vCull1[i] > 0)
+ m_nCullv1[i] = 3+i;
+ else
+ m_nCullv1[i] = i;
+ if (m_vCull2[i] > 0)
+ m_nCullv2[i] = 3+i;
+ else
+ m_nCullv2[i] = i;
+ }
+}
+
+qboolean CCamWnd::CullBrush (brush_t *b)
+{
+ int i;
+ vec3_t point;
+ float d;
+
+ if (g_PrefsDlg.m_bCubicClipping)
+ {
+ float fLevel = g_PrefsDlg.m_nCubicScale * 64;
+
+ point[0] = m_Camera.origin[0] - fLevel;
+ point[1] = m_Camera.origin[1] - fLevel;
+ point[2] = m_Camera.origin[2] - fLevel;
+
+ for (i=0; i<3; i++)
+ if (b->mins[i] < point[i] && b->maxs[i] < point[i])
+ return true;
+
+ point[0] = m_Camera.origin[0] + fLevel;
+ point[1] = m_Camera.origin[1] + fLevel;
+ point[2] = m_Camera.origin[2] + fLevel;
+
+ for (i=0; i<3; i++)
+ if (b->mins[i] > point[i] && b->maxs[i] > point[i])
+ return true;
+ }
+
+
+ for (i=0 ; i<3 ; i++)
+ point[i] = b->mins[m_nCullv1[i]] - m_Camera.origin[i];
+
+ d = DotProduct (point, m_vCull1);
+ if (d < -1)
+ return true;
+
+ for (i=0 ; i<3 ; i++)
+ point[i] = b->mins[m_nCullv2[i]] - m_Camera.origin[i];
+
+ d = DotProduct (point, m_vCull2);
+ if (d < -1)
+ return true;
+
+ return false;
+}
+
+#if 0
+void CCamWnd::DrawLightRadius(brush_t* pBrush)
+{
+ // if lighting
+ int nRadius = Brush_LightRadius(pBrush);
+ if (nRadius > 0)
+ {
+ Brush_SetLightColor(pBrush);
+ qglEnable (GL_BLEND);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglDisable (GL_TEXTURE_2D);
+
+ qglEnable(GL_TEXTURE_2D);
+ qglDisable(GL_BLEND);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ }
+}
+#endif
+
+/*
+==============
+Cam_Draw
+==============
+*/
+
+void CCamWnd::Cam_Draw()
+{
+ brush_t *brush;
+ face_t *face;
+ float screenaspect;
+ float yfov;
+ double start, end;
+ int i;
+
+ /*
+ FILE *f = fopen("g:/nardo/raduffy/editorhack.dat", "w");
+ if (f != NULL) {
+ fwrite(&m_Camera.origin[0], sizeof(float), 1, f);
+ fwrite(&m_Camera.origin[1], sizeof(float), 1, f);
+ fwrite(&m_Camera.origin[2], sizeof(float), 1, f);
+ fwrite(&m_Camera.angles[PITCH], sizeof(float), 1, f);
+ fwrite(&m_Camera.angles[YAW], sizeof(float), 1, f);
+ fclose(f);
+ }
+ */
+
+ if (!active_brushes.next)
+ return; // not valid yet
+
+ if (m_Camera.timing)
+ start = Sys_DoubleTime ();
+
+ //
+ // clear
+ //
+ QE_CheckOpenGLForErrors();
+
+ qglViewport(0, 0, m_Camera.width, m_Camera.height);
+ qglScissor(0, 0, m_Camera.width, m_Camera.height);
+ qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][0],
+ g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][1],
+ g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][2], 0);
+ qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ //
+ // set up viewpoint
+ //
+ vec5_t lightPos;
+
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglEnable(GL_LIGHTING);
+ //qglEnable(GL_LIGHT0);
+
+ lightPos[0] = lightPos[1] = lightPos[2] = 3.5;
+ lightPos[3] = 1.0;
+ qglLightModelfv(GL_LIGHT_MODEL_AMBIENT, lightPos);
+ //qglLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
+ //lightPos[0] = lightPos[1] = lightPos[2] = 3.5;
+ //qglLightfv(GL_LIGHT0, GL_AMBIENT, lightPos);
+ }
+ else
+ {
+ qglDisable(GL_LIGHTING);
+ }
+
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadIdentity ();
+
+ screenaspect = (float)m_Camera.width / m_Camera.height;
+ yfov = 2*atan((float)m_Camera.height / m_Camera.width)*180/Q_PI;
+ qgluPerspective (yfov, screenaspect, 2, 8192);
+
+ qglRotatef (-90, 1, 0, 0); // put Z going up
+ qglRotatef (90, 0, 0, 1); // put Z going up
+ qglRotatef (m_Camera.angles[0], 0, 1, 0);
+ qglRotatef (-m_Camera.angles[1], 0, 0, 1);
+ qglTranslatef (-m_Camera.origin[0], -m_Camera.origin[1], -m_Camera.origin[2]);
+
+ Cam_BuildMatrix ();
+
+
+ //if (m_Camera.draw_mode == cd_light)
+ //{
+// if (g_PrefsDlg.m_bGLLighting)
+// {
+// VectorCopy(m_Camera.origin, lightPos);
+// lightPos[3] = 1;
+// qglLightfv(GL_LIGHT0, GL_POSITION, lightPos);
+// }
+ //}
+
+ InitCull ();
+
+ //
+ // draw stuff
+ //
+ GLfloat lAmbient[] = {1.0, 1.0, 1.0, 1.0};
+
+ switch (m_Camera.draw_mode)
+ {
+ case cd_wire:
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglDisable(GL_BLEND);
+ qglDisable(GL_DEPTH_TEST);
+ qglColor3f(1.0, 1.0, 1.0);
+ // qglEnable (GL_LINE_SMOOTH);
+ break;
+
+ case cd_solid:
+ qglCullFace(GL_FRONT);
+ qglEnable(GL_CULL_FACE);
+ qglShadeModel (GL_FLAT);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_BLEND);
+ qglEnable(GL_DEPTH_TEST);
+ qglDepthFunc (GL_LEQUAL);
+ break;
+
+ case cd_texture:
+ qglCullFace(GL_FRONT);
+ qglEnable(GL_CULL_FACE);
+ qglShadeModel (GL_FLAT);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglEnable(GL_TEXTURE_2D);
+ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ qglDisable(GL_BLEND);
+ qglEnable(GL_DEPTH_TEST);
+ qglDepthFunc (GL_LEQUAL);
+ break;
+
+ case cd_blend:
+ qglCullFace(GL_FRONT);
+ qglEnable(GL_CULL_FACE);
+ qglShadeModel (GL_FLAT);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglEnable(GL_TEXTURE_2D);
+ qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ qglDisable(GL_DEPTH_TEST);
+ qglEnable (GL_BLEND);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ }
+
+ qglMatrixMode(GL_TEXTURE);
+
+ m_nNumTransBrushes = 0;
+
+ for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
+ {
+ //DrawLightRadius(brush);
+
+ if (CullBrush (brush))
+ continue;
+
+ if (FilterBrush (brush))
+ continue;
+
+ if ((brush->brush_faces->texdef.flags & (SURF_TRANS33 | SURF_TRANS66)) || (brush->brush_faces->d_texture->bFromShader && brush->brush_faces->d_texture->fTrans != 1.0))
+ {
+ m_TransBrushes [ m_nNumTransBrushes++ ] = brush;
+ }
+ else
+ {
+ //-- if (brush->patchBrush)
+ //-- m_TransBrushes [ m_nNumTransBrushes++ ] = brush;
+ //-- else
+ Brush_Draw(brush);
+ }
+
+
+ }
+
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglDisable (GL_LIGHTING);
+ }
+
+ //
+ //qglDepthMask ( 0 ); // Don't write to depth buffer
+ qglEnable ( GL_BLEND );
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ for ( i = 0; i < m_nNumTransBrushes; i++ )
+ Brush_Draw (m_TransBrushes[i]);
+
+ //qglDepthMask ( 1 ); // Ok, write now
+
+ qglMatrixMode(GL_PROJECTION);
+
+ //
+ // now draw selected brushes
+ //
+
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglEnable (GL_LIGHTING);
+ }
+
+ qglTranslatef (g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);
+ qglMatrixMode(GL_TEXTURE);
+
+ brush_t* pList = (g_bClipMode && g_pSplitList) ? g_pSplitList : &selected_brushes;
+ // draw normally
+ for (brush = pList->next ; brush != pList ; brush=brush->next)
+ {
+ //DrawLightRadius(brush);
+ //if (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint)
+ // continue;
+
+ Brush_Draw(brush);
+ }
+
+ // blend on top
+ qglMatrixMode(GL_PROJECTION);
+
+
+ qglDisable (GL_LIGHTING);
+ qglColor4f(1.0, 0.0, 0.0, 0.3);
+ qglEnable (GL_BLEND);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglDisable (GL_TEXTURE_2D);
+ for (brush = pList->next ; brush != pList ; brush=brush->next)
+ {
+ if ( (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint) ||
+ (brush->terrainBrush && g_qeglobals.d_select_mode == sel_terrainpoint) )
+ continue;
+
+ for (face=brush->brush_faces ; face ; face=face->next)
+ Face_Draw( face );
+ }
+
+
+ int nCount = g_ptrSelectedFaces.GetSize();
+ if (nCount > 0)
+ {
+ for (int i = 0; i < nCount; i++)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
+ Face_Draw(selFace);
+ }
+ }
+
+ // non-zbuffered outline
+
+ qglDisable (GL_BLEND);
+ qglDisable (GL_DEPTH_TEST);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ qglColor3f (1, 1, 1);
+ for (brush = pList->next ; brush != pList ; brush=brush->next)
+ {
+ if (g_qeglobals.dontDrawSelectedOutlines || (brush->patchBrush && g_qeglobals.d_select_mode == sel_curvepoint) ||
+ (brush->terrainBrush && g_qeglobals.d_select_mode == sel_terrainpoint))
+ continue;
+
+ for (face=brush->brush_faces ; face ; face=face->next)
+ Face_Draw( face );
+ }
+
+
+ // edge / vertex flags
+
+ if (g_qeglobals.d_select_mode == sel_vertex)
+ {
+ qglPointSize (4);
+ qglColor3f (0,1,0);
+ qglBegin (GL_POINTS);
+ for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
+ qglVertex3fv (g_qeglobals.d_points[i]);
+ qglEnd ();
+ qglPointSize (1);
+ }
+ else if (g_qeglobals.d_select_mode == sel_edge)
+ {
+ float *v1, *v2;
+
+ qglPointSize (4);
+ qglColor3f (0,0,1);
+ qglBegin (GL_POINTS);
+ for (i=0 ; i<g_qeglobals.d_numedges ; i++)
+ {
+ v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
+ v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
+ qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
+ }
+ qglEnd ();
+ qglPointSize (1);
+ }
+
+
+ g_splineList->draw(static_cast<qboolean>(g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint));
+ if (g_qeglobals.selectObject && (g_qeglobals.d_select_mode == sel_addpoint || g_qeglobals.d_select_mode == sel_editpoint)) {
+ g_qeglobals.selectObject->drawSelection();
+ }
+
+ //
+ // draw pointfile
+ //
+
+ qglEnable(GL_DEPTH_TEST);
+
+
+ DrawPathLines ();
+
+
+
+ if (g_qeglobals.d_pointfile_display_list)
+ {
+ Pointfile_Draw();
+ // glCallList (g_qeglobals.d_pointfile_display_list);
+ }
+
+ // bind back to the default texture so that we don't have problems
+ // elsewhere using/modifying texture maps between contexts
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+
+#if 0
+ // area selection hack
+ if (g_qeglobals.d_select_mode == sel_area)
+ {
+ qglEnable (GL_BLEND);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglColor4f(0.0, 0.0, 1.0, 0.25);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglRectfv(g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR);
+ qglDisable (GL_BLEND);
+ }
+#endif
+
+ qglFinish();
+ QE_CheckOpenGLForErrors();
+ // Sys_EndWait();
+ if (m_Camera.timing)
+ {
+ end = Sys_DoubleTime ();
+ Sys_Printf ("Camera: %i ms\n", (int)(1000*(end-start)));
+ }
+}
+
+
+void CCamWnd::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+ CRect rect;
+ GetClientRect(rect);
+ m_Camera.width = rect.right;
+ m_Camera.height = rect.bottom;
+ InvalidateRect(NULL, false);
+}
+
+void CCamWnd::BenchMark()
+{
+ PAINTSTRUCT ps;
+ CRect rct;
+ GetWindowRect(rct);
+ long lStyle = ::GetWindowLong(GetSafeHwnd(), GWL_STYLE);
+ ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, QE3_CHILDSTYLE);
+ CWnd* pParent = GetParent();
+ SetParent(g_pParentWnd);
+ MoveWindow(CRect(30, 30, 400, 400), TRUE);
+
+ BeginPaint(&ps);
+ if (!qwglMakeCurrent(ps.hdc, g_qeglobals.d_hglrcBase))
+ Error ("wglMakeCurrent failed in Benchmark");
+
+ qglDrawBuffer (GL_FRONT);
+ double dStart = Sys_DoubleTime ();
+ for (int i=0 ; i < 100 ; i++)
+ {
+ m_Camera.angles[YAW] = i*4;
+ Cam_Draw();
+ }
+ qwglSwapBuffers(ps.hdc);
+ qglDrawBuffer (GL_BACK);
+ double dEnd = Sys_DoubleTime ();
+ EndPaint(&ps);
+ Sys_Printf ("%5.2f seconds\n", dEnd - dStart);
+ ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, lStyle);
+ SetParent(pParent);
+ MoveWindow(rct, TRUE);
+}
+
+void CCamWnd::ReInitGL()
+{
+
+ qwglMakeCurrent(0,0);
+ QEW_SetupPixelFormat(GetDC()->m_hDC, true);
+ if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ Error ("wglMakeCurrent failed");
+
+ return;
+
+ long lStyle = ::GetWindowLong(GetSafeHwnd(), GWL_STYLE);
+ int nID = ::GetWindowLong(GetSafeHwnd(), GWL_ID);
+ CWnd* pParent = GetParent();
+ CRect rctClient;
+ GetClientRect(rctClient);
+ DestroyWindow();
+ Create(CAMERA_WINDOW_CLASS, "", lStyle, rctClient, pParent, nID);
+}
+
+void CCamWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
+}
+
+// Timo
+// brush primitive texture shifting, using camera view to select translations :
+void CCamWnd::ShiftTexture_BrushPrimit(face_t *f, int x, int y)
+{
+ vec3_t texS,texT;
+ vec3_t viewX,viewY;
+ int XS,XT,YS,YT;
+ int outS,outT;
+#ifdef _DEBUG
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ Sys_Printf("Warning : unexpected call to CCamWnd::ShiftTexture_BrushPrimit with brush primitive mode disbaled\n");
+ return;
+ }
+#endif
+ // compute face axis base
+ ComputeAxisBase( f->plane.normal, texS, texT );
+ // compute camera view vectors
+ VectorCopy( m_Camera.vup, viewY );
+ VectorCopy( m_Camera.vright, viewX );
+ // compute best vectors
+ ComputeBest2DVector( viewX, texS, texT, XS, XT );
+ ComputeBest2DVector( viewY, texS, texT, YS, YT );
+ // check this is not a degenerate case
+ if ( ( XS == YS ) && ( XT == YT ) )
+ {
+#ifdef _DEBUG
+ Sys_Printf("Warning : degenerate best vectors axis base in CCamWnd::ShiftTexture_BrushPrimit\n");
+#endif
+ // forget it
+ Select_ShiftTexture_BrushPrimit( f, x, y );
+ return;
+ }
+ // compute best fitted translation in face axis base
+ outS = XS*x + YS*y;
+ outT = XT*x + YT*y;
+ // call actual texture shifting code
+ Select_ShiftTexture_BrushPrimit( f, outS, outT );
+}
diff --git a/q3radiant/CamWnd.h b/q3radiant/CamWnd.h
new file mode 100755
index 0000000..8f0a283
--- /dev/null
+++ b/q3radiant/CamWnd.h
@@ -0,0 +1,120 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_CAMWND_H__44B4BA03_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
+#define AFX_CAMWND_H__44B4BA03_781B_11D1_B53C_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// CamWnd.h : header file
+//
+/////////////////////////////////////////////////////////////////////////////
+// CCamWnd window
+class CXYWnd;
+
+class CCamWnd : public CWnd
+{
+ DECLARE_DYNCREATE(CCamWnd);
+// Construction
+public:
+ CCamWnd();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCamWnd)
+ protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ void ShiftTexture_BrushPrimit(face_t *f, int x, int y);
+ void ReInitGL();
+ void BenchMark();
+ CXYWnd* m_pXYFriend;
+ void SetXYFriend(CXYWnd* pWnd);
+ virtual ~CCamWnd();
+ camera_t& Camera(){return m_Camera;};
+ void Cam_MouseControl(float dtime);
+ void Cam_ChangeFloor(qboolean up);
+
+protected:
+ void Cam_Init();
+ void Cam_BuildMatrix();
+ void Cam_PositionDrag();
+ void Cam_MouseDown(int x, int y, int buttons);
+ void Cam_MouseUp (int x, int y, int buttons);
+ void Cam_MouseMoved (int x, int y, int buttons);
+ void InitCull();
+ qboolean CullBrush (brush_t *b);
+ void Cam_Draw();
+
+
+ brush_t* m_TransBrushes[MAX_MAP_BRUSHES];
+ int m_nNumTransBrushes;
+ camera_t m_Camera;
+ int m_nCambuttonstate;
+ CPoint m_ptButton;
+ CPoint m_ptCursor;
+ CPoint m_ptLastCursor;
+ face_t* m_pSide_select;
+ vec3_t m_vCull1;
+ vec3_t m_vCull2;
+ int m_nCullv1[3];
+ int m_nCullv2[3];
+ bool m_bClipMode;
+
+ // Generated message map functions
+protected:
+ void OriginalMouseDown(UINT nFlags, CPoint point);
+ void OriginalMouseUp(UINT nFlags, CPoint point);
+ //{{AFX_MSG(CCamWnd)
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnPaint();
+ afx_msg void OnDestroy();
+ afx_msg void OnClose();
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnMButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CAMWND_H__44B4BA03_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/CapDialog.cpp b/q3radiant/CapDialog.cpp
new file mode 100755
index 0000000..c4194c7
--- /dev/null
+++ b/q3radiant/CapDialog.cpp
@@ -0,0 +1,64 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// CapDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "CapDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CCapDialog dialog
+
+
+CCapDialog::CCapDialog(CWnd* pParent /*=NULL*/)
+ : CDialog(CCapDialog::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CCapDialog)
+ m_nCap = 0;
+ //}}AFX_DATA_INIT
+}
+
+
+void CCapDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CCapDialog)
+ DDX_Radio(pDX, IDC_RADIO_CAP, m_nCap);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CCapDialog, CDialog)
+ //{{AFX_MSG_MAP(CCapDialog)
+ // NOTE: the ClassWizard will add message map macros here
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCapDialog message handlers
diff --git a/q3radiant/CapDialog.h b/q3radiant/CapDialog.h
new file mode 100755
index 0000000..df81dcb
--- /dev/null
+++ b/q3radiant/CapDialog.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_CAPDIALOG_H__10637162_2BD2_11D2_B030_00AA00A410FC__INCLUDED_)
+#define AFX_CAPDIALOG_H__10637162_2BD2_11D2_B030_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// CapDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CCapDialog dialog
+
+class CCapDialog : public CDialog
+{
+// Construction
+public:
+ static enum {BEVEL = 0, ENDCAP, IBEVEL, IENDCAP};
+ CCapDialog(CWnd* pParent = NULL); // standard constructor
+
+ int getCapType() {return m_nCap;};
+// Dialog Data
+ //{{AFX_DATA(CCapDialog)
+ enum { IDD = IDD_DIALOG_CAP };
+ int m_nCap;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCapDialog)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CCapDialog)
+ // NOTE: the ClassWizard will add member functions here
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CAPDIALOG_H__10637162_2BD2_11D2_B030_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/CharBuffer.h b/q3radiant/CharBuffer.h
new file mode 100755
index 0000000..ab86627
--- /dev/null
+++ b/q3radiant/CharBuffer.h
@@ -0,0 +1,109 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __CHARBUFFER_HPP
+#define __CHARBUFFER_HPP
+
+class CCharBuffer
+{
+ char* m_pCharBuffer;
+ unsigned m_uSize;
+
+ public:
+ CCharBuffer();
+
+ CCharBuffer(unsigned uSize);
+
+ CCharBuffer(const char* pString);
+
+ CCharBuffer(const CCharBuffer& rhs);
+
+ ~CCharBuffer();
+
+ char* Allocate(uint uSize);
+
+ void DeAllocate();
+
+ size_t StringLength()
+ { return strlen(m_pCharBuffer); }
+
+ void StripTrailing(char c, int nLen);
+
+ char& operator *()
+ { return *m_pCharBuffer; }
+
+ char& operator *() const
+ { return *const_cast<CCharBuffer*>(this)->m_pCharBuffer; }
+
+ operator void*()
+ { return m_pCharBuffer; }
+
+ operator char*()
+ { return m_pCharBuffer; }
+
+ operator const char*()
+ { return reinterpret_cast<const char*>(m_pCharBuffer); }
+
+ operator unsigned char*()
+ { return reinterpret_cast<unsigned char*>(m_pCharBuffer); }
+
+ operator const unsigned char*()
+ { return reinterpret_cast<const unsigned char*>(m_pCharBuffer); }
+
+ unsigned SizeOf()
+ { return m_uSize; }
+
+ CCharBuffer& operator =(const CCharBuffer& rhs);
+
+ CCharBuffer& operator =(const char* pString);
+
+ bool operator ==(const CCharBuffer& rhs) const
+ { return strcmp(m_pCharBuffer, rhs.m_pCharBuffer) == 0; }
+
+ bool operator ==(char* pString) const
+ { return strcmp(m_pCharBuffer, pString) == 0; }
+
+ bool operator ==(const char* pString) const
+ { return strcmp(m_pCharBuffer, pString) == 0; }
+
+ bool operator !=(CCharBuffer& rhs) const
+ { return strcmp(m_pCharBuffer, rhs.m_pCharBuffer) != 0; }
+
+ bool operator !=(char* pString) const
+ { return strcmp(m_pCharBuffer, pString) != 0; }
+
+ bool operator !=(const char* pString) const
+ { return strcmp(m_pCharBuffer, pString) != 0; }
+
+ char& operator [](int nIndex)
+ { return m_pCharBuffer[nIndex]; }
+
+ char& operator [](int nIndex) const
+ { return m_pCharBuffer[nIndex]; }
+
+ char* Fill(char FillChar)
+ { memset(m_pCharBuffer, FillChar, m_uSize-1); return m_pCharBuffer; }
+};
+//
+//-----------------------------------------------------------------------------
+#endif // __CCHARBUFFER_HPP
+//-----------------------------------------------------------------------------
+//
diff --git a/q3radiant/ChildFrm.cpp b/q3radiant/ChildFrm.cpp
new file mode 100755
index 0000000..b2e477f
--- /dev/null
+++ b/q3radiant/ChildFrm.cpp
@@ -0,0 +1,86 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ChildFrm.cpp : implementation of the CChildFrame class
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+
+#include "ChildFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame
+
+IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd)
+
+BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd)
+ //{{AFX_MSG_MAP(CChildFrame)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame construction/destruction
+
+CChildFrame::CChildFrame()
+{
+ // TODO: add member initialization code here
+
+}
+
+CChildFrame::~CChildFrame()
+{
+}
+
+BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+ // TODO: Modify the Window class or styles here by modifying
+ // the CREATESTRUCT cs
+
+ return CMDIChildWnd::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame diagnostics
+
+#ifdef _DEBUG
+void CChildFrame::AssertValid() const
+{
+ CMDIChildWnd::AssertValid();
+}
+
+void CChildFrame::Dump(CDumpContext& dc) const
+{
+ CMDIChildWnd::Dump(dc);
+}
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CChildFrame message handlers
diff --git a/q3radiant/ChildFrm.h b/q3radiant/ChildFrm.h
new file mode 100755
index 0000000..1de2584
--- /dev/null
+++ b/q3radiant/ChildFrm.h
@@ -0,0 +1,73 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ChildFrm.h : interface of the CChildFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_CHILDFRM_H__330BBF0C_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+#define AFX_CHILDFRM_H__330BBF0C_731C_11D1_B539_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CChildFrame : public CMDIChildWnd
+{
+ DECLARE_DYNCREATE(CChildFrame)
+public:
+ CChildFrame();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CChildFrame)
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CChildFrame();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CChildFrame)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CHILDFRM_H__330BBF0C_731C_11D1_B539_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/CommandsDlg.cpp b/q3radiant/CommandsDlg.cpp
new file mode 100755
index 0000000..761ea43
--- /dev/null
+++ b/q3radiant/CommandsDlg.cpp
@@ -0,0 +1,109 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// CommandsDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "CommandsDlg.h"
+#include "MainFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CCommandsDlg dialog
+
+
+CCommandsDlg::CCommandsDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CCommandsDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CCommandsDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CCommandsDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CCommandsDlg)
+ DDX_Control(pDX, IDC_LIST_COMMANDS, m_lstCommands);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CCommandsDlg, CDialog)
+ //{{AFX_MSG_MAP(CCommandsDlg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCommandsDlg message handlers
+
+BOOL CCommandsDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ m_lstCommands.SetTabStops(96);
+ int nCount = g_nCommandCount;
+
+ CFile fileout;
+ fileout.Open("c:/commandlist.txt", CFile::modeCreate | CFile::modeWrite);
+ for (int n = 0; n < nCount; n++)
+ {
+ CString strLine;
+ char c = g_Commands[n].m_nKey;
+ CString strKeys = c;
+ for (int k = 0; k < g_nKeyCount; k++)
+ {
+ if (g_Keys[k].m_nVKKey == g_Commands[n].m_nKey)
+ {
+ strKeys = g_Keys[k].m_strName;
+ break;
+ }
+ }
+ CString strMod("");
+ if (g_Commands[n].m_nModifiers & RAD_SHIFT)
+ strMod = "Shift";
+ if (g_Commands[n].m_nModifiers & RAD_ALT)
+ strMod += (strMod.GetLength() > 0) ? " + Alt" : "Alt";
+ if (g_Commands[n].m_nModifiers & RAD_CONTROL)
+ strMod += (strMod.GetLength() > 0) ? " + Control" : "Control";
+ if (strMod.GetLength() > 0)
+ {
+ strMod += " + ";
+ }
+ strLine.Format("%s \t%s%s", g_Commands[n].m_strCommand, strMod, strKeys);
+ m_lstCommands.AddString(strLine);
+
+ strLine.Format("%s \t\t\t%s%s", g_Commands[n].m_strCommand, strMod, strKeys);
+
+ fileout.Write(strLine, strLine.GetLength());
+ fileout.Write("\r\n", 2);
+ }
+ fileout.Close();
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/CommandsDlg.h b/q3radiant/CommandsDlg.h
new file mode 100755
index 0000000..7347e84
--- /dev/null
+++ b/q3radiant/CommandsDlg.h
@@ -0,0 +1,67 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_COMMANDSDLG_H__C80F6E42_8531_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_COMMANDSDLG_H__C80F6E42_8531_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// CommandsDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CCommandsDlg dialog
+
+class CCommandsDlg : public CDialog
+{
+// Construction
+public:
+ CCommandsDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CCommandsDlg)
+ enum { IDD = IDD_DLG_COMMANDLIST };
+ CListBox m_lstCommands;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCommandsDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CCommandsDlg)
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_COMMANDSDLG_H__C80F6E42_8531_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/DRAG.CPP b/q3radiant/DRAG.CPP
new file mode 100755
index 0000000..d6a0928
--- /dev/null
+++ b/q3radiant/DRAG.CPP
@@ -0,0 +1,828 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+
+/*
+
+ drag either multiple brushes, or select plane points from
+ a single brush.
+
+*/
+
+qboolean drag_ok;
+vec3_t drag_xvec;
+vec3_t drag_yvec;
+
+static int buttonstate;
+int pressx, pressy;
+static vec3_t pressdelta;
+static vec3_t vPressStart;
+static int buttonx, buttony;
+
+
+//int num_move_points;
+//float *move_points[1024];
+
+int lastx, lasty;
+
+qboolean drag_first;
+
+
+void AxializeVector (vec3_t v)
+{
+ vec3_t a;
+ float o;
+ int i;
+
+ if (!v[0] && !v[1])
+ return;
+ if (!v[1] && !v[2])
+ return;
+ if (!v[0] && !v[2])
+ return;
+
+ for (i=0 ; i<3 ; i++)
+ a[i] = fabs(v[i]);
+ if (a[0] > a[1] && a[0] > a[2])
+ i = 0;
+ else if (a[1] > a[0] && a[1] > a[2])
+ i = 1;
+ else
+ i = 2;
+
+ o = v[i];
+ VectorCopy (vec3_origin, v);
+ if (o<0)
+ v[i] = -1;
+ else
+ v[i] = 1;
+
+}
+
+
+/*
+===========
+Drag_Setup
+===========
+*/
+void Drag_Setup (int x, int y, int buttons,
+ vec3_t xaxis, vec3_t yaxis,
+ vec3_t origin, vec3_t dir)
+{
+ trace_t t;
+ face_t *f;
+
+ drag_first = true;
+
+ VectorCopy (vec3_origin, pressdelta);
+ pressx = x;
+ pressy = y;
+
+ VectorCopy (xaxis, drag_xvec);
+ AxializeVector (drag_xvec);
+ VectorCopy (yaxis, drag_yvec);
+ AxializeVector (drag_yvec);
+
+ if (g_qeglobals.d_select_mode == sel_addpoint) {
+ if (g_qeglobals.selectObject) {
+ g_qeglobals.selectObject->addPoint(origin[0], origin[1], origin[2]);
+ } else {
+ clearSelection();
+ }
+ return;
+ }
+
+ if (g_qeglobals.d_select_mode == sel_editpoint) {
+
+ if (g_qeglobals.selectObject) {
+ if (g_qeglobals.selectObject->selectPointByRay(origin[0], origin[1], origin[2], dir[0], dir[1], dir[2], !(buttons == MK_SHIFT)) >= 0) {
+ drag_ok = true;
+ }
+ return;
+ } else {
+ clearSelection();
+ }
+ Sys_UpdateWindows(W_ALL);
+ Undo_Start("drag object point");
+
+ return;
+ }
+
+
+ extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons);
+ if (g_qeglobals.d_select_mode == sel_curvepoint)
+ {
+ //if ((buttons == MK_LBUTTON))
+ // g_qeglobals.d_num_move_points = 0;
+
+ SelectCurvePointByRay (origin, dir, buttons);
+
+ if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area)
+ {
+ drag_ok = true;
+ }
+
+ Sys_UpdateWindows(W_ALL);
+
+ Undo_Start("drag curve point");
+ Undo_AddBrushList(&selected_brushes);
+
+ return;
+ }
+ else if (g_qeglobals.d_select_mode == sel_terrainpoint)
+ {
+ Terrain_SelectPointByRay( origin, dir, buttons );
+
+ if (g_qeglobals.d_numterrapoints || g_qeglobals.d_select_mode == sel_area)
+ {
+ drag_ok = true;
+ }
+
+ Sys_UpdateWindows(W_ALL);
+
+ Undo_Start("drag terrain point");
+ Undo_AddBrushList(&selected_brushes);
+ return;
+ }
+ else if (g_qeglobals.d_select_mode == sel_terraintexture)
+ {
+ Terrain_SelectPointByRay( origin, dir, buttons );
+
+ if (g_qeglobals.d_numterrapoints || g_qeglobals.d_select_mode == sel_area)
+ {
+ drag_ok = true;
+ }
+
+ Sys_UpdateWindows(W_ALL);
+
+ Undo_Start("drag terrain point");
+ Undo_AddBrushList(&selected_brushes);
+ return;
+ }
+ else
+ {
+ g_qeglobals.d_num_move_points = 0;
+ }
+
+ if (selected_brushes.next == &selected_brushes)
+ {
+ //in this case a new brush is created when the dragging
+ //takes place in the XYWnd, An useless undo is created
+ //when the dragging takes place in the CamWnd
+ Undo_Start("create brush");
+
+ Sys_Status("No selection to drag\n", 0);
+ return;
+ }
+
+
+ if (g_qeglobals.d_select_mode == sel_vertex)
+ {
+ SelectVertexByRay (origin, dir);
+ if (g_qeglobals.d_num_move_points)
+ {
+ drag_ok = true;
+ Undo_Start("drag vertex");
+ Undo_AddBrushList(&selected_brushes);
+ return;
+ }
+ }
+
+ if (g_qeglobals.d_select_mode == sel_edge)
+ {
+ SelectEdgeByRay (origin, dir);
+ if (g_qeglobals.d_num_move_points)
+ {
+ drag_ok = true;
+ Undo_Start("drag edge");
+ Undo_AddBrushList(&selected_brushes);
+ return;
+ }
+ }
+
+
+ //
+ // check for direct hit first
+ //
+ t = Test_Ray (origin, dir, true);
+ if (t.selected)
+ {
+ drag_ok = true;
+
+ Undo_Start("drag selection");
+ Undo_AddBrushList(&selected_brushes);
+
+ if (buttons == (MK_LBUTTON|MK_CONTROL) )
+ {
+ Sys_Printf ("Shear dragging face\n");
+ Brush_SelectFaceForDragging (t.brush, t.face, true);
+ }
+ else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )
+ {
+ Sys_Printf ("Sticky dragging brush\n");
+ for (f=t.brush->brush_faces ; f ; f=f->next)
+ Brush_SelectFaceForDragging (t.brush, f, false);
+ }
+ else
+ Sys_Printf ("Dragging entire selection\n");
+
+ return;
+ }
+
+ if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
+ return;
+
+ //
+ // check for side hit
+ //
+ // multiple brushes selected?
+ if (selected_brushes.next->next != &selected_brushes)
+ {
+ // yes, special handling
+ bool bOK = (g_PrefsDlg.m_bALTEdge) ? (static_cast<bool>(::GetAsyncKeyState(VK_MENU))) : true;
+ if (bOK)
+ {
+ for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next)
+ {
+ if (buttons & MK_CONTROL)
+ Brush_SideSelect (pBrush, origin, dir, true);
+ else
+ Brush_SideSelect (pBrush, origin, dir, false);
+ }
+ }
+ else
+ {
+ Sys_Printf ("press ALT to drag multiple edges\n");
+ return;
+ }
+ }
+ else
+ {
+ // single select.. trying to drag fixed entities handle themselves and just move
+ if (buttons & MK_CONTROL)
+ Brush_SideSelect (selected_brushes.next, origin, dir, true);
+ else
+ Brush_SideSelect (selected_brushes.next, origin, dir, false);
+ }
+
+ Sys_Printf ("Side stretch\n");
+ drag_ok = true;
+
+ Undo_Start("side stretch");
+ Undo_AddBrushList(&selected_brushes);
+}
+
+entity_t *peLink;
+
+void UpdateTarget(vec3_t origin, vec3_t dir)
+{
+ trace_t t;
+ entity_t *pe;
+ int i;
+ char sz[128];
+
+ t = Test_Ray (origin, dir, 0);
+
+ if (!t.brush)
+ return;
+
+ pe = t.brush->owner;
+
+ if (pe == NULL)
+ return;
+
+ // is this the first?
+ if (peLink != NULL)
+ {
+
+ // Get the target id from out current target
+ // if there is no id, make one
+
+ i = IntForKey(pe, "target");
+ if (i <= 0)
+ {
+ i = GetUniqueTargetId(1);
+ sprintf(sz, "%d", i);
+
+ SetKeyValue(pe, "target", sz);
+ }
+
+ // set the target # into our src
+
+ sprintf(sz, "%d", i);
+ SetKeyValue(peLink, "targetname", sz);
+
+ Sys_UpdateWindows(W_ENTITY);
+
+ }
+
+ // promote the target to the src
+
+ peLink = pe;
+
+}
+
+/*
+===========
+Drag_Begin
+//++timo test three button mouse and three button emulation here ?
+===========
+*/
+void Drag_Begin (int x, int y, int buttons,
+ vec3_t xaxis, vec3_t yaxis,
+ vec3_t origin, vec3_t dir)
+{
+ trace_t t;
+ bool altdown;
+
+ drag_ok = false;
+ VectorCopy (vec3_origin, pressdelta);
+ VectorCopy (vec3_origin, vPressStart);
+ drag_first = true;
+ peLink = NULL;
+
+ altdown = static_cast<bool>(::GetAsyncKeyState(VK_MENU));
+
+ // shift-LBUTTON = select entire brush
+ if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint &&
+ g_qeglobals.d_select_mode != sel_terrainpoint && g_qeglobals.d_select_mode != sel_terraintexture)
+ {
+ int nFlag = altdown ? SF_CYCLE : 0;
+ if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0) // extremely low chance of this happening from camera
+ Select_Ray (origin, dir, nFlag | SF_ENTITIES_FIRST); // hack for XY
+ else
+ Select_Ray (origin, dir, nFlag);
+ return;
+ }
+
+ // ctrl-alt-LBUTTON = multiple brush select without selecting whole entities
+ if (buttons == (MK_LBUTTON | MK_CONTROL) && altdown && g_qeglobals.d_select_mode != sel_curvepoint &&
+ g_qeglobals.d_select_mode != sel_terrainpoint && g_qeglobals.d_select_mode != sel_terraintexture)
+ {
+ if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0) // extremely low chance of this happening from camera
+ Select_Ray (origin, dir, SF_ENTITIES_FIRST); // hack for XY
+ else
+ Select_Ray (origin, dir, 0);
+ return;
+ }
+
+ // ctrl-shift-LBUTTON = select single face
+ if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint &&
+ g_qeglobals.d_select_mode != sel_terrainpoint && g_qeglobals.d_select_mode != sel_terraintexture)
+ {
+ Select_Deselect (!static_cast<bool>(::GetAsyncKeyState(VK_MENU)));
+ Select_Ray (origin, dir, SF_SINGLEFACE);
+ return;
+ }
+
+
+ // LBUTTON + all other modifiers = manipulate selection
+ if (buttons & MK_LBUTTON)
+ {
+ //
+ Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);
+ return;
+ }
+
+ int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+ // middle button = grab texture
+ if (buttons == nMouseButton)
+ {
+ t = Test_Ray (origin, dir, false);
+ if (t.face)
+ {
+ g_qeglobals.d_new_brush_bottom_z = t.brush->mins[2];
+ g_qeglobals.d_new_brush_top_z = t.brush->maxs[2];
+ // use a local brushprimit_texdef fitted to a default 2x2 texture
+ brushprimit_texdef_t bp_local;
+ ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL );
+ Texture_SetTexture ( &t.face->texdef, &bp_local, false, GETPLUGINTEXDEF(t.face));
+ UpdateSurfaceDialog();
+ UpdatePatchInspector();
+ }
+ else
+ Sys_Printf ("Did not select a texture\n");
+ return;
+ }
+
+ // ctrl-middle button = set entire brush to texture
+ if (buttons == (nMouseButton|MK_CONTROL) )
+ {
+ t = Test_Ray (origin, dir, false);
+ if (t.brush)
+ {
+ if (t.brush->brush_faces->texdef.name[0] == '(')
+ Sys_Printf ("Can't change an entity texture\n");
+ else
+ {
+ Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, false, static_cast<IPluginTexdef *>( g_qeglobals.d_texturewin.pTexdef ) );
+ Sys_UpdateWindows (W_ALL);
+ }
+ }
+ else
+ Sys_Printf ("Didn't hit a btrush\n");
+ return;
+ }
+
+ // ctrl-shift-middle button = set single face to texture
+ if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) )
+ {
+ t = Test_Ray (origin, dir, false);
+ if (t.brush)
+ {
+ if (t.brush->brush_faces->texdef.name[0] == '(')
+ Sys_Printf ("Can't change an entity texture\n");
+ else
+ {
+ SetFaceTexdef (t.brush, t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef);
+ Brush_Build( t.brush );
+ Sys_UpdateWindows (W_ALL);
+ }
+ }
+ else
+ Sys_Printf ("Didn't hit a btrush\n");
+ return;
+ }
+
+ if (buttons == (nMouseButton | MK_SHIFT))
+ {
+ Sys_Printf("Set brush face texture info\n");
+ t = Test_Ray (origin, dir, false);
+ if (t.brush)
+ {
+ if (t.brush->brush_faces->texdef.name[0] == '(')
+ {
+ if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT)
+ {
+ CString strBuff;
+ qtexture_t* pTex = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
+ if (pTex)
+ {
+ vec3_t vColor;
+ VectorCopy(pTex->color, vColor);
+
+ float fLargest = 0.0f;
+ for (int i = 0; i < 3; i++)
+ {
+ if (vColor[i] > fLargest)
+ fLargest = vColor[i];
+ }
+
+ if (fLargest == 0.0f)
+ {
+ vColor[0] = vColor[1] = vColor[2] = 1.0f;
+ }
+ else
+ {
+ float fScale = 1.0f / fLargest;
+ for (int i = 0; i < 3; i++)
+ {
+ vColor[i] *= fScale;
+ }
+ }
+ strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]);
+ SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer(0));
+ Sys_UpdateWindows (W_ALL);
+ }
+ }
+ else
+ {
+ Sys_Printf ("Can't select an entity brush face\n");
+ }
+ }
+ else
+ {
+ //strcpy(t.face->texdef.name,g_qeglobals.d_texturewin.texdef.name);
+ t.face->texdef.SetName(g_qeglobals.d_texturewin.texdef.name);
+ Brush_Build(t.brush);
+ Sys_UpdateWindows (W_ALL);
+ }
+ }
+ else
+ Sys_Printf ("Didn't hit a brush\n");
+ return;
+ }
+
+}
+
+
+//
+//===========
+//MoveSelection
+//===========
+//
+void MoveSelection (vec3_t move)
+{
+ int i, success;
+ brush_t *b;
+ CString strStatus;
+ vec3_t vTemp, vTemp2, end;
+
+ if (!move[0] && !move[1] && !move[2])
+ return;
+
+ move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0];
+ move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1];
+ move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2];
+
+ if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode)
+ {
+ float fDeg = -move[2];
+ float fAdj = move[2];
+ int nAxis = 0;
+ if (g_pParentWnd->ActiveXY()->GetViewType() == XY)
+ {
+ fDeg = -move[1];
+ fAdj = move[1];
+ nAxis = 2;
+ }
+ else
+ if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)
+ {
+ fDeg = move[2];
+ fAdj = move[2];
+ nAxis = 1;
+ }
+ else
+ nAxis = 0;
+
+ g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;
+ strStatus.Format("%s x:: %.1f y:: %.1f z:: %.1f", (g_bPatchBendMode) ? "Bend angle" : "Rotation", g_pParentWnd->ActiveXY()->Rotation()[0], g_pParentWnd->ActiveXY()->Rotation()[1], g_pParentWnd->ActiveXY()->Rotation()[2]);
+ g_pParentWnd->SetStatusText(2, strStatus);
+
+ if (g_bPatchBendMode)
+ {
+ Patch_SelectBendNormal();
+ Select_RotateAxis(nAxis, fDeg*2, false, true);
+ Patch_SelectBendAxis();
+ Select_RotateAxis(nAxis, fDeg, false, true);
+ }
+ else
+ {
+ Select_RotateAxis(nAxis, fDeg, false, true);
+ }
+ return;
+ }
+
+ if (g_pParentWnd->ActiveXY()->ScaleMode())
+ {
+ vec3_t v;
+ v[0] = v[1] = v[2] = 1.0;
+ if (move[1] > 0)
+ {
+ v[0] = 1.1;
+ v[1] = 1.1;
+ v[2] = 1.1;
+ }
+ else
+ if (move[1] < 0)
+ {
+ v[0] = 0.9;
+ v[1] = 0.9;
+ v[2] = 0.9;
+ }
+
+ Select_Scale((g_nScaleHow & SCALE_X) ? 1.0 : v[0],
+ (g_nScaleHow & SCALE_Y) ? 1.0 : v[1],
+ (g_nScaleHow & SCALE_Z) ? 1.0 : v[2]);
+ Sys_UpdateWindows (W_ALL);
+ return;
+ }
+
+
+ vec3_t vDistance;
+ VectorSubtract(pressdelta, vPressStart, vDistance);
+ strStatus.Format("Distance x: %.1f y: %.1f z: %.1f", vDistance[0], vDistance[1], vDistance[2]);
+ g_pParentWnd->SetStatusText(3, strStatus);
+
+ //
+ // dragging only a part of the selection
+ //
+ //point object selection
+ if (g_qeglobals.d_select_mode == sel_editpoint) {
+ if (g_qeglobals.selectObject) {
+ g_qeglobals.selectObject->updateSelection(move[0], move[1], move[2]);
+ }
+ return;
+ }
+
+
+ // this is fairly crappy way to deal with curvepoint and area selection
+ // but it touches the smallest amount of code this way
+ //
+ if (g_qeglobals.d_num_move_points || g_qeglobals.d_numterrapoints || g_qeglobals.d_select_mode == sel_area)
+ {
+ //area selection
+ if (g_qeglobals.d_select_mode == sel_area)
+ {
+ VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);
+ return;
+ }
+ //curve point selection
+ if (g_qeglobals.d_select_mode == sel_curvepoint)
+ {
+ Patch_UpdateSelected(move);
+ return;
+ }
+ //terrain point selection
+ if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) )
+ {
+ Terrain_UpdateSelected(move);
+ return;
+ }
+
+ //vertex selection
+ if (g_qeglobals.d_select_mode == sel_vertex)
+ {
+ success = true;
+ for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
+ {
+ success &= Brush_MoveVertex(b, g_qeglobals.d_move_points[0], move, end, true);
+ }
+ if (success)
+ VectorCopy(end, g_qeglobals.d_move_points[0]);
+ return;
+ }
+ //all other selection types
+ for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
+ VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
+ //VectorScale(move, .5, move);
+ //for (i=0 ; i<g_qeglobals.d_num_move_points2 ; i++)
+ // VectorAdd (g_qeglobals.d_move_points2[i], move, g_qeglobals.d_move_points2[i]);
+ for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
+ {
+ VectorCopy(b->maxs, vTemp);
+ VectorSubtract(vTemp, b->mins, vTemp);
+ Brush_Build( b );
+ for (i=0 ; i<3 ; i++)
+ if (b->mins[i] > b->maxs[i]
+ || b->maxs[i] - b->mins[i] > MAX_BRUSH_SIZE)
+ break; // dragged backwards or fucked up
+ if (i != 3)
+ break;
+ if (b->patchBrush)
+ {
+ VectorCopy(b->maxs, vTemp2);
+ VectorSubtract(vTemp2, b->mins, vTemp2);
+ VectorSubtract(vTemp2, vTemp, vTemp2);
+ //if (!Patch_DragScale(b->nPatchID, vTemp2, move))
+ if (!Patch_DragScale(b->pPatch, vTemp2, move))
+ {
+ b = NULL;
+ break;
+ }
+ }
+
+ if (b->terrainBrush)
+ {
+ VectorCopy(b->maxs, vTemp2);
+ VectorSubtract(vTemp2, b->mins, vTemp2);
+ VectorSubtract(vTemp2, vTemp, vTemp2);
+ if (!Terrain_DragScale(b->pTerrain, vTemp2, move))
+ {
+ b = NULL;
+ break;
+ }
+ }
+ }
+ // if any of the brushes were crushed out of existance
+ // calcel the entire move
+ if (b != &selected_brushes)
+ {
+ Sys_Printf ("Brush dragged backwards, move canceled\n");
+ for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
+ VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ Brush_Build( b );
+ }
+
+ }
+ else
+ {
+ // reset face originals from vertex edit mode
+ // this is dirty, but unfortunately necessary because Brush_Build
+ // can remove windings
+ for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
+ {
+ Brush_ResetFaceOriginals(b);
+ }
+ //
+ // if there are lots of brushes selected, just translate instead
+ // of rebuilding the brushes
+ //
+ if (drag_yvec[2] == 0 && selected_brushes.next->next != &selected_brushes)
+ {
+ Select_Move (move);
+ //VectorAdd (g_qeglobals.d_select_translate, move, g_qeglobals.d_select_translate);
+ }
+ else
+ {
+ Select_Move (move);
+ }
+ }
+}
+
+/*
+===========
+Drag_MouseMoved
+===========
+*/
+void Drag_MouseMoved (int x, int y, int buttons)
+{
+ vec3_t move, delta;
+ int i;
+
+ if (!buttons)
+ {
+ drag_ok = false;
+ return;
+ }
+ if (!drag_ok)
+ return;
+
+ // clear along one axis
+ if (buttons & MK_SHIFT)
+ {
+ drag_first = false;
+ if (abs(x-pressx) > abs(y-pressy))
+ y = pressy;
+ else
+ x = pressx;
+ }
+
+
+ for (i=0 ; i<3 ; i++)
+ {
+ move[i] = drag_xvec[i]*(x - pressx) + drag_yvec[i]*(y - pressy);
+ if (!g_PrefsDlg.m_bNoClamp)
+ {
+ move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
+ }
+ }
+
+ VectorSubtract (move, pressdelta, delta);
+ VectorCopy (move, pressdelta);
+
+ MoveSelection (delta);
+
+}
+
+/*
+===========
+Drag_MouseUp
+===========
+*/
+void Drag_MouseUp (int nButtons)
+{
+ Sys_Status ("drag completed.", 0);
+
+ if (g_qeglobals.d_select_mode == sel_area)
+ {
+ if ( OnlyTerrainSelected() )
+ {
+ Terrain_SelectAreaPoints();
+ g_qeglobals.d_select_mode = sel_terrainpoint;
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ {
+ Patch_SelectAreaPoints();
+ g_qeglobals.d_select_mode = sel_curvepoint;
+ Sys_UpdateWindows (W_ALL);
+ }
+ }
+
+ if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2])
+ {
+ Select_Move (g_qeglobals.d_select_translate);
+ VectorCopy (vec3_origin, g_qeglobals.d_select_translate);
+ Sys_UpdateWindows (W_CAMERA);
+ }
+
+ g_pParentWnd->SetStatusText(3, "");
+
+ //
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
diff --git a/q3radiant/DialogInfo.cpp b/q3radiant/DialogInfo.cpp
new file mode 100755
index 0000000..3015997
--- /dev/null
+++ b/q3radiant/DialogInfo.cpp
@@ -0,0 +1,94 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// DialogInfo.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "DialogInfo.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogInfo dialog
+CDialogInfo g_dlgInfo;
+
+void ShowInfoDialog(const char* pText)
+{
+ if (g_dlgInfo.GetSafeHwnd())
+ {
+ g_dlgInfo.m_wndInfo.SetWindowText(pText);
+ g_dlgInfo.ShowWindow(SW_SHOW);
+ }
+ else
+ {
+ g_dlgInfo.Create(IDD_DLG_INFORMATION);
+ g_dlgInfo.m_wndInfo.SetWindowText(pText);
+ g_dlgInfo.ShowWindow(SW_SHOW);
+ }
+ g_pParentWnd->SetFocus();
+}
+
+void HideInfoDialog()
+{
+ if (g_dlgInfo.GetSafeHwnd())
+ g_dlgInfo.ShowWindow(SW_HIDE);
+}
+
+
+CDialogInfo::CDialogInfo(CWnd* pParent /*=NULL*/)
+ : CDialog(CDialogInfo::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDialogInfo)
+ //}}AFX_DATA_INIT
+}
+
+
+void CDialogInfo::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDialogInfo)
+ DDX_Control(pDX, IDC_EDIT1, m_wndInfo);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDialogInfo, CDialog)
+ //{{AFX_MSG_MAP(CDialogInfo)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogInfo message handlers
+
+BOOL CDialogInfo::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ // TODO: Add extra initialization here
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/DialogInfo.h b/q3radiant/DialogInfo.h
new file mode 100755
index 0000000..f0faafc
--- /dev/null
+++ b/q3radiant/DialogInfo.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_DIALOGINFO_H__81DF2A33_A552_11D1_B58E_00AA00A410FC__INCLUDED_)
+#define AFX_DIALOGINFO_H__81DF2A33_A552_11D1_B58E_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// DialogInfo.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogInfo dialog
+void HideInfoDialog();
+void ShowInfoDialog(const char* pText);
+
+class CDialogInfo : public CDialog
+{
+// Construction
+public:
+ CDialogInfo(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CDialogInfo)
+ enum { IDD = IDD_DLG_INFORMATION };
+ CEdit m_wndInfo;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDialogInfo)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CDialogInfo)
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DIALOGINFO_H__81DF2A33_A552_11D1_B58E_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/DialogTextures.cpp b/q3radiant/DialogTextures.cpp
new file mode 100755
index 0000000..f91766b
--- /dev/null
+++ b/q3radiant/DialogTextures.cpp
@@ -0,0 +1,89 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// DialogTextures.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "DialogTextures.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogTextures dialog
+
+
+CDialogTextures::CDialogTextures(CWnd* pParent /*=NULL*/)
+ : CDialog(CDialogTextures::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDialogTextures)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CDialogTextures::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDialogTextures)
+ DDX_Control(pDX, IDC_LIST_TEXTURES, m_wndList);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDialogTextures, CDialog)
+ //{{AFX_MSG_MAP(CDialogTextures)
+ ON_LBN_DBLCLK(IDC_LIST_TEXTURES, OnDblclkListTextures)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogTextures message handlers
+
+void CDialogTextures::OnOK()
+{
+ m_nSelection = m_wndList.GetCurSel();
+ CDialog::OnOK();
+}
+
+void CDialogTextures::OnDblclkListTextures()
+{
+ OnOK();
+}
+
+BOOL CDialogTextures::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ CStringArray sa;
+ FillTextureMenu(&sa);
+ m_nSelection = -1;
+ for (int i = 0; i < sa.GetSize(); i ++)
+ {
+ m_wndList.AddString(sa.GetAt(i));
+ }
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/DialogTextures.h b/q3radiant/DialogTextures.h
new file mode 100755
index 0000000..368b088
--- /dev/null
+++ b/q3radiant/DialogTextures.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_DIALOGTEXTURES_H__F3F3F984_E47E_11D1_B61B_00AA00A410FC__INCLUDED_)
+#define AFX_DIALOGTEXTURES_H__F3F3F984_E47E_11D1_B61B_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// DialogTextures.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogTextures dialog
+
+class CDialogTextures : public CDialog
+{
+// Construction
+public:
+ CDialogTextures(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CDialogTextures)
+ enum { IDD = IDD_DIALOG_TEXTURELIST };
+ CListBox m_wndList;
+ //}}AFX_DATA
+ int m_nSelection;
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDialogTextures)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CDialogTextures)
+ virtual void OnOK();
+ afx_msg void OnDblclkListTextures();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DIALOGTEXTURES_H__F3F3F984_E47E_11D1_B61B_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/DialogThick.cpp b/q3radiant/DialogThick.cpp
new file mode 100755
index 0000000..8b5eb33
--- /dev/null
+++ b/q3radiant/DialogThick.cpp
@@ -0,0 +1,66 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// DialogThick.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "DialogThick.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogThick dialog
+
+
+CDialogThick::CDialogThick(CWnd* pParent /*=NULL*/)
+ : CDialog(CDialogThick::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDialogThick)
+ m_bSeams = TRUE;
+ m_nAmount = 8;
+ //}}AFX_DATA_INIT
+}
+
+
+void CDialogThick::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDialogThick)
+ DDX_Check(pDX, IDC_CHECK_SEAMS, m_bSeams);
+ DDX_Text(pDX, IDC_EDIT_AMOUNT, m_nAmount);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDialogThick, CDialog)
+ //{{AFX_MSG_MAP(CDialogThick)
+ // NOTE: the ClassWizard will add message map macros here
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogThick message handlers
diff --git a/q3radiant/DialogThick.h b/q3radiant/DialogThick.h
new file mode 100755
index 0000000..303dfe2
--- /dev/null
+++ b/q3radiant/DialogThick.h
@@ -0,0 +1,68 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_DIALOGTHICK_H__59F46602_553D_11D2_B082_00AA00A410FC__INCLUDED_)
+#define AFX_DIALOGTHICK_H__59F46602_553D_11D2_B082_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// DialogThick.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CDialogThick dialog
+
+class CDialogThick : public CDialog
+{
+// Construction
+public:
+ CDialogThick(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CDialogThick)
+ enum { IDD = IDD_DIALOG_THICKEN };
+ BOOL m_bSeams;
+ int m_nAmount;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDialogThick)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CDialogThick)
+ // NOTE: the ClassWizard will add member functions here
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DIALOGTHICK_H__59F46602_553D_11D2_B082_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/DlgEvent.cpp b/q3radiant/DlgEvent.cpp
new file mode 100755
index 0000000..2af1629
--- /dev/null
+++ b/q3radiant/DlgEvent.cpp
@@ -0,0 +1,65 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// DlgEvent.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "DlgEvent.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDlgEvent dialog
+
+
+CDlgEvent::CDlgEvent(CWnd* pParent /*=NULL*/)
+ : CDialog(CDlgEvent::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDlgEvent)
+ m_strParm = _T("");
+ m_event = 0;
+ //}}AFX_DATA_INIT
+}
+
+
+void CDlgEvent::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDlgEvent)
+ DDX_Text(pDX, IDC_EDIT_PARAM, m_strParm);
+ DDX_Radio(pDX, IDC_RADIO_EVENT, m_event);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDlgEvent, CDialog)
+ //{{AFX_MSG_MAP(CDlgEvent)
+ // NOTE: the ClassWizard will add message map macros here
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDlgEvent message handlers
diff --git a/q3radiant/DlgEvent.h b/q3radiant/DlgEvent.h
new file mode 100755
index 0000000..f99235a
--- /dev/null
+++ b/q3radiant/DlgEvent.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_DLGEVENT_H__B12EEBE1_FB71_407B_9075_50F63B168567__INCLUDED_)
+#define AFX_DLGEVENT_H__B12EEBE1_FB71_407B_9075_50F63B168567__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// DlgEvent.h : header file
+//
+
+#include "splines/splines.h"
+/////////////////////////////////////////////////////////////////////////////
+// CDlgEvent dialog
+
+class CDlgEvent : public CDialog
+{
+// Construction
+public:
+ CDlgEvent(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CDlgEvent)
+ enum { IDD = IDD_DLG_CAMERAEVENT };
+ CString m_strParm;
+ int m_event;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDlgEvent)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CDlgEvent)
+ // NOTE: the ClassWizard will add member functions here
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DLGEVENT_H__B12EEBE1_FB71_407B_9075_50F63B168567__INCLUDED_)
diff --git a/q3radiant/ECLASS.CPP b/q3radiant/ECLASS.CPP
new file mode 100755
index 0000000..0e3f46a
--- /dev/null
+++ b/q3radiant/ECLASS.CPP
@@ -0,0 +1,932 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+#include "io.h"
+#include "pakstuff.h"
+//#include "qertypes.h"
+
+eclass_t *eclass = NULL;
+eclass_t *eclass_bad = NULL;
+char eclass_directory[1024];
+
+// md3 cache for misc_models
+eclass_t *g_md3Cache = NULL;
+
+/*
+
+the classname, color triple, and bounding box are parsed out of comments
+A ? size means take the exact brush size.
+
+/*QUAKED <classname> (0 0 0) ?
+/*QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)
+
+Flag names can follow the size description:
+
+/*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY
+
+*/
+
+void CleanEntityList(eclass_t *&pList)
+{
+ while (pList)
+ {
+ eclass_t* pTemp = pList->next;
+
+ entitymodel *model = pList->model;
+ while (model != NULL)
+ {
+ delete []model->pTriList;
+ model = model->pNext;
+ }
+
+ if (pList->modelpath)
+ free(pList->modelpath);
+ if (pList->skinpath) // PGM
+ free(pList->skinpath); // PGM
+
+ free(pList->name);
+ free(pList->comments);
+ free(pList);
+ pList = pTemp;
+ }
+
+ pList = NULL;
+
+}
+
+
+void CleanUpEntities()
+{
+ CleanEntityList(eclass);
+ CleanEntityList(g_md3Cache);
+/*
+ while (eclass)
+ {
+ eclass_t* pTemp = eclass->next;
+ delete []eclass->pTriList;
+
+ if (eclass->modelpath)
+ free(eclass->modelpath);
+ if (eclass->skinpath) // PGM
+ free(eclass->skinpath); // PGM
+
+ free(eclass->name);
+ free(eclass->comments);
+ free(eclass);
+ eclass = pTemp;
+ }
+
+ eclass = NULL;
+*/
+ if (eclass_bad)
+ {
+ free(eclass_bad->name);
+ free(eclass_bad->comments);
+ free(eclass_bad);
+ eclass_bad = NULL;
+ }
+}
+
+void ExtendBounds(vec3_t v, vec3_t &vMin, vec3_t &vMax)
+{
+ for (int i = 0 ;i < 3 ;i++)
+ {
+ vec_t f = v[i];
+
+ if (f < vMin[i])
+ {
+ vMin[i] = f;
+ }
+
+ if (f > vMax[i])
+ {
+ vMax[i] = f;
+ }
+ }
+}
+
+
+
+// FIXME: this code is a TOTAL clusterfuck
+//
+void LoadModel(const char *pLocation, eclass_t *e, vec3_t &vMin, vec3_t &vMax, entitymodel *&pModel, const char *pSkin)
+{
+ // this assumes a path only and uses tris.md2
+ // for the model and skin.pcx for the skin
+ char cPath[1024];
+ char cSkin[1024];
+ char cFullLocation[1024];
+ //struct _finddata_t fileinfo;
+
+ vMin[0] = vMin[1] = vMin[2] = 99999;
+ vMax[0] = vMax[1] = vMax[2] = -99999;
+
+ bool bMD3 = false;
+ bool bASE = false;
+
+ strcpy( cFullLocation, pLocation );
+
+ if (strstr(pLocation, ".md3"))
+ {
+ bMD3 = true;
+ }
+ else if (strstr(pLocation, ".md2") != NULL)
+ {
+ sprintf( cFullLocation, "%stris.md2", pLocation);
+ }
+ else if (strstr(pLocation, ".ase") != NULL)
+ {
+ bASE = true;
+ }
+
+ sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cFullLocation);
+
+ Sys_Printf("Loading model %s...", cPath);
+ unsigned char* p = NULL;
+ bool bOpen = (LoadFile(cPath, reinterpret_cast<void**>(&p)) > 0);
+ if (!bOpen)
+ {
+ Sys_Printf(" failed. Trying PAK file...");
+// sprintf (cPath, "%stris.md2", pLocation);
+ strcpy (cPath, cFullLocation);
+ bOpen = (PakLoadAnyFile(cPath, reinterpret_cast<void**>(&p)) > 0);
+ }
+
+ if (bOpen)
+ {
+ Sys_Printf(" successful.\n");
+
+ if (bASE)
+ {
+/*
+ free(p);
+ CString strOut;
+ ::GetTempPath(1024, strOut.GetBuffer(1024));
+ strOut.ReleaseBuffer();
+ AddSlash(strOut);
+ strOut += "Temp.ase";
+ CopyFile(cPath, strOut, false);
+ CString strIn = strOut;
+ FindReplace(strOut, ".ase", ".md3");
+ strcpy(cPath, strIn);
+ strcpy(cSkin, strOut);
+ Q3Data_ProduceTempMD3(ValueForKey(g_qeglobals.d_project_entity, "basepath"), cPath, cSkin);
+ CString strModel = cPath;
+ if (LoadFile(strOut.GetBuffer(0), reinterpret_cast<void**>(&p)) == 0)
+ {
+ Sys_Printf(" Conversion from ASE failed.\n");
+ return;
+ }
+ bMD3 = true;
+*/
+ }
+
+ if (bMD3)
+ {
+ md3Header_t header;
+ md3Surface_t *pSurface;
+ header = *(md3Header_t *)p;
+ if (pSkin != NULL)
+ {
+ strcpy(cSkin, pSkin);
+ }
+ else
+ {
+ cSkin[0] = '\0';
+ }
+ int n = header.numFrames;
+ pSurface = (md3Surface_t *) (p + header.ofsSurfaces);
+ for (int z = 0; z < header.numSurfaces; z++ )
+ {
+ int nTris = pSurface->numTriangles;
+
+ //unsigned char* pTris = reinterpret_cast<unsigned char*>(pSurface);
+ //pTris += pSurface->ofsTriangles;
+
+ if (nTris > 0)
+ {
+ int nStart = 0;
+ if (pModel->pTriList == NULL)
+ {
+ pModel->nModelPosition = 0;
+ pModel->pTriList = new trimodel[nTris];
+ pModel->nTriCount = nTris;
+ }
+ else
+ {
+ // already have one so we need to reallocate
+ int nNewCount = pModel->nTriCount + nTris;
+ trimodel* pNewModels = new trimodel[nNewCount];
+ for (int i = 0; i < pModel->nTriCount; i++)
+ {
+ memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
+ }
+ nStart = pModel->nTriCount;
+ pModel->nTriCount = nNewCount;
+ //nTris = nNewCount;
+ delete [] pModel->pTriList;
+ pModel->pTriList = pNewModels;
+ }
+
+ md3Triangle_t *pTris = reinterpret_cast<md3Triangle_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsTriangles));
+ md3XyzNormal_t *pXyz = reinterpret_cast<md3XyzNormal_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsXyzNormals));
+ if (e->nFrame < pSurface->numFrames)
+ {
+ pXyz += (e->nFrame * pSurface->numVerts);
+ }
+
+ md3St_t *pST = reinterpret_cast<md3St_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsSt));
+
+ for (int i = 0; i < nTris; i++)
+ {
+ for (int k = 0; k < 3; k ++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ //e->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
+ pModel->pTriList[nStart].v[k][j] = pXyz[pTris[i].indexes[k]].xyz[j] * MD3_XYZ_SCALE;
+ }
+ pModel->pTriList[nStart].st[k][0] = pST[pTris[i].indexes[k]].st[0];
+ pModel->pTriList[nStart].st[k][1] = pST[pTris[i].indexes[k]].st[1];
+ ExtendBounds (pModel->pTriList[nStart].v[k], vMin, vMax);
+ }
+ nStart++;
+ }
+
+ }
+
+ md3Shader_t *pShader = reinterpret_cast<md3Shader_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsShaders));
+ sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pShader->name);
+ strlwr(cPath);
+ pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
+ if (pModel->nTextureBind == -1)
+ {
+ Sys_Printf("Model skin load failed on texture %s\n", cPath);
+ }
+ pSurface = (md3Surface_t *) ((( char * ) pSurface) + pSurface->ofsEnd);
+ pModel->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
+ pModel = pModel->pNext;
+ }
+ }
+ else
+ {
+
+ dmdl_t model;
+ daliasframe_t *f;
+ unsigned char* pTris = p;
+ dstvert_t *pST = NULL;
+ int nTris = 0;
+
+ // grab model params
+ memcpy(&model, p, sizeof(dmdl_t));
+ f = (daliasframe_t*)(p + model.ofs_frames);
+ pTris += model.ofs_tris;
+ pST = reinterpret_cast<dstvert_t*>(p + model.ofs_st);
+ nTris = model.num_tris;
+
+ if(pSkin)
+ {
+ strcpy (cSkin, pSkin);
+ if ((cSkin[strlen(cSkin)-1] == '\\') || (cSkin[strlen(cSkin)-1] == '/'))
+ strcat(cSkin, "skin.pcx\0");
+ }
+ else
+ {
+ strcpy(cSkin, (char *)(p + model.ofs_skins));
+ }
+
+ sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
+ strlwr(cPath);
+ pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
+ if (pModel->nTextureBind == -1)
+ {
+ Sys_Printf("Model skin load failed on texture %s\n", cPath);
+ }
+ int nStart = 0;
+ if (pModel->pTriList == NULL)
+ {
+ pModel->nModelPosition = 0;
+ pModel->pTriList = new trimodel[nTris];
+ pModel->nTriCount = nTris;
+ }
+ else
+ {
+ // already have one so we need to reallocate
+ int nNewCount = pModel->nTriCount + nTris;
+ trimodel* pNewModels = new trimodel[nNewCount];
+ for (int i = 0; i < pModel->nTriCount; i++)
+ {
+ memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
+ }
+ nStart = pModel->nTriCount;
+ pModel->nTriCount = nNewCount;
+ nTris = nNewCount;
+ delete [] pModel->pTriList;
+ pModel->pTriList = pNewModels;
+ }
+
+ for (int i = nStart; i < nTris; i++)
+ {
+ dtriangle_t tri;
+ memcpy(&tri, pTris, sizeof(dtriangle_t));
+ for (int k = 0; k < 3; k ++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ pModel->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
+ }
+
+ pModel->pTriList[i].st[k][0] = pST[tri.index_st[k]].s / pModel->nSkinWidth;
+ pModel->pTriList[i].st[k][1] = pST[tri.index_st[k]].t / pModel->nSkinHeight;;
+ ExtendBounds (pModel->pTriList[i].v[k], vMin, vMax);
+ }
+ pTris += sizeof(dtriangle_t);
+ }
+ }
+ free(p);
+ }
+ else
+ {
+ Sys_Printf(" failed.\n");
+ }
+
+#if 0
+ if (pModel->pTriList != NULL && pModel->nTriCount > 0 && !bMD3)
+ {
+ if(fabs(vMin[2]) < ((vMax[2]-vMin[2]) / 10.0)) // > 90% above 0 point.
+ pModel->nModelPosition = 1;
+// sprintf (cPath, "%s/%sskin.pcx", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
+ sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
+ pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
+ if (pModel->nTextureBind == -1)
+ {
+// sprintf (cPath, "%sskin.pcx", pLocation);
+ strcpy (cPath, cSkin);
+ pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
+ }
+ }
+#endif
+
+}
+
+void setSpecialLoad(eclass_t *e, const char* pWhat, char*& p)
+{
+ CString str = e->comments;
+ int n = str.Find(pWhat);
+ if (n >= 0)
+ {
+ char* pText = e->comments + n + strlen(pWhat);
+ if (*pText == '\"')
+ pText++;
+
+ str = "";
+ while (*pText != '\"' && *pText != '\0')
+ {
+ str += *pText;
+ pText++;
+ }
+ if (str.GetLength() > 0)
+ {
+ p = strdup(str);
+ //--LoadModel(str, e);
+ }
+ }
+}
+
+char *debugname;
+
+eclass_t *Eclass_InitFromText (char *text)
+{
+ char *t;
+ int len;
+ int r, i;
+ char parms[256], *p;
+ eclass_t *e;
+ char color[128];
+
+ e = (eclass_t*)qmalloc(sizeof(*e));
+ memset (e, 0, sizeof(*e));
+
+ text += strlen("/*QUAKED ");
+
+// grab the name
+ text = COM_Parse (text);
+ e->name = (char*)qmalloc (strlen(com_token)+1);
+ strcpy (e->name, com_token);
+ debugname = e->name;
+
+// grab the color, reformat as texture name
+ r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
+ if (r != 3)
+ return e;
+ sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
+ //strcpy (e->texdef.name, color);
+ e->texdef.SetName(color);
+
+ while (*text != ')')
+ {
+ if (!*text)
+ return e;
+ text++;
+ }
+ text++;
+
+// get the size
+ text = COM_Parse (text);
+ if (com_token[0] == '(')
+ { // parse the size as two vectors
+ e->fixedsize = true;
+ r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
+ &e->maxs[0], &e->maxs[1], &e->maxs[2]);
+ if (r != 6)
+ return e;
+
+ for (i=0 ; i<2 ; i++)
+ {
+ while (*text != ')')
+ {
+ if (!*text)
+ return e;
+ text++;
+ }
+ text++;
+ }
+ }
+ else
+ { // use the brushes
+ }
+
+// get the flags
+
+
+// copy to the first /n
+ p = parms;
+ while (*text && *text != '\n')
+ *p++ = *text++;
+ *p = 0;
+ text++;
+
+// any remaining words are parm flags
+ p = parms;
+ for (i=0 ; i<8 ; i++)
+ {
+ p = COM_Parse (p);
+ if (!p)
+ break;
+ strcpy (e->flagnames[i], com_token);
+ }
+
+// find the length until close comment
+ for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
+ ;
+
+// copy the comment block out
+ len = t-text;
+ e->comments = (char*)qmalloc (len+1);
+ memcpy (e->comments, text, len);
+#if 0
+ for (i=0 ; i<len ; i++)
+ if (text[i] == '\n')
+ e->comments[i] = '\r';
+ else
+ e->comments[i] = text[i];
+#endif
+ e->comments[len] = 0;
+
+ setSpecialLoad(e, "model=", e->modelpath);
+ setSpecialLoad(e, "skin=", e->skinpath);
+ char *pFrame = NULL;
+ setSpecialLoad(e, "frame=", pFrame);
+ if (pFrame != NULL)
+ {
+ e->nFrame = atoi(pFrame);
+ }
+
+ if(!e->skinpath)
+ setSpecialLoad(e, "texture=", e->skinpath);
+
+ // setup show flags
+ e->nShowFlags = 0;
+ if (strcmpi(e->name, "light") == 0)
+ {
+ e->nShowFlags |= ECLASS_LIGHT;
+ }
+
+ if ( (strnicmp(e->name, "info_player", strlen("info_player")) == 0)
+ ||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0)
+ ||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) )
+ {
+ e->nShowFlags |= ECLASS_ANGLE;
+ }
+ if (strcmpi(e->name, "path") == 0)
+ {
+ e->nShowFlags |= ECLASS_PATH;
+ }
+ if (strcmpi(e->name, "misc_model") == 0)
+ {
+ e->nShowFlags |= ECLASS_MISCMODEL;
+ }
+
+
+ return e;
+}
+
+qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax)
+{
+ if (e->modelpath != NULL)
+ {
+ if (e->model == NULL)
+ {
+ e->model = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
+ }
+ char *pModelBuff = strdup(e->modelpath);
+ char *pSkinBuff = NULL;
+ if (e->skinpath)
+ {
+ pSkinBuff = strdup(e->skinpath);
+ }
+
+ CStringList Models;
+ CStringList Skins;
+ char* pToken = strtok(pModelBuff, ";\0");
+ while (pToken != NULL)
+ {
+ Models.AddTail(pToken);
+ pToken = strtok(NULL, ";\0");
+ }
+
+ if (pSkinBuff != NULL)
+ {
+ pToken = strtok(pSkinBuff, ";\0");
+ while (pToken != NULL)
+ {
+ Skins.AddTail(pToken);
+ pToken = strtok(NULL, ";\0");
+ }
+ }
+
+ entitymodel *model = e->model;
+ for (int i = 0; i < Models.GetCount(); i++)
+ {
+ char *pSkin = NULL;
+ if (i < Skins.GetCount())
+ {
+ pSkin = Skins.GetAt(Skins.FindIndex(i)).GetBuffer(0);
+ }
+ LoadModel(Models.GetAt(Models.FindIndex(i)), e, vMin, vMax, model, pSkin);
+ model->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
+ model = model->pNext;
+ }
+
+ // at this poitn vMin and vMax contain the min max of the model
+ // which needs to be centered at origin 0, 0, 0
+
+ VectorSnap(vMin);
+ VectorSnap(vMax);
+
+ if (vMax[0] - vMin[0] < 2)
+ {
+ vMin[0] -= 1;
+ vMax[0] += 1;
+ }
+
+ if (vMin[1] - vMax[1] < 2)
+ {
+ vMin[1] -= 1;
+ vMax[1] += 1;
+ }
+
+ if (vMax[2] - vMin[2] < 2)
+ {
+ vMax[2] -= 1;
+ vMax[2] += 1;
+ }
+
+ vec3_t vTemp;
+ VectorAdd(vMin, vMax, vTemp);
+ VectorScale(vTemp, 0.5, vTemp);
+ model = e->model;
+ while (model != NULL)
+ {
+ for (i = 0; i < model->nTriCount; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ ;//VectorSubtract(model->pTriList[i].v[j], vTemp, model->pTriList[i].v[j]);
+ }
+ }
+ model = model->pNext;
+ }
+
+ free(pModelBuff);
+ free(e->modelpath);
+ e->modelpath = NULL;
+
+ if(e->skinpath)
+ {
+ free(e->skinpath);
+ e->skinpath = NULL;
+ free(pSkinBuff);
+ }
+
+ }
+ return (e->model != NULL && e->model->nTriCount > 0);
+}
+
+
+void EClass_InsertSortedList(eclass_t *&pList, eclass_t *e)
+{
+ eclass_t *s;
+
+ if (!pList)
+ {
+ pList = e;
+ return;
+ }
+
+
+ s = pList;
+ if (stricmp (e->name, s->name) < 0)
+ {
+ e->next = s;
+ pList = e;
+ return;
+ }
+
+ do
+ {
+ if (!s->next || stricmp (e->name, s->next->name) < 0)
+ {
+ e->next = s->next;
+ s->next = e;
+ return;
+ }
+ s=s->next;
+ } while (1);
+}
+
+/*
+=================
+Eclass_InsertAlphabetized
+=================
+*/
+void Eclass_InsertAlphabetized (eclass_t *e)
+{
+#if 1
+ EClass_InsertSortedList(eclass, e);
+#else
+ eclass_t *s;
+
+ if (!eclass)
+ {
+ eclass = e;
+ return;
+ }
+
+
+ s = eclass;
+ if (stricmp (e->name, s->name) < 0)
+ {
+ e->next = s;
+ eclass = e;
+ return;
+ }
+
+ do
+ {
+ if (!s->next || stricmp (e->name, s->next->name) < 0)
+ {
+ e->next = s->next;
+ s->next = e;
+ return;
+ }
+ s=s->next;
+ } while (1);
+#endif
+}
+
+
+/*
+=================
+Eclass_ScanFile
+=================
+*/
+
+qboolean parsing_single = false;
+qboolean eclass_found;
+eclass_t *eclass_e;
+//#ifdef BUILD_LIST
+extern bool g_bBuildList;
+CString strDefFile;
+//#endif
+void Eclass_ScanFile (char *filename)
+{
+ int size;
+ char *data;
+ eclass_t *e;
+ int i;
+ char temp[1024];
+
+ QE_ConvertDOSToUnixName( temp, filename );
+
+ Sys_Printf ("ScanFile: %s\n", temp);
+
+ // BUG
+ size = LoadFile (filename, (void**)&data);
+ eclass_found = false;
+ for (i=0 ; i<size ; i++)
+ if (!strncmp(data+i, "/*QUAKED",8))
+ {
+
+ //#ifdef BUILD_LIST
+ if (g_bBuildList)
+ {
+ CString strDef = "";
+ int j = i;
+ while (1)
+ {
+ strDef += *(data+j);
+ if (*(data+j) == '/' && *(data+j-1) == '*')
+ break;
+ j++;
+ }
+ strDef += "\r\n\r\n\r\n";
+ strDefFile += strDef;
+ }
+ //#endif
+ e = Eclass_InitFromText (data+i);
+ if (e)
+ Eclass_InsertAlphabetized (e);
+ else
+ printf ("Error parsing: %s in %s\n",debugname, filename);
+
+ // single ?
+ eclass_e = e;
+ eclass_found = true;
+ if ( parsing_single )
+ break;
+ }
+
+ free (data);
+}
+
+
+
+void Eclass_InitForSourceDirectory (char *path)
+{
+ struct _finddata_t fileinfo;
+ int handle;
+ char filename[1024];
+ char filebase[1024];
+ char temp[1024];
+ char *s;
+
+ QE_ConvertDOSToUnixName( temp, path );
+
+ Sys_Printf ("Eclass_InitForSourceDirectory: %s\n", temp );
+
+ strcpy (filebase, path);
+ s = filebase + strlen(filebase)-1;
+ while (*s != '\\' && *s != '/' && s!=filebase)
+ s--;
+ *s = 0;
+
+ CleanUpEntities();
+ eclass = NULL;
+//#ifdef BUILD_LIST
+ if (g_bBuildList)
+ strDefFile = "";
+//#endif
+ handle = _findfirst (path, &fileinfo);
+ if (handle != -1)
+ {
+ do
+ {
+ sprintf (filename, "%s\\%s", filebase, fileinfo.name);
+ Eclass_ScanFile (filename);
+ } while (_findnext( handle, &fileinfo ) != -1);
+
+ _findclose (handle);
+ }
+
+//#ifdef BUILD_LIST
+ if (g_bBuildList)
+ {
+ CFile file;
+ if (file.Open("c:\\entities.def", CFile::modeCreate | CFile::modeWrite))
+ {
+ file.Write(strDefFile.GetBuffer(0), strDefFile.GetLength());
+ file.Close();
+ }
+ }
+//#endif
+
+ eclass_bad = Eclass_InitFromText ("/*QUAKED UNKNOWN_CLASS (0 0.5 0) ?");
+}
+
+eclass_t *Eclass_ForName (char *name, qboolean has_brushes)
+{
+ eclass_t *e;
+ char init[1024];
+
+#ifdef _DEBUG
+ // grouping stuff, not an eclass
+ if (strcmp(name, "group_info")==0)
+ Sys_Printf("WARNING: unexpected group_info entity in Eclass_ForName\n");
+#endif
+
+ if (!name)
+ return eclass_bad;
+
+ for (e=eclass ; e ; e=e->next)
+ if (!strcmp (name, e->name))
+ return e;
+
+ // create a new class for it
+ if (has_brushes)
+ {
+ sprintf (init, "/*QUAKED %s (0 0.5 0) ?\nNot found in source.\n", name);
+ e = Eclass_InitFromText (init);
+ }
+ else
+ {
+ sprintf (init, "/*QUAKED %s (0 0.5 0) (-8 -8 -8) (8 8 8)\nNot found in source.\n", name);
+ e = Eclass_InitFromText (init);
+ }
+
+ Eclass_InsertAlphabetized (e);
+
+ return e;
+}
+
+
+eclass_t* GetCachedModel(entity_t *pEntity, const char *pName, vec3_t &vMin, vec3_t &vMax)
+{
+
+ eclass_t *e = NULL;
+ if (pName == NULL || strlen(pName) == 0)
+ {
+ return NULL;
+ }
+
+ for (e = g_md3Cache; e ; e = e->next)
+ {
+ if (!strcmp (pName, e->name))
+ {
+ pEntity->md3Class = e;
+ VectorCopy(e->mins, vMin);
+ VectorCopy(e->maxs, vMax);
+ return e;
+ }
+ }
+
+ e = (eclass_t*)qmalloc(sizeof(*e));
+ memset (e, 0, sizeof(*e));
+ e->name = strdup(pName);
+ e->modelpath = strdup(pName);
+ e->skinpath = strdup(pName);
+ char *p = strstr(e->skinpath, ".md3");
+ if (p != NULL)
+ {
+ p++;
+ strncpy(p, "tga", 3);
+ }
+ else
+ {
+ free(e->skinpath);
+ e->skinpath = NULL;
+ }
+
+ e->color[0] = e->color[2] = 0.85;
+
+ if (Eclass_hasModel(e, vMin, vMax))
+ {
+ EClass_InsertSortedList(g_md3Cache, e);
+ VectorCopy(vMin, e->mins);
+ VectorCopy(vMax, e->maxs);
+ pEntity->md3Class = e;
+ return e;
+ }
+
+ return NULL;
+}
diff --git a/q3radiant/ENTITY.CPP b/q3radiant/ENTITY.CPP
new file mode 100755
index 0000000..d4353b5
--- /dev/null
+++ b/q3radiant/ENTITY.CPP
@@ -0,0 +1,933 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+
+//
+int g_entityId = 1;
+
+char *ValueForKey ( epair_t *&e, const char *key)
+{
+ epair_t *ep;
+ for (ep=e ; ep ; ep=ep->next)
+ {
+ if (!strcmp (ep->key, key) )
+ {
+ return ep->value;
+ }
+ }
+ return "";
+}
+
+
+char *ValueForKey (entity_t *ent, const char *key)
+{
+ return ValueForKey(ent->epairs, key);
+}
+
+void TrackMD3Angles(entity_t *e, const char *key, const char *value)
+{
+ if (strcmpi(key, "angle") != 0)
+ {
+ return;
+ }
+
+ if (e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL)
+ {
+ float a = FloatForKey (e, "angle");
+ float b = atof(value);
+ if (a != b)
+ {
+ vec3_t vAngle;
+ vAngle[0] = vAngle[1] = 0;
+ vAngle[2] = -a;
+ Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
+ vAngle[2] = b;
+ Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
+ }
+ }
+}
+
+void SetKeyValue (epair_t *&e, const char *key, const char *value)
+{
+ epair_t *ep;
+ for (ep=e ; ep ; ep=ep->next)
+ {
+ if (!strcmp (ep->key, key) )
+ {
+ free (ep->value);
+ ep->value = (char*)qmalloc(strlen(value)+1);
+ strcpy (ep->value, value);
+ return;
+ }
+ }
+ ep = (epair_t*)qmalloc (sizeof(*ep));
+ ep->next = e;
+ e = ep;
+ ep->key = (char*)qmalloc(strlen(key)+1);
+ strcpy (ep->key, key);
+ ep->value = (char*)qmalloc(strlen(value)+1);
+ strcpy (ep->value, value);
+
+}
+
+
+void SetKeyValue (entity_t *ent, const char *key, const char *value)
+{
+
+ if (ent == NULL)
+ return;
+
+ if (!key || !key[0])
+ return;
+
+ TrackMD3Angles(ent, key, value);
+
+ SetKeyValue(ent->epairs, key, value);
+
+}
+
+void DeleteKey (epair_t *&e, const char *key)
+{
+ epair_t **ep, *next;
+
+ ep = &e;
+ while (*ep)
+ {
+ next = *ep;
+ if ( !strcmp (next->key, key) )
+ {
+ *ep = next->next;
+ free(next->key);
+ free(next->value);
+ free(next);
+ return;
+ }
+ ep = &next->next;
+ }
+}
+
+
+void DeleteKey (entity_t *ent, const char *key)
+{
+ DeleteKey(ent->epairs, key);
+}
+
+
+
+
+float FloatForKey (entity_t *ent, const char *key)
+{
+ char *k;
+
+ k = ValueForKey (ent, key);
+ return atof(k);
+}
+
+int IntForKey (entity_t *ent, const char *key)
+{
+ char *k;
+
+ k = ValueForKey (ent, key);
+ return atoi(k);
+}
+
+void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
+{
+ char *k;
+
+ k = ValueForKey (ent, key);
+ sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
+}
+
+/*
+===============
+Entity_FreeEpairs
+
+Frees the entity epairs.
+===============
+*/
+void Entity_FreeEpairs(entity_t *e)
+{
+ epair_t *ep, *next;
+
+ for (ep = e->epairs; ep; ep = next)
+ {
+ next = ep->next;
+ free (ep->key);
+ free (ep->value);
+ free (ep);
+ }
+ e->epairs = NULL;
+}
+
+/*
+===========
+Entity_AddToList
+===========
+*/
+void Entity_AddToList(entity_t *e, entity_t *list)
+{
+ if (e->next || e->prev)
+ Error ("Entity_AddToList: allready linked");
+ e->next = list->next;
+ list->next->prev = e;
+ list->next = e;
+ e->prev = list;
+}
+
+/*
+===========
+Entity_RemoveFromList
+===========
+*/
+void Entity_RemoveFromList (entity_t *e)
+{
+ if (!e->next || !e->prev)
+ Error ("Entity_RemoveFromList: not linked");
+ e->next->prev = e->prev;
+ e->prev->next = e->next;
+ e->next = e->prev = NULL;
+}
+
+
+
+/*
+===============
+Entity_Free
+
+Frees the entity and any brushes is has.
+The entity is removed from the global entities list.
+===============
+*/
+void Entity_Free (entity_t *e)
+{
+ // do we have a plugin entity ?
+ if ( e->pPlugEnt )
+ {
+ e->pPlugEnt->DecRef();
+ e->pPlugEnt = NULL;
+ }
+
+ while (e->brushes.onext != &e->brushes)
+ Brush_Free (e->brushes.onext);
+
+ if (e->next)
+ {
+ e->next->prev = e->prev;
+ e->prev->next = e->next;
+ }
+
+ Entity_FreeEpairs(e);
+
+ free (e);
+}
+
+/*
+=================
+Entity_MemorySize
+=================
+*/
+int Entity_MemorySize(entity_t *e)
+{
+ epair_t *ep;
+ int size = 0;
+
+ for (ep = e->epairs; ep; ep = ep->next)
+ {
+ size += _msize(ep->key);
+ size += _msize(ep->value);
+ size += _msize(ep);
+ }
+ size += _msize(e);
+ return size;
+}
+
+/*
+=================
+ParseEpair
+=================
+*/
+epair_t *ParseEpair (void)
+{
+ epair_t *e;
+
+ e = (epair_t*)qmalloc (sizeof(*e));
+
+ e->key = (char*)qmalloc(strlen(token)+1);
+ strcpy (e->key, token);
+
+ GetToken (false);
+ e->value = (char*)qmalloc(strlen(token)+1);
+ strcpy (e->value, token);
+
+ return e;
+}
+
+/*
+================
+Entity_Parse
+
+If onlypairs is set, the classname info will not
+be looked up, and the entity will not be added
+to the global list. Used for parsing the project.
+================
+*/
+entity_t *Entity_Parse (qboolean onlypairs, brush_t* pList)
+{
+ entity_t *ent;
+ eclass_t *e;
+ brush_t *b;
+ vec3_t mins, maxs;
+ epair_t *ep;
+ qboolean has_brushes;
+
+ if (!GetToken (true))
+ return NULL;
+
+ if (strcmp (token, "{") )
+ Error ("ParseEntity: { not found");
+
+ ent = (entity_t*)qmalloc (sizeof(*ent));
+ ent->entityId = g_entityId++;
+ ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
+
+ int n = 0;
+ do
+ {
+ if (!GetToken (true))
+ {
+ Warning ("ParseEntity: EOF without closing brace");
+ return NULL;
+ }
+ if (!strcmp (token, "}") )
+ break;
+ if (!strcmp (token, "{") )
+ {
+ b = Brush_Parse ();
+ if (b != NULL)
+ {
+ b->owner = ent;
+ // add to the end of the entity chain
+ b->onext = &ent->brushes;
+ b->oprev = ent->brushes.oprev;
+ ent->brushes.oprev->onext = b;
+ ent->brushes.oprev = b;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ ep = ParseEpair ();
+ ep->next = ent->epairs;
+ ent->epairs = ep;
+ }
+ } while (1);
+
+ // group info entity?
+ if (strcmp(ValueForKey (ent, "classname"), "group_info") == 0)
+ return ent;
+
+ if (onlypairs)
+ return ent;
+
+ if (ent->brushes.onext == &ent->brushes)
+ has_brushes = false;
+ else
+ has_brushes = true;
+
+ GetVectorForKey (ent, "origin", ent->origin);
+
+ e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
+ ent->eclass = e;
+ if ( e->nShowFlags & ECLASS_PLUGINENTITY )
+ {
+ // locate the plugin
+ CPlugIn * pPlug = g_pParentWnd->GetPlugInMgr().PluginForModule( e->hPlug );
+ if (pPlug)
+ {
+ // create the plugin entity
+ IPluginEntity* pPlugEnt = pPlug->CreatePluginEntity( ent );
+ if (pPlugEnt)
+ {
+ ent->pPlugEnt = pPlugEnt;
+ // the brush is used to select and move
+ pPlugEnt->GetBounds( mins, maxs );
+ }
+ else
+ {
+ // give it a default bounding box
+ SetKeyValue (ent, "model", "");
+ mins[0] = -4; mins[1] = -4; mins[2] = -4;
+ maxs[0] = 4; maxs[1] = 4; maxs[2] = 4;
+ VectorAdd( mins, ent->origin, mins );
+ VectorAdd( maxs, ent->origin, maxs );
+ }
+ b = Brush_Create (mins, maxs, &ent->eclass->texdef);
+ Entity_LinkBrush (ent, b);
+ Brush_Build( b, true );
+ }
+ else
+ Sys_Printf("WARNING: plugin lookup failed for plugin entities\n");
+ }
+ else if (e->fixedsize)
+ { // fixed size entity
+ if (ent->brushes.onext != &ent->brushes)
+ {
+ printf ("Warning: Fixed size entity with brushes\n");
+#if 0
+ while (ent->brushes.onext != &ent->brushes)
+ { // FIXME: this will free the entity and crash!
+ Brush_Free (b);
+ }
+#endif
+ ent->brushes.next = ent->brushes.prev = &ent->brushes;
+ }
+
+ // create a custom brush
+ VectorAdd (e->mins, ent->origin, mins);
+ VectorAdd (e->maxs, ent->origin, maxs);
+
+ float a = 0;
+ if (e->nShowFlags & ECLASS_MISCMODEL)
+ {
+ char* p = ValueForKey(ent, "model");
+ if (p != NULL && strlen(p) > 0)
+ {
+ vec3_t vMin, vMax;
+ a = FloatForKey (ent, "angle");
+ if (GetCachedModel(ent, p, vMin, vMax))
+ {
+ // create a custom brush
+ VectorAdd (ent->md3Class->mins, ent->origin, mins);
+ VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
+ }
+ }
+ }
+
+ b = Brush_Create (mins, maxs, &e->texdef);
+
+ if (a)
+ {
+ vec3_t vAngle;
+ vAngle[0] = vAngle[1] = 0;
+ vAngle[2] = a;
+ Brush_Rotate(b, vAngle, ent->origin, false);
+ }
+
+
+ b->owner = ent;
+
+ b->onext = ent->brushes.onext;
+ b->oprev = &ent->brushes;
+ ent->brushes.onext->oprev = b;
+ ent->brushes.onext = b;
+ }
+ else
+ { // brush entity
+ if (ent->brushes.next == &ent->brushes)
+ printf ("Warning: Brush entity with no brushes\n");
+ }
+
+ // add all the brushes to the main list
+ if (pList)
+ {
+ for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
+ {
+ b->next = pList->next;
+ pList->next->prev = b;
+ b->prev = pList;
+ pList->next = b;
+ }
+ }
+
+ return ent;
+}
+
+void VectorMidpoint(vec3_t va, vec3_t vb, vec3_t& out)
+{
+ for (int i = 0; i < 3; i++)
+ out[i] = va[i] + ((vb[i] - va[i]) / 2);
+}
+
+
+/*
+============
+Entity_Write
+============
+*/
+void Entity_Write (entity_t *e, FILE *f, qboolean use_region)
+{
+ epair_t *ep;
+ brush_t *b;
+ vec3_t origin;
+ char text[128];
+ int count;
+
+ // if none of the entities brushes are in the region,
+ // don't write the entity at all
+ if (use_region)
+ {
+ // in region mode, save the camera position as playerstart
+ if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") )
+ {
+ fprintf (f, "{\n");
+ fprintf (f, "\"classname\" \"info_player_start\"\n");
+ fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)g_pParentWnd->GetCamera()->Camera().origin[0],
+ (int)g_pParentWnd->GetCamera()->Camera().origin[1], (int)g_pParentWnd->GetCamera()->Camera().origin[2]);
+ fprintf (f, "\"angle\" \"%i\"\n", (int)g_pParentWnd->GetCamera()->Camera().angles[YAW]);
+ fprintf (f, "}\n");
+ return;
+ }
+
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ if (!Map_IsBrushFiltered(b))
+ break; // got one
+
+ if (b == &e->brushes)
+ return; // nothing visible
+ }
+
+ if ( e->eclass->nShowFlags & ECLASS_PLUGINENTITY )
+ {
+ // NOTE: the whole brush placement / origin stuff is a mess
+ VectorCopy( e->origin, origin );
+ sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
+ SetKeyValue (e, "origin", text);
+ }
+ // if fixedsize, calculate a new origin based on the current
+ // brush position
+ else if (e->eclass->fixedsize)
+ {
+ if (e->eclass->nShowFlags & ECLASS_MISCMODEL && e->md3Class != NULL)
+ {
+ VectorCopy(e->origin, origin);
+ //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin);
+ }
+ else
+ {
+ VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
+ }
+ sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
+ SetKeyValue (e, "origin", text);
+ }
+
+ fprintf (f, "{\n");
+ for (ep = e->epairs ; ep ; ep=ep->next)
+ fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
+
+ if (!e->eclass->fixedsize)
+ {
+ count = 0;
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ {
+ if (!use_region || !Map_IsBrushFiltered (b))
+ {
+ fprintf (f, "// brush %i\n", count);
+ count++;
+ Brush_Write (b, f);
+ }
+ }
+ }
+ fprintf (f, "}\n");
+}
+
+
+
+qboolean IsBrushSelected(brush_t* bSel)
+{
+ for (brush_t* b = selected_brushes.next ;b != NULL && b != &selected_brushes; b = b->next)
+ {
+ if (b == bSel)
+ return true;
+ }
+ return false;
+}
+
+//
+//============
+//Entity_WriteSelected
+//============
+//
+void Entity_WriteSelected(entity_t *e, FILE *f)
+{
+ epair_t *ep;
+ brush_t *b;
+ vec3_t origin;
+ char text[128];
+ int count;
+
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ if (IsBrushSelected(b))
+ break; // got one
+
+ if (b == &e->brushes)
+ return; // nothing selected
+
+ // if fixedsize, calculate a new origin based on the current
+ // brush position
+ if (e->eclass->fixedsize)
+ {
+ if (e->eclass->nShowFlags & ECLASS_MISCMODEL && e->md3Class != NULL)
+ {
+ VectorCopy(e->origin, origin);
+ //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin);
+ }
+ else
+ {
+ VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
+ }
+ sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
+ SetKeyValue (e, "origin", text);
+ }
+
+ fprintf (f, "{\n");
+ for (ep = e->epairs ; ep ; ep=ep->next)
+ fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
+
+ if (!e->eclass->fixedsize)
+ {
+ count = 0;
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ {
+ if (IsBrushSelected(b))
+ {
+ fprintf (f, "// brush %i\n", count);
+ count++;
+ Brush_Write (b, f);
+ }
+ }
+ }
+ fprintf (f, "}\n");
+}
+
+
+//
+//============
+//Entity_WriteSelected to a CMemFile
+//============
+//
+void Entity_WriteSelected(entity_t *e, CMemFile* pMemFile)
+{
+ epair_t *ep;
+ brush_t *b;
+ vec3_t origin;
+ char text[128];
+ int count;
+
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ if (IsBrushSelected(b))
+ break; // got one
+
+ if (b == &e->brushes)
+ return; // nothing selected
+
+ // if fixedsize, calculate a new origin based on the current
+ // brush position
+ if (e->eclass->fixedsize)
+ {
+ if (e->eclass->nShowFlags & ECLASS_MISCMODEL && e->md3Class != NULL)
+ {
+ //VectorSubtract (e->brushes.onext->mins, e->md3Class->mins, origin);
+ VectorCopy(e->origin, origin);
+ }
+ else
+ {
+ VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
+ }
+ sprintf (text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
+ SetKeyValue (e, "origin", text);
+ }
+
+ MemFile_fprintf(pMemFile, "{\n");
+ for (ep = e->epairs ; ep ; ep=ep->next)
+ MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value);
+
+ if (!e->eclass->fixedsize)
+ {
+ count = 0;
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ {
+ if (IsBrushSelected(b))
+ {
+ MemFile_fprintf(pMemFile, "// brush %i\n", count);
+ count++;
+ Brush_Write (b, pMemFile);
+ }
+ }
+ }
+ MemFile_fprintf(pMemFile, "}\n");
+}
+
+
+
+
+/*
+============
+Entity_Create
+
+Creates a new entity out of the selected_brushes list.
+If the entity class is fixed size, the brushes are only
+used to find a midpoint. Otherwise, the brushes have
+their ownership transfered to the new entity.
+============
+*/
+entity_t *Entity_Create (eclass_t *c)
+{
+ entity_t *e;
+ brush_t *b;
+ vec3_t mins, maxs;
+ int i;
+
+ // check to make sure the brushes are ok
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ if (b->owner != world_entity)
+ {
+ Sys_Printf ("Entity NOT created, brushes not all from world\n");
+ Sys_Beep ();
+ return NULL;
+ }
+ }
+
+ // create it
+
+ e = (entity_t*)qmalloc(sizeof(*e));
+ e->entityId = g_entityId++;
+ e->brushes.onext = e->brushes.oprev = &e->brushes;
+ e->eclass = c;
+ SetKeyValue (e, "classname", c->name);
+
+ // add the entity to the entity list
+ Entity_AddToList(e, &entities);
+
+ // plugin entity ?
+ if (c->nShowFlags & ECLASS_PLUGINENTITY)
+ {
+ // locate the plugin
+ CPlugIn * pPlug = g_pParentWnd->GetPlugInMgr().PluginForModule( c->hPlug );
+ if (pPlug)
+ {
+ //
+ // just use the selection for positioning
+ //
+ b = selected_brushes.next;
+ for (i=0 ; i<3 ; i++)
+ e->origin[i] = b->mins[i] - c->mins[i];
+
+ // create the plugin entity
+ IPluginEntity* pPlugEnt = pPlug->CreatePluginEntity( e );
+
+ if (pPlugEnt)
+ {
+ e->pPlugEnt = pPlugEnt;
+ // the brush is used to select and move
+ pPlugEnt->GetBounds( mins, maxs );
+ b = Brush_Create (mins, maxs, &c->texdef);
+
+ Entity_LinkBrush (e, b);
+
+ // delete the current selection
+ Select_Delete ();
+
+ // select the new brush
+ b->next = b->prev = &selected_brushes;
+ selected_brushes.next = selected_brushes.prev = b;
+
+ Brush_Build( b );
+ }
+ }
+ else
+ {
+ Sys_Printf( "WARNING: plugin lookup failed while creating a plugin entitiy in Entity_Create\n" );
+ return NULL;
+ }
+ }
+ else if (c->fixedsize)
+ {
+ //
+ // just use the selection for positioning
+ //
+ b = selected_brushes.next;
+ for (i=0 ; i<3 ; i++)
+ e->origin[i] = b->mins[i] - c->mins[i];
+
+ // create a custom brush
+ VectorAdd (c->mins, e->origin, mins);
+ VectorAdd (c->maxs, e->origin, maxs);
+
+ b = Brush_Create (mins, maxs, &c->texdef);
+
+ Entity_LinkBrush (e, b);
+
+ // delete the current selection
+ Select_Delete ();
+
+ // select the new brush
+ b->next = b->prev = &selected_brushes;
+ selected_brushes.next = selected_brushes.prev = b;
+
+ Brush_Build( b );
+ }
+ else
+ {
+ //
+ // change the selected brushes over to the new entity
+ //
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ Entity_UnlinkBrush (b);
+ Entity_LinkBrush (e, b);
+ Brush_Build( b ); // so the key brush gets a name
+ }
+ }
+
+ Sys_UpdateWindows (W_ALL);
+ return e;
+}
+
+
+/*
+===========
+Entity_LinkBrush
+===========
+*/
+void Entity_LinkBrush (entity_t *e, brush_t *b)
+{
+ if (b->oprev || b->onext)
+ Error ("Entity_LinkBrush: Allready linked");
+ b->owner = e;
+
+ b->onext = e->brushes.onext;
+ b->oprev = &e->brushes;
+ e->brushes.onext->oprev = b;
+ e->brushes.onext = b;
+}
+
+/*
+===========
+Entity_UnlinkBrush
+===========
+*/
+void Entity_UnlinkBrush (brush_t *b)
+{
+ //if (!b->owner || !b->onext || !b->oprev)
+ if (!b->onext || !b->oprev)
+ Error ("Entity_UnlinkBrush: Not currently linked");
+ b->onext->oprev = b->oprev;
+ b->oprev->onext = b->onext;
+ b->onext = b->oprev = NULL;
+ b->owner = NULL;
+}
+
+
+/*
+===========
+Entity_Clone
+===========
+*/
+entity_t *Entity_Clone (entity_t *e)
+{
+ entity_t *n;
+ epair_t *ep, *np;
+
+ n = (entity_t*)qmalloc(sizeof(*n));
+ n->entityId = g_entityId++;
+ n->brushes.onext = n->brushes.oprev = &n->brushes;
+ n->eclass = e->eclass;
+
+ // add the entity to the entity list
+ Entity_AddToList(n, &entities);
+
+ for (ep = e->epairs ; ep ; ep=ep->next)
+ {
+ np = (epair_t*)qmalloc(sizeof(*np));
+ np->key = copystring(ep->key);
+ np->value = copystring(ep->value);
+ np->next = n->epairs;
+ n->epairs = np;
+ }
+ return n;
+}
+
+int GetUniqueTargetId(int iHint)
+{
+ int iMin, iMax, i;
+ BOOL fFound;
+ entity_t *pe;
+
+ fFound = FALSE;
+ pe = entities.next;
+ iMin = 0;
+ iMax = 0;
+
+ for (; pe != NULL && pe != &entities ; pe = pe->next)
+ {
+ i = IntForKey(pe, "target");
+ if (i)
+ {
+ iMin = min(i, iMin);
+ iMax = max(i, iMax);
+ if (i == iHint)
+ fFound = TRUE;
+ }
+ }
+
+ if (fFound)
+ return iMax + 1;
+ else
+ return iHint;
+}
+
+entity_t *FindEntity(char *pszKey, char *pszValue)
+{
+ entity_t *pe;
+
+ pe = entities.next;
+
+ for (; pe != NULL && pe != &entities ; pe = pe->next)
+ {
+ if (!strcmp(ValueForKey(pe, pszKey), pszValue))
+ return pe;
+ }
+
+ return NULL;
+}
+
+entity_t *FindEntityInt(char *pszKey, int iValue)
+{
+ entity_t *pe;
+
+ pe = entities.next;
+
+ for (; pe != NULL && pe != &entities ; pe = pe->next)
+ {
+ if (IntForKey(pe, pszKey) == iValue)
+ return pe;
+ }
+
+ return NULL;
+}
diff --git a/q3radiant/ENTITY.H b/q3radiant/ENTITY.H
new file mode 100755
index 0000000..df929c0
--- /dev/null
+++ b/q3radiant/ENTITY.H
@@ -0,0 +1,76 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+ // entity.h
+
+ void Eclass_InitForSourceDirectory (char *path);
+ eclass_t *Eclass_ForName (char *name, qboolean has_brushes);
+
+ // forward declare this one
+ class IPluginEntity;
+
+ typedef struct entity_s
+ {
+ struct entity_s *prev, *next;
+ brush_t brushes; // head/tail of list
+ int undoId, redoId, entityId; // used for undo/redo
+ vec3_t origin;
+ eclass_t *eclass;
+ epair_t *epairs;
+ eclass_t *md3Class;
+ IPluginEntity *pPlugEnt;
+ vec3_t vRotation; // valid for misc_models only
+ vec3_t vScale; // valid for misc_models only
+ } entity_t;
+
+ char *ValueForKey (entity_t *ent, const char *key);
+ void SetKeyValue (entity_t *ent, const char *key, const char *value);
+ void SetKeyValue (epair_t *&e, const char *key, const char *value);
+ void DeleteKey (entity_t *ent, const char *key);
+ void DeleteKey (epair_t *&e, const char *key);
+ float FloatForKey (entity_t *ent, const char *key);
+ int IntForKey (entity_t *ent, const char *key);
+ void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec);
+
+ void Entity_Free (entity_t *e);
+ void Entity_FreeEpairs(entity_t *e);
+ int Entity_MemorySize(entity_t *e);
+ entity_t *Entity_Parse (qboolean onlypairs, brush_t* pList = NULL);
+ void Entity_Write (entity_t *e, FILE *f, qboolean use_region);
+ void Entity_WriteSelected(entity_t *e, FILE *f);
+ void Entity_WriteSelected(entity_t *e, CMemFile*);
+ entity_t *Entity_Create (eclass_t *c);
+ entity_t *Entity_Clone (entity_t *e);
+ void Entity_AddToList(entity_t *e, entity_t *list);
+ void Entity_RemoveFromList(entity_t *e);
+
+ void Entity_LinkBrush (entity_t *e, brush_t *b);
+ void Entity_UnlinkBrush (brush_t *b);
+ entity_t *FindEntity(char *pszKey, char *pszValue);
+ entity_t *FindEntityInt(char *pszKey, int iValue);
+
+ int GetUniqueTargetId(int iHint);
+ qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax);
+ eclass_t* GetCachedModel(entity_t *pEntity, const char *pName, vec3_t &vMin, vec3_t &vMax);
+
+ //Timo : used for parsing epairs in brush primitive
+ epair_t* ParseEpair(void);
+ char *ValueForKey ( epair_t *&e, const char *key);
diff --git a/q3radiant/ENTITYW.H b/q3radiant/ENTITYW.H
new file mode 100755
index 0000000..7aad9da
--- /dev/null
+++ b/q3radiant/ENTITYW.H
@@ -0,0 +1,68 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// entity.h
+
+#define DlgXBorder 5
+#define DlgYBorder 5
+
+
+#define EntList 0
+#define EntComment 1
+#define EntCheck1 2
+#define EntCheck2 3
+#define EntCheck3 4
+#define EntCheck4 5
+#define EntCheck5 6
+#define EntCheck6 7
+#define EntCheck7 8
+#define EntCheck8 9
+#define EntCheck9 10
+#define EntCheck10 11
+#define EntCheck11 12
+#define EntCheck12 13
+#define EntProps 14
+#define EntDir0 15
+#define EntDir45 16
+#define EntDir90 17
+#define EntDir135 18
+#define EntDir180 19
+#define EntDir225 20
+#define EntDir270 21
+#define EntDir315 22
+#define EntDirUp 23
+#define EntDirDown 24
+#define EntDelProp 25
+#define EntKeyLabel 26
+#define EntKeyField 27
+#define EntValueLabel 28
+#define EntValueField 29
+#define EntColor 30
+#define EntAssignSounds 31
+#define EntAssignModels 32
+#define EntTab 33
+
+#define EntLast 34
+
+extern HWND hwndEnt[EntLast];
+
+extern int rgIds[EntLast];
+
diff --git a/q3radiant/EPAIRS.H b/q3radiant/EPAIRS.H
new file mode 100755
index 0000000..378cd31
--- /dev/null
+++ b/q3radiant/EPAIRS.H
@@ -0,0 +1,1402 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef EPAIRS_H_
+#define EPAIRS_H_
+
+typedef struct
+{
+ char *key;
+ char *value;
+} userEpair_t;
+
+userEpair_t eclassStr[] =
+{
+ //////////////////////////////
+ // Worldspawn
+ //////////////////////////////
+ {"classname", "worldspawn"},
+ {"color", "0 0 0"},
+ {"rem", "Only used for the world entity."},
+ {"rem", "cdtrack - number of CD track to play when level starts"},
+ {"rem", "fog_value - level of fog for this map"},
+
+ //////////////////////////////
+ // Light
+ //////////////////////////////
+ {"classname", "light"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "0 1 0"},
+ {"flag", "START_OFF"},
+
+ {"rem", "style - number of style to use, 0-63"},
+ {"rem", "nelnosmama - string to define lightstyle"},
+
+ //////////////////////////////
+ // light_walltorch
+ //////////////////////////////
+ {"classname", "light_walltorch"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "0 1 0"},
+ {"flag", "START_ON"},
+
+ {"rem", "style - number of style to use, 0-63"},
+ {"rem", "nelnosmama - string to define lightstyle"},
+
+ //////////////////////////////
+ // light_spot
+ //////////////////////////////
+ {"classname", "light_spot"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "0 1 0"},
+ {"flag", "START_ON"},
+
+ {"rem", "Used to make a spotlight. If it is targeted at another entity,"},
+ {"rem", "the spotlight will point directly at it, otherwise it will point"},
+ {"rem", "in the direction of its 'angle' field"},
+ {"rem", ""},
+ {"rem", "style - number of style to use, 0-63"},
+ {"rem", "nelnosmama - string to define lightstyle"},
+
+ //////////////////////////////
+ // light_strobe
+ //////////////////////////////
+ {"classname", "light_strobe"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "0 1 0"},
+
+ {"flag", "START_ON"},
+ {"rem", "style - number of style to use, 0-63"},
+ {"rem", "nelnosmama - string to define lightstyle"},
+
+ //////////////////////////////
+ // effect_fog
+ //////////////////////////////
+ {"classname", "effect_fog"},
+ {"color", "0 1 0"},
+ {"rem", "Duh, fog."},
+ {"rem", ""},
+
+ //////////////////////////////
+ // effect_snow
+ //////////////////////////////
+ {"classname", "effect_snow"},
+ {"color", "1 1 1"},
+ {"height", "10"},
+ {"rem", "Snow!"},
+ {"rem", "Do you realize the entire street value of this mountain?"},
+
+ //////////////////////////////
+ // effect_rain
+ //////////////////////////////
+ {"classname", "effect_rain"},
+ {"height", "10"},
+ {"color", "0 0.5 0.8"},
+ {"rem", "Rain!"},
+ {"rem", "Yellow rain?"},
+
+ //////////////////////////////
+ // func_door
+ //////////////////////////////
+ {"classname", "func_door"},
+ {"color", "0 0.5 0.8"},
+ {"health", "0"},
+ {"speed", "100"},
+ {"wait", "3"},
+ {"lip", "8"},
+ {"dmg", "2"},
+ {"angle", "0 0 0"},
+ {"message", "you suck"},
+ {"targetname", ""},
+ {"flag", "START_OPEN"},
+ {"flag", "REVERSE"},
+ {"flag", "DOOR_DONT_LINK"},
+ {"flag", "TOGGLE"},
+ {"flag", "AUTO_OPEN"},
+ {"flag", "USE_TO_CLOSE"},
+
+ {"rem", "Doors that touch are linked together to operate as one."},
+ {"rem", " "},
+ {"rem", "message - printed when the door is touched if it is a trigger door and it hasn't been fired yet"},
+ {"rem", "angle - determines the opening direction"},
+ {"rem", "targetname - if set, no touch field will be spawned and a remote button or trigger field activates the door."},
+ {"rem", "health - if set, door must be shot open"},
+ {"rem", "speed - movement speed (100 default)"},
+ {"rem", "wait - time to wait before returning (3 default, -1 = never return)"},
+ {"rem", "lip - amount of door visible remaining at end of move (8 default)"},
+ {"rem", "dmg - damage to inflict when blocked (2 default)"},
+ {"rem", "sound_opening - name of the sound to play during opening, ie. doors/creek.wav"},
+ {"rem", "sound_open_finish - name of the sound to play when opening completes, ie. doors/slam.wav"},
+ {"rem", "sound_closing - name of the sound to play when closing starts, ie. doors/creek.wav"},
+ {"rem", "sound_close_finish - name of the sound to play when closing completes, ie. doors/slam.wav"},
+ {"rem", " "},
+ {"rem", "Spawnflags:"},
+ {"rem", "TOGGLE causes the door to wait in both the start and end states for a"},
+ {"rem", "trigger event."},
+ {"rem", " "},
+ {"rem", "START_OPEN causes the door to move to its destination when spawned, and"},
+ {"rem", "operate in reverse. It is used to temporarily or permanently close off an"},
+ {"rem", "area when triggered (not usefull for touch or takedamage doors)."},
+ {"rem", "AUTO_OPEN will spawn a trigger field around the door that can open it without"},
+ {"rem", "its being used."},
+ {"rem", "DOOR_DONT_LINK will stop a door from being automatically linked to other doors"},
+ {"rem", "that it touches."},
+
+ //////////////////////////////
+ // func_plat
+ //////////////////////////////
+ {"classname", "func_plat"},
+ {"color", "0 0.5 0.8"},
+ {"flag", "PLAT_START_UP"},
+ {"flag", ""},
+ {"flag", ""},
+ {"flag", "PLAT_TOGGLE"},
+
+ {"rem", "Plats should be drawn in the up position to spawn correctly"},
+ {"rem", " "},
+ {"rem", "message - printed when the door is touched if it is a trigger door and it hasn't been fired yet"},
+ {"rem", "angle - determines the opening direction"},
+ {"rem", "targetname - if set, no touch field will be spawned and a remote button or trigger field activates the door."},
+ {"rem", "health - if set, door must be shot open"},
+ {"rem", "speed - movement speed (100 default)"},
+ {"rem", "wait - time to wait before returning (3 default, -1 = never return)"},
+ {"rem", "height - number of units to move the platform up from spawn position. If height is"},
+ {"rem", "not specified, then the movement distance is determined based on the vertical size of the platform."},
+ {"rem", "dmg - damage to inflict when blocked (2 default)"},
+ {"rem", "sound_up - name of the sound to play when going up, ie. doors/creek.wav"},
+ {"rem", "sound_top - name of the sound to play when plat hits top, ie. doors/slam.wav"},
+ {"rem", "sound_down - name of the sound to play when going down, ie. doors/creek.wav"},
+ {"rem", "sound_bottom - name of the sound to play when plat hits bottom, ie. doors/slam.wav"},
+ {"rem", " "},
+ {"rem", "Spawnflags:"},
+ {"rem", "PLAT_START_UP starts the platform in the up (drawn) position"},
+ {"rem", "(height added to drawn position)"},
+ {"rem", "TOGGLE causes the platform to wait in both the start and end states for a"},
+ {"rem", "trigger event."},
+
+ //////////////////////////////
+ // func_door_rotate
+ //////////////////////////////
+ {"classname", "func_door_rotate"},
+ {"distance", "90.0"},
+ {"color", "0 0.5 0.8"},
+ {"message", "they suck"},
+ {"flag", "START_OPEN"},
+ {"flag", "REVERSE"},
+ {"flag", "DOOR_DONT_LINK"},
+ {"flag", "TOGGLE"},
+ {"flag", "X_AXIS"},
+ {"flag", "Y_AXIS"},
+ {"flag", "AUTO_OPEN"},
+ {"flag", "USE_TO_CLOSE"},
+// {"flag", "X_AXIS"},
+// {"flag", "Y_AXIS"},
+
+ {"rem", "if two doors touch, they are assumed to be connected and operate as a unit."},
+ {"rem", " "},
+ {"rem", "TOGGLE causes the door to wait in both the start and end states for a"},
+ {"rem", "trigger event."},
+ {"rem", " "},
+ {"rem", "START_OPEN causes the door to move to its destination when spawned, and"},
+ {"rem", "operate in reverse. It is used to temporarily or permanently close off an"},
+ {"rem", "area when triggered (not usefull for touch or takedamage doors)."},
+ {"rem", " "},
+ {"rem", "Key doors are allways wait -1."},
+ {"rem", " "},
+ {"rem", "You need to have an origin brush as part of this entity. The center of"},
+ {"rem", "that brush will be"},
+ {"rem", "the point around which it is rotated. It will rotate around the Z axis by"},
+ {"rem", "default. You can"},
+ {"rem", "check either the X_AXIS or Y_AXIS box to change that."},
+ {"rem", " "},
+ {"rem", "'distance' is how many degrees the door will be rotated."},
+ {"rem", "'speed' determines how fast the door moves; default value is 100."},
+ {"rem", " "},
+ {"rem", "REVERSE will cause the door to rotate in the opposite direction."},
+ {"rem", " "},
+ {"rem", "'message' is printed when the door is touched if it is a trigger door and"},
+ {"rem", " it hasn't been fired yet."},
+ {"rem", "'targetname' if set, no touch field will be spawned and a remote button or"},
+ {"rem", " trigger field activates the door."},
+ {"rem", "'health' if set, door must be shot open"},
+ {"rem", "'wait' wait before returning (3 default, -1 = never return)"},
+ {"rem", "'dmg' damage to inflict when blocked (2 default)"},
+ {"rem", "sound_opening - name of the sound to play during opening, ie. doors/creek.wav"},
+ {"rem", "sound_open_finish - name of the sound to play when opening completes, ie. doors/slam.wav"},
+ {"rem", "sound_closing - name of the sound to play when closing starts, ie. doors/creek.wav"},
+ {"rem", "sound_close_finish - name of the sound to play when closing completes, ie. doors/slam.wav"},
+ {"rem", "AUTO_OPEN will spawn a trigger field around the door that can open it without"},
+ {"rem", "its being used."},
+ {"rem", "DOOR_DONT_LINK will stop a door from being automatically linked to other doors"},
+ {"rem", "that it touches."},
+
+ //////////////////////////////
+ // func_rotate
+ //////////////////////////////
+ {"classname", "func_rotate"},
+ {"color", "0.0 0.5 0.8"},
+ {"flag", "START_ON"},
+ {"flag", "REVERSE"},
+ {"flag", "X_AXIS"},
+ {"flag", "Y_AXIS"},
+
+ {"rem", "You need to have an origin brush as part of this entity."},
+ {"rem", "The center of that brush will be"},
+ {"rem", "the point around which it is rotated. It will rotate around the Z axis by"},
+ {"rem", "default. You can"},
+ {"rem", "check either the X_AXIS or Y_AXIS box to change that."},
+ {"rem", " "},
+ {"rem", "'speed' determines how fast it moves; default value is 100."},
+ {"rem", "'dmg' damage to inflict when blocked (2 default)"},
+ {"rem", " "},
+ {"rem", "REVERSE will cause the it to rotate in the opposite direction."},
+
+ //////////////////////////////
+ // trigger_multiple
+ //////////////////////////////
+ {"classname", "trigger_multiple"},
+ {"color", "0.5 0.5 0.5"},
+ {"health", "0"},
+ {"delay", "0"},
+ {"wait", "0.2"},
+ {"sound", ""},
+ {"targetname", ""},
+ {"target", ""},
+ {"killtarget", ""},
+ {"message", ""},
+ {"flag", "NOTOUCH"},
+
+ {"rem", "a repeatable trigger, targetted at the entity with the name"},
+ {"rem", "targetname."},
+ {"rem", ""},
+ {"rem", "health - if set the trigger must be killed to activate"},
+ {"rem", "delay - time to wait after activation before firing target"},
+ {"rem", "wait - time to wait between retriggering (default = 0.2 seconds)"},
+ {"rem", ""},
+ {"rem", "Spawnflags:"},
+ {"rem", "NOTOUCH - if set the trigger is only fired by other entities and"},
+ {"rem", "not by touching."},
+
+ //////////////////////////////
+ // trigger_console
+ //////////////////////////////
+ {"classname", "trigger_console"},
+ {"color", "0.5 0.5 0.5"},
+ {"wait", "0.2"},
+ {"command", ""},
+ {"rem", ""},
+ {"rem", "command - the command to send to the console when triggered"},
+
+ //////////////////////////////
+ // trigger_once
+ //////////////////////////////
+ {"classname", "trigger_once"},
+ {"color", "0.5 0.5 0.5"},
+ {"angle", "0 0 0"},
+ {"health", "0"},
+ {"delay", "0"},
+ {"sound", ""},
+ {"targetname", ""},
+ {"killtarget", ""},
+ {"message", ""},
+ {"flag", "NOTOUCH"},
+
+ {"rem", "triggers once, then removes itself"},
+ {"rem", " "},
+ {"rem", "health - if set the trigger must be killed to activate"},
+ {"rem", "delay - time to wait after activation before firing target"},
+ {"rem", "wait - time to wait between retriggering (default = 0.2 seconds)"},
+ {"rem", "sound - name of sound to play upon firing"},
+ {"rem", " "},
+ {"rem", "Spawnflags:"},
+ {"rem", "NOTOUCH - if set the trigger is only fired by other entities and"},
+ {"rem", "not by touching."},
+
+ //////////////////////////////
+ // trigger_relay
+ //////////////////////////////
+ {"classname", "trigger_relay"},
+ {"color", "0.5 0.5 0.5"},
+ {"delay", "0"},
+ {"sound", ""},
+ {"targetname", ""},
+ {"killtarget", ""},
+ {"message", ""},
+
+ {"rem", "sound - name of sound to play upon firing"},
+
+ //////////////////////////////
+ // trigger_teleport
+ //////////////////////////////
+ {"classname", "trigger_teleport"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"targetname", ""},
+ {"killtarget", ""},
+ {"message", ""},
+ {"flag", "PLAYER_ONLY"},
+ {"flag", "NO_FLASH"},
+ {"flag", "NO_ANGLE_ADJUST"},
+
+ {"rem", "sound - name of sound to play upon firing, if not specified, then no"},
+ {"rem", "sound will be played"},
+ {"rem", "fog_value - sets fog_value to this when a teleporter is used"},
+ {"rem", ""},
+ {"rem", "Spawnflags:"},
+ {"rem", "PLAYER_ONLY - will only teleport players (NOT bots)"},
+ {"rem", "NO_FLASH - no spawn fog will be generated when an object teleports"},
+ {"rem", "NO_ANGLE_ADJUST - the object's angle will not be adjusted when it is"},
+ {"rem", "teleported."},
+
+ //////////////////////////////
+ // info_teleport_destination
+ //////////////////////////////
+ {"classname", "info_teleport_destination"},
+ {"color", "0.5 0.5 0.5"},
+ {"size", "-8.0 -8.0 -8.0 8.0 8.0 8.0"},
+
+ //////////////////////////////
+ // trigger_warp
+ //////////////////////////////
+ {"classname", "trigger_warp"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"targetname", ""},
+ {"killtarget", ""},
+ {"message", ""},
+ {"flag", "PLAYER_ONLY"},
+ {"flag", "NO_FLASH"},
+ {"flag", "NO_ANGLE_ADJUST"},
+
+ {"rem", "sound - name of sound to play upon firing, if not specified, then no"},
+ {"rem", "sound will be played"},
+ {"rem", "fog_value - sets fog_value to this when a warp is used"},
+ {"rem", "speed - speed from this path point to the next"},
+ {"rem", ""},
+ {"rem", "Spawnflags:"},
+ {"rem", "PLAYER_ONLY - will only teleport players (NOT bots)"},
+ {"rem", "NO_FLASH - no spawn fog will be generated when an object teleports"},
+ {"rem", "NO_ANGLE_ADJUST - the object's angle will not be adjusted when it is"},
+ {"rem", "teleported."},
+
+ //////////////////////////////
+ // tele_cylinder
+ //////////////////////////////
+
+ {"classname", "warp_cylinder"},
+ {"color", "0.5 0.5 0.5"},
+ {"color", "1 0 1"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Location player starts in deathmatch"},
+
+ //////////////////////////////
+ // info_warp_destination
+ //////////////////////////////
+ {"classname", "info_warp_destination"},
+ {"color", "0.5 0.5 0.5"},
+ {"size", "-8.0 -8.0 -8.0 8.0 8.0 8.0"},
+
+ {"rem", "target - next target to warp to"},
+ {"rem", "speed - speed from this path point to the next"},
+
+ //////////////////////////////
+ // trigger_onlyregistered
+ //////////////////////////////
+ {"classname", "trigger_onlyregistered"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"wait", "2.0"},
+ {"message", ""},
+
+ {"rem", "sound - name of sound to play upon firing"},
+ {"rem", "wait - the number of seconds between triggerings and"},
+ {"rem", "the length of time the message will be displayed"},
+
+ //////////////////////////////
+ // trigger_hurt
+ //////////////////////////////
+ {"classname", "trigger_hurt"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"dmg", "2.0"},
+ {"wait", "2.0"},
+ {"message", ""},
+
+ {"rem", "sound - name of sound to play upon firing"},
+ {"rem", "dmg - the amount of damage the trigger will do to an object"},
+ {"rem", "wait - the number of seconds between triggerings and"},
+
+ //////////////////////////////
+ // trigger_push
+ //////////////////////////////
+ {"classname", "trigger_push"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"message", ""},
+ {"speed", "1000.0"},
+ {"flag", "PUSH_ONCE"},
+ {"rem", "speed - the velocity to give the object"},
+ {"rem", "speed - the velocity to give the object"},
+
+ //////////////////////////////
+ // trigger_counter
+ //////////////////////////////
+ {"classname", "trigger_counter"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"flag", "NO_MESSAGE"},
+
+ {"rem", "sound - name of sound to play upon firing"},
+ {"rem", "message - message to display upon last triggering"},
+ {"rem", "when NO_MESSAGE is set, no messages are displayed upon triggering"},
+
+ //////////////////////////////
+ // trigger_changelevel
+ //////////////////////////////
+ {"classname", "trigger_changelevel"},
+ {"color", "0.5 0.5 0.5"},
+ {"sound", ""},
+ {"map", ""},
+ {"flag", "NO_INTERMISSION"},
+
+ {"rem", "sound - name of sound to play upon firing"},
+ {"rem", "message - message to display upon last triggering"},
+
+ //////////////////////////////
+ // func_wall
+ //////////////////////////////
+ {"classname", "func_wall"},
+ {"color", "0 0.5 0.8"},
+ {"health", "0"},
+ {"message", ""},
+ {"targetname", ""},
+ {"target", ""},
+ {"killtarget", ""},
+
+ {"rem", "targetname - the name of this wall if it is a target"},
+ {"rem", "target - the next entity to trigger when this one is triggered"},
+ {"rem", "killtarget - the targetname of the entity to remove when triggered"},
+
+ //////////////////////////////
+ // func_button
+ //////////////////////////////
+ {"classname", "func_button"},
+ {"color", "0 0.5 0.8"},
+ {"health", "0"},
+ {"targetname", ""},
+ {"target", ""},
+ {"killtarget", ""},
+ {"speed", ""},
+ {"wait", ""},
+ {"angle", ""},
+ {"lip", ""},
+ {"flag", "PUSH_TOUCH"},
+
+ {"rem", "targetname - the name of this wall if it is a target"},
+ {"rem", "target - the next entity to trigger when this one is triggered"},
+ {"rem", "killtarget - the targetname of the entity to remove when triggered"},
+ {"rem", "sound_use - the sound to play when the button is used (defaults to none)"},
+ {"rem", "sound_return - the sound to play when the button returns (defaults to none)"},
+ {"rem", "speed - rate of travel when button moves"},
+ {"rem", "wait - seconds to wait befor returning to useable (-1 = never return)"},
+ {"rem", "angle - direction of travel"},
+ {"rem", "lip - amount of button left sticking out after being pushed (default 4)"},
+ {"rem", "health - when > 0 the button must be killed in order to fire"},
+ {"rem", "PUSH_TOUCH will allow the button to be pushed by running into it, Quake style"},
+
+ //////////////////////////////
+ // func_multi_button
+ //////////////////////////////
+ {"classname", "func_multi_button"},
+ {"color", "0 0.5 0.8"},
+ {"health", "0"},
+ {"targetname", ""},
+ {"target", ""},
+ {"killtarget", ""},
+ {"speed", ""},
+ {"wait", ""},
+ {"angle", ""},
+ {"lip", ""},
+ {"flag", "PUSH_TOUCH"},
+ {"flag", "CYCLE"},
+
+ {"rem", "targetname - the name of this wall if it is a target"},
+ {"rem", "target - the next entity to trigger when this one is triggered"},
+ {"rem", "killtarget - the targetname of the entity to remove when triggered"},
+ {"rem", "sound_use - the sound to play when the button is used (defaults to none)"},
+ {"rem", "sound_return - the sound to play when the button returns (defaults to none)"},
+ {"rem", "speed - rate of travel when button moves"},
+ {"rem", "wait - seconds to wait befor returning to useable (-1 = never return)"},
+ {"rem", "angle - direction of travel"},
+ {"rem", "health - when > 0 the button must be killed in order to fire"},
+ {"rem", "distance - distance button travels on each push"},
+ {"rem", "count - number of positions this button has"},
+ {"rem", "PUSH_TOUCH will allow the button to be pushed by running into it, Quake style"},
+ {"rem", "CYCLE - button will not return to top from last position, but will go back through all positions"},
+
+ //////////////////////////////
+ // func_train
+ //////////////////////////////
+ {"classname", "func_train"},
+ {"distance", "90.0"},
+ {"color", "0 0.5 0.8"},
+ {"rem", "targetname - the name of this train"},
+ {"rem", "target - the path_corner that the train will spawn at"},
+ {"rem", "killtarget - the targetname of the entity to remove when triggered"},
+
+ //////////////////////////////
+ // func_train
+ //////////////////////////////
+ {"classname", "func_train2"},
+ {"distance", "90.0"},
+ {"color", "0 0.5 0.8"},
+ {"rem", "targetname - the name of this train"},
+ {"rem", "target - the path_corner that the train will spawn at"},
+ {"rem", "killtarget - the targetname of the entity to remove when triggered"},
+
+ //////////////////////////////
+ // path_corner_train
+ //////////////////////////////
+ {"classname", "path_corner_train"},
+ {"distance", "90.0"},
+ {"color", "0.5 0.3 0"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"flag", "X_AXIS"},
+ {"flag", "Y_AXIS"},
+ {"flag", "Z_AXIS"},
+ {"flag", "TRIGWAIT"},
+ {"rem", "killtarget - the targetname of the entity to remove when this"},
+ {"rem", "path_corner is reached"},
+ {"rem", "speed - rate of travel from this path_corner to the next"},
+ {"rem", "wait - seconds to wait after the actions on this path_corner are complete"},
+ {"rem", "sound - sound to play at this path corner"},
+ {"rem", "x_distance - distance in degrees to rotate around x axis"},
+ {"rem", "y_distance - distance in degrees to rotate around y axis"},
+ {"rem", "z_distance - distance in degrees to rotate around z axis"},
+ {"rem", "x_speed - speed to rotate along x axis in degrees per second"},
+ {"rem", "y_speed - speed to rotate along y axis in degrees per second"},
+ {"rem", "z_speed - speed to rotate along z axis in degrees per second"},
+ {"rem", "health - if health is set, the train will wait at this path corner"},
+ {"rem", "until it is killed."},
+ {"rem", "Spawnflags:"},
+ {"rem", "X_AXIS - when checked train will rotate continually around "},
+ {"rem", "x axis at x_speed degrees per second"},
+ {"rem", "Y_AXIS - when checked train will rotate continually around "},
+ {"rem", "y axis at y_speed degrees per second"},
+ {"rem", "Z_AXIS - when checked train will rotate continually around "},
+ {"rem", "z axis at z_speed degrees per second"},
+ {"rem", "TRIGWAIT - wait here until triggered"},
+
+ //////////////////////////////
+ // info_player_start
+ //////////////////////////////
+ {"classname", "info_player_start"},
+ {"color", "1 0 0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Location player starts in single play."},
+
+ //////////////////////////////
+ // info_mikiko_start
+ //////////////////////////////
+ {"classname", "info_mikiko_start"},
+ {"color", "1 0 0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Location Mikiko starts in single play."},
+
+ //////////////////////////////
+ // info_superfly_start
+ //////////////////////////////
+ {"classname", "info_superfly_start"},
+ {"color", "1 0 0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Location Superfly starts in single play."},
+
+ //////////////////////////////
+ // info_null
+ //////////////////////////////
+ {"classname", "info_null"},
+ {"color", "1 0 0"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"rem", "You can point anything to this as a target"},
+
+ //////////////////////////////
+ // info_player_deathmatch
+ //////////////////////////////
+ {"classname", "info_player_deathmatch"},
+ {"color", "1 0 1"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Location player starts in deathmatch"},
+
+ //////////////////////////////
+ // info_player_coop
+ //////////////////////////////
+ {"classname", "info_player_coop"},
+ {"color", "1 0 1"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Location player starts in coop"},
+
+ //////////////////////////////
+ // func_door_secret
+ //////////////////////////////
+ {"classname", "func_door_secret"},
+ {"color", "0 0.5 0.8"},
+ {"health", "0"},
+ {"speed", "100"},
+ {"wait", "3"},
+ {"lip", "8"},
+ {"dmg", "2"},
+ {"angle", "0 0 0"},
+ {"message", "we all suck"},
+ {"targetname", ""},
+ {"flag", "OPEN_ONCE"},
+ {"flag", "1ST_LEFT"},
+ {"flag", "1ST_DOWN"},
+ {"flag", "NO_SHOOT"},
+ {"flag", "YES_SHOOT"},
+
+ {"rem", "message - printed when the door is touched if it is a trigger door and it hasn't been fired yet"},
+ {"rem", "angle - determines the opening direction"},
+ {"rem", "targetname - if set, no touch field will be spawned and a remote button or trigger field activates the door."},
+ {"rem", "health - if set, door must be shot open"},
+ {"rem", "speed - movement speed (100 default)"},
+ {"rem", "wait - time to wait before returning (3 default, -1 = never return)"},
+ {"rem", "dmg - damage to inflict when blocked (2 default)"},
+ {"rem", "sound_opening - name of the sound to play during opening, ie. doors/creek.wav"},
+ {"rem", "sound_open_finish - name of the sound to play when opening completes, ie. doors/slam.wav"},
+ {"rem", "sound_closing - name of the sound to play when closing starts, ie. doors/creek.wav"},
+ {"rem", "sound_close_finish - name of the sound to play when closing completes, ie. doors/slam.wav"},
+ {"rem", " "},
+ {"rem", "Spawnflags:"},
+ {"rem", "SECRET_OPEN_ONCE - door stays open (imagine that...)"},
+ {"rem", "SECRET_1ST_LEFT - first move is left of move direction"},
+ {"rem", "SECRET_1ST_DOWN - first move is down from move direction"},
+ {"rem", "SECRET_NO_SHOOT - only opened by a trigger"},
+ {"rem", "SECRET_YES_SHOOT - shootable even if targeted"},
+
+ //////////////////////////////
+ // func_wall_explode
+ //////////////////////////////
+ {"classname", "func_wall_explode"},
+ {"color", "0 0.5 0.8"},
+ {"health", "0"},
+ {"message", ""},
+ {"targetname", ""},
+ {"target", ""},
+ {"killtarget", ""},
+ {"model_1", ""},
+ {"model_2", ""},
+ {"model_3", ""},
+ {"flag", "ROCK_CHUNKS"},
+ {"flag", "WOOD_CHUNKS"},
+ {"flag", "EXTRA_CHUNKS"},
+ {"flag", "EXTRA_VELOCITY"},
+ {"flag", "NO_CHUNKS"},
+ {"flag", "NO_SOUND"},
+
+ {"rem", "targetname - the name of this wall if it is a target"},
+ {"rem", "target - the next entity to trigger when this one is triggered"},
+ {"rem", "killtarget - the targetname of the entity to remove when triggered"},
+ {"rem", "health - ummm... this would be the health of the wall, if it is 0 then"},
+ {"rem", "the wall can only be exploded by targetting it"},
+ {"rem", "message - this prints out when wall go boom"},
+ {"rem", "model_1 - the specific pathname of the first model to throw when killed"},
+ {"rem", "if model_1 is set then spawnflags ROCK_CHUNKS and WOOD_CHUNKS are overridden"},
+ {"rem", "model_2 - the pathname of the second model"},
+ {"rem", "model_3 - I wouldn't bet on it, but this is probably the name of the 3rd model"},
+ {"rem", " "},
+ {"rem", "Spawnflags:"},
+ {"rem", "ROCK_CHUNKS - makes rock chunk wall-gibs fly"},
+ {"rem", "WOOD_CHUNKS - makes wood chunk wall-gibs fly"},
+ {"rem", "EXTRA_CHUNKS - makes up to 3 chunks per explosion, instead of just one"},
+ {"rem", "EXTRA_VELOCITY - gives chunks a higher velocity (good for underwater)"},
+ {"rem", "NO_CHUNKS - um, no chunks"},
+ {"rem", "NO_SOUND - no sound, use when lots of func walls are activated simultaneously to keep the"},
+ {"rem", "Quake engine from choking with too many sounds at once."},
+
+ //////////////////////////////
+ // func_anim
+ //////////////////////////////
+ {"classname", "func_anim"},
+ {"color", "0.0 1.0 0.1"},
+ {"flag", "VISIBLE"},
+ {"rem", "Spawnflags:"},
+ {"rem", "VISIBLE - start visible"},
+
+ //////////////////////////////
+ // func_floater
+ //////////////////////////////
+ {"classname", "func_floater"},
+ {"color", "0 0.5 0.8"},
+ {"size", "-16 -16 -16 16 16 16"},
+ {"model", ""},
+
+ {"rem", "model - pathname to model (ie. models/floater.mdl)"},
+ {"rem", "velocity_cap - maximum up/down velocity"},
+ {"rem", "dissipate - how fast velocity degrades to velocity_cap (default = 0.99)"},
+ {"rem", "object_mass - mass of object (mass / volume = density)"},
+ {"rem", "object_volume - volume of object (mass / volume = density)"},
+
+ //////////////////////////////
+ // func_debris
+ //////////////////////////////
+
+ {"classname", "func_debris"},
+ {"color", "0 0.5 0.8"},
+ {"target", ""},
+ {"flag", "GO_TO_ACTIVATOR"},
+ {"flag", "NO_ROTATE"},
+ {"flag", "MOMENTUM_DAMAGE"},
+ {"flag", "NO_ROTATION_ADJUST"},
+ {"flag", "DROP_ONLY"},
+ {"flag", "QUARTER_SIZE"},
+
+ {"rem", "target - debris will fly towards targeted entity"},
+ {"rem", "fly_sound - sound to play while the entity flies through the air"},
+ {"rem", "hit_sound - sound to play when the entity hits something"},
+ {"rem", "damage - amount of damage to do when hitting another object"},
+ {"rem", "if MOMENTUM_DAMAGE is selected, then damage will be based on the"},
+ {"rem", "speed of the debris when it impacts the object and damage becomes"},
+ {"rem", "the divisor, so if speed at impact = 300 and damge = 3, then damage done"},
+ {"rem", "while 300 / 3 = 100 points. If damage is not set, then momentum damage"},
+ {"rem", "will be the default with a damage divisor of 3."},
+ {"rem", "Spawnflags:"},
+ {"rem", "GO_TO_ACTIVATOR - debris will fly at whoever activated it"},
+ {"rem", "NO_ROTATE - don't give this debris any random rotation"},
+ {"rem", "MOMENTUM_DAMAGE - damage based on velocity"},
+ {"rem", "DROP_ONLY - no upward velocity, debris just falls"},
+ {"rem", "QUARTER_SIZE - shrink bounding box by 1/4"},
+ {"rem", "Notes:"},
+ {"rem", "A func debris entity must have an origin brush contained in it,"},
+ {"rem", "otherwise it will rotate around the center of the level, not"},
+ {"rem", "its own center. That is bad."},
+
+ //////////////////////////////
+ // func_debris_visible
+ //////////////////////////////
+
+ {"classname", "func_debris_visible"},
+ {"color", "0 0.5 0.8"},
+ {"target", ""},
+ {"flag", "GO_TO_ACTIVATOR"},
+ {"flag", "NO_ROTATE"},
+ {"flag", "MOMENTUM_DAMAGE"},
+ {"flag", "NO_ROTATION_ADJUST"},
+ {"flag", "DROP_ONLY"},
+ {"flag", "QUARTER_SIZE"},
+
+ {"rem", "SAME AS FUNC_DEBRIS EXCEPT DEBRIS IS VISIBLE BEFORE TARGETTING"},
+ {"rem", "target - debris will fly towards targeted entity"},
+ {"rem", "fly_sound - sound to play while the entity flies through the air"},
+ {"rem", "hit_sound - sound to play when the entity hits something"},
+ {"rem", "damage - amount of damage to do when hitting another object"},
+ {"rem", "if MOMENTUM_DAMAGE is selected, then damage will be based on the"},
+ {"rem", "speed of the debris when it impacts the object and damage becomes"},
+ {"rem", "the divisor, so if speed at impact = 300 and damge = 3, then damage done"},
+ {"rem", "while 300 / 3 = 100 points. If damage is not set, then momentum damage"},
+ {"rem", "will be the default with a damage divisor of 3."},
+ {"rem", "Spawnflags:"},
+ {"rem", "GO_TO_ACTIVATOR - debris will fly at whoever activated it"},
+ {"rem", "NO_ROTATE - don't give this debris any random rotation"},
+ {"rem", "MOMENTUM_DAMAGE - damage based on velocity"},
+ {"rem", "DROP_ONLY - no upward velocity, debris just falls"},
+ {"rem", "QUARTER_SIZE - shrink bounding box by 1/4"},
+ {"rem", "Notes:"},
+ {"rem", "A func debris entity must have an origin brush contained in it,"},
+ {"rem", "otherwise it will rotate around the center of the level, not"},
+ {"rem", "its own center. That is bad."},
+
+ //////////////////////////////
+ // func_particlefield
+ //////////////////////////////
+ {"classname", "func_particlefield"},
+ {"color", "0 0.5 0.8"},
+ {"flag", "USE_COUNT"},
+ {"rem", "count - number of times to trigger before activated"},
+ {"rem", "color - color of particles use:"},
+ {"rem", "black, blue, green, cyan, red, "},
+ {"rem", "purple, brown, ltgray, dkgray, "},
+ {"rem", "ltblue, ltgreen, ltcyan, ltpurple,"},
+ {"rem", "yellow, white"},
+
+ //////////////////////////////
+ // func_monitor
+ //////////////////////////////
+ {"classname", "func_monitor"},
+ {"color", "0 0.5 0.8"},
+ {"rem", "target - the info_camera that the view will be from"},
+ {"rem", "fov - the field of view when looking through this camera"},
+
+ //////////////////////////////
+ // info_camera
+ //////////////////////////////
+ {"classname", "info_camera"},
+ {"color", "1 0 0"},
+ {"size", "-8 -8 -8 8 8 8"},
+
+ //////////////////////////////
+ // misc_lavaball_drop
+ //////////////////////////////
+ {"classname", "misc_lavaball_drop"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "1.0 0.5 0.0"},
+
+ //////////////////////////////
+ // misc_lavaball_toss
+ //////////////////////////////
+ {"classname", "misc_lavaball_toss"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "1.0 0.5 0.0"},
+
+ {"rem", "target = can be triggered"},
+ {"rem", "mintime = minimum time between tosses (default = 4.0 seconds)"},
+ {"rem", "maxtime = maximum time between tosses (default = 12.0 seconds)"},
+ {"rem", "damage = damage to do when an hitting something"},
+ {"rem", "upmin = minimum upward velocity (default = 200)"},
+ {"rem", "upmax = maximum upward velocity (default = 800)"},
+
+ //////////////////////////////
+ // sound_ambient
+ //////////////////////////////
+
+ {"classname", "sound_ambient"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"color", "1 0 1"},
+
+ {"rem", "sound - path to ambient sound (ie. ambience/sound.wav."},
+ {"rem", "fade - distance multiplier to make sounds fade in further away from source."},
+ {"rem", "1.0 is normal, 2.0 is twice as far."},
+ {"rem", "volume - 0 through 255. 255 is max."},
+
+ //////////////////////////////
+ // sound_ambient
+ //////////////////////////////
+
+ {"classname", "trigger_fog_value"},
+ {"color", "0 1 0"},
+
+ {"rem", "fog_value - the value for fog density 0 - 4. 0 is off, ie. r_drawfog 0"},
+
+ //////////////////////////////
+ // node_node
+ //////////////////////////////
+
+ {"classname", "node_node"},
+ {"color", "0.5 0.5 1"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"flag", "NODE_DOOR"},
+
+ {"rem", "number - the number of this node"},
+ {"rem", "link - the number of the node linked to (can be up to four link fields)"},
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Monsters
+ //
+ //////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ ////////////////////////////////////////
+ // Episode 1 monsters
+ ////////////////////////////////////////
+
+ {"classname", "monster_froginator"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A light and refreshing monster."},
+ {"rem", "One day I will read the spec and know what this"},
+ {"rem", "monster does."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_crox"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A realistic representation of your mother"},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_slaughterskeet"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_thunderskeet"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_venomvermin"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_tentaclor"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_sludgeminion"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"flag", "PATHFOLLOW"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_prisoner"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "gib him."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "func_prisoner_respawn"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "time - seconds until a new prisoner is spawned"},
+
+ {"classname", "monster_inmater"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-32 -32 -24 32 32 64"},
+ {"flag", "WANDER"},
+ {"flag", "PATHFOLLOW"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+ {"rem", "PATH_FOLLOW - begin following a monster path"},
+
+ {"classname", "monster_squid"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_trackattack"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Track turrets need to have a target"},
+ {"rem", "which is the path_corner_track at which"},
+ {"rem", "they will start."},
+ {"rem", "Spawn about 16 units below the track to"},
+
+ {"classname", "monster_trackdaddy"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Track turrets need to have a target"},
+ {"rem", "which is the path_corner_track at which"},
+ {"rem", "they will start."},
+
+ {"classname", "monster_lasergat"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "Track turrets need to have a target"},
+ {"rem", "which is the path_corner_track at which"},
+ {"rem", "they will start."},
+
+ {"classname", "monster_psyclaw"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big dog without a head and a"},
+ {"rem", "brain for a back. Cool, eh?"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_labworker"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "Lab worker. Your momma."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_battleboar"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A motorized, cybernetic pig, of course."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ //////////////////////////////
+ // path_corner_track
+ //
+ // path corners for tracked turrets only!
+ //////////////////////////////
+
+ {"classname", "path_corner_track"},
+ {"distance", "90.0"},
+ {"color", "0.5 0.3 0"},
+ {"size", "-8 -8 -8 8 8 8"},
+
+ ////////////////////////////////////////
+ // Episode 2 monsters
+ ////////////////////////////////////////
+
+ {"classname", "monster_skeleton"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "Where's he at? Ahh! He's in me!"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_spider"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-32 -32 -24 32 32 32"},
+ {"flag", "WANDER"},
+ {"rem", "Dumbass."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_tarantula"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "Dumbass."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_griffon"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_harpy"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_centurion"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_siren"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_ferryman"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_satyr"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-32 -32 -24 32 32 64"},
+ {"flag", "WANDER"},
+ {"rem", "This thing will beat you down."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_column"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-32 -32 -24 32 32 64"},
+ {"flag", "WANDER"},
+ {"rem", "Look at the tits on that statue!!"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ ////////////////////////////////////////
+ // Episode 3 monsters
+ ////////////////////////////////////////
+
+ {"classname", "monster_plague_rat"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"rem", "I broke you!"},
+ {"flag", "WANDER"},
+ {"rem", "I broke you!"},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_rotworm"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "I beat the dictionary out of your filthy mouth!"},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_buboid"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "Dumbass."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_priest"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_doombat"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_lycanthir"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_fletcher"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_dwarf"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_dragonegg"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_babydragon"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ ////////////////////////////////////////
+ // Episode 4 monsters
+ ////////////////////////////////////////
+
+ {"classname", "monster_gang1"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "Less than half a fucking man."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_gang2"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "You're fucking dumb! Suck it down."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_blackprisoner"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_whiteprisoner"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_femgang"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_rocketdude"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_chaingang"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "A big thing with a big beak."},
+ {"rem", "radius - wander radius"},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monster_labmonkey"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 32"},
+ {"flag", "WANDER"},
+ {"rem", "Lab monkey. This thing will crack your skull."},
+ {"rem", "Spawnflags:"},
+ {"rem", "WANDER - monster will wander around"},
+
+ {"classname", "monkey_message"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"rem", "Target this from the monkey switch to display current monkey state."},
+
+ //////////////////////////////////////////////////////////////////
+ // monster AI markers
+ //////////////////////////////////////////////////////////////////
+
+ {"classname", "monster_path_corner"},
+ {"distance", "90.0"},
+ {"color", "0.5 0.3 0"},
+ {"size", "-8 -8 -8 8 8 8"},
+ {"rem", "A path corner for a monster to travel along"},
+ {"rem" "target1 - target4: "},
+ {"rem", "Can have up to 4 targets for the monster"},
+ {"rem", "to travel to. If there is more than one target"},
+ {"rem", "the monster will randomly choose the next target"},
+ {"rem", "from those available."},
+ {"rem", "action1 - action4: "},
+ {"rem", "Use the action field to make a monster perform a"},
+ {"rem", "specific action at the path corner. For example"},
+ {"rem", "'action scoop' will make a sludge minion scoop"},
+ {"rem", "sludge at that path corner (other monsters will"},
+ {"rem", "ignore the scoop command. You can have multiple"},
+ {"rem", "actions on a path corner, for instance:"},
+ {"rem", " action1 scoop"},
+ {"rem", " action2 interrogate"},
+ {"rem", "Sludge minions reaching this path corner will scoop"},
+ {"rem", "while Inmaters will search out nearest prisoner"},
+
+
+ //////////////////////////////////////////////////////////////////
+ // decorations
+ //////////////////////////////////////////////////////////////////
+
+ {"classname", "deco_e1"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 0"},
+ {"flag", "DECO_EXPLODE"},
+ {"flag", "DECO_NO_EXPLODE"},
+ {"flag", "DECO_PUSHABLE"},
+ {"rem", "model - choose model # -- see list."},
+
+ {"classname", "deco_e2"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 0"},
+ {"flag", "DECO_EXPLODE"},
+ {"flag", "DECO_NO_EXPLODE"},
+ {"flag", "DECO_PUSHABLE"},
+ {"rem", "model - choose model # -- see list."},
+
+ {"classname", "deco_e3"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 0"},
+ {"flag", "DECO_EXPLODE"},
+ {"flag", "DECO_NO_EXPLODE"},
+ {"flag", "DECO_PUSHABLE"},
+ {"rem", "model - choose model # -- see list."},
+
+ {"classname", "deco_e4"},
+ {"color", "1.0 0.0 0.0"},
+ {"size", "-16 -16 -24 16 16 0"},
+ {"flag", "DECO_EXPLODE"},
+ {"flag", "DECO_NO_EXPLODE"},
+ {"flag", "DECO_PUSHABLE"},
+ {"rem", "model - choose model # -- see list."},
+
+ {NULL, NULL},
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/EditWnd.cpp b/q3radiant/EditWnd.cpp
new file mode 100755
index 0000000..e2dbd34
--- /dev/null
+++ b/q3radiant/EditWnd.cpp
@@ -0,0 +1,61 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// EditWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "EditWnd.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditWnd
+IMPLEMENT_DYNCREATE(CEditWnd, CWnd);
+
+CEditWnd::CEditWnd()
+{
+}
+
+CEditWnd::~CEditWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CEditWnd, CEdit)
+ //{{AFX_MSG_MAP(CEditWnd)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditWnd message handlers
+
+BOOL CEditWnd::PreCreateWindow(CREATESTRUCT& cs)
+{
+ cs.style = WS_CHILD | WS_VSCROLL | ES_AUTOHSCROLL | ES_MULTILINE | WS_VISIBLE;
+ cs.lpszClass = "EDIT";
+ return CEdit::PreCreateWindow(cs);
+}
diff --git a/q3radiant/EditWnd.h b/q3radiant/EditWnd.h
new file mode 100755
index 0000000..02f6532
--- /dev/null
+++ b/q3radiant/EditWnd.h
@@ -0,0 +1,71 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_EDITWND_H__279AAE22_78C5_11D1_B53C_00AA00A410FC__INCLUDED_)
+#define AFX_EDITWND_H__279AAE22_78C5_11D1_B53C_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// EditWnd.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CEditWnd window
+
+class CEditWnd : public CEdit
+{
+ DECLARE_DYNCREATE(CEditWnd);
+// Construction
+public:
+ CEditWnd();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CEditWnd)
+ protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CEditWnd();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CEditWnd)
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_EDITWND_H__279AAE22_78C5_11D1_B53C_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/EntityListDlg.cpp b/q3radiant/EntityListDlg.cpp
new file mode 100755
index 0000000..a2c2e66
--- /dev/null
+++ b/q3radiant/EntityListDlg.cpp
@@ -0,0 +1,152 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// EntityListDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "EntityListDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CEntityListDlg dialog
+
+
+CEntityListDlg::CEntityListDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CEntityListDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CEntityListDlg)
+ //}}AFX_DATA_INIT
+}
+
+
+void CEntityListDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CEntityListDlg)
+ DDX_Control(pDX, IDC_LIST_ENTITY, m_lstEntity);
+ DDX_Control(pDX, IDC_TREE_ENTITY, m_treeEntity);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CEntityListDlg, CDialog)
+ //{{AFX_MSG_MAP(CEntityListDlg)
+ ON_BN_CLICKED(IDSELECT, OnSelect)
+ ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_ENTITY, OnSelchangedTreeEntity)
+ ON_NOTIFY(NM_DBLCLK, IDC_TREE_ENTITY, OnDblclkTreeEntity)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CEntityListDlg message handlers
+
+void CEntityListDlg::OnSelect()
+{
+ HTREEITEM hItem = m_treeEntity.GetSelectedItem();
+ if (hItem)
+ {
+ entity_t* pEntity = reinterpret_cast<entity_t*>(m_treeEntity.GetItemData(hItem));
+ if (pEntity)
+ {
+ Select_Deselect();
+ Select_Brush (pEntity->brushes.onext);
+ }
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+BOOL CEntityListDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ CMapStringToPtr mapEntity;
+
+ HTREEITEM hParent = m_treeEntity.InsertItem(world_entity->eclass->name);
+ HTREEITEM hChild = m_treeEntity.InsertItem(world_entity->eclass->name, hParent);
+ m_treeEntity.SetItemData(hChild, reinterpret_cast<DWORD>(world_entity));
+
+ for (entity_t* pEntity=entities.next ; pEntity != &entities ; pEntity=pEntity->next)
+ {
+ hParent = NULL;
+ if (mapEntity.Lookup(pEntity->eclass->name, reinterpret_cast<void*&>(hParent)) == FALSE)
+ {
+ hParent = m_treeEntity.InsertItem(pEntity->eclass->name);
+ mapEntity.SetAt(pEntity->eclass->name, reinterpret_cast<void*>(hParent));
+ }
+ hChild = m_treeEntity.InsertItem(pEntity->eclass->name, hParent);
+ m_treeEntity.SetItemData(hChild, reinterpret_cast<DWORD>(pEntity));
+ }
+
+ CRect rct;
+ m_lstEntity.GetClientRect(rct);
+ m_lstEntity.InsertColumn(0, "Key", LVCFMT_LEFT, rct.Width() / 2);
+ m_lstEntity.InsertColumn(1, "Value", LVCFMT_LEFT, rct.Width() / 2);
+ m_lstEntity.DeleteColumn(2);
+ UpdateData(FALSE);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CEntityListDlg::OnSelchangedTreeEntity(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
+ HTREEITEM hItem = m_treeEntity.GetSelectedItem();
+ m_lstEntity.DeleteAllItems();
+ if (hItem)
+ {
+ CString strList;
+ entity_t* pEntity = reinterpret_cast<entity_t*>(m_treeEntity.GetItemData(hItem));
+ if (pEntity)
+ {
+ for (epair_t* pEpair = pEntity->epairs ; pEpair ; pEpair = pEpair->next)
+ {
+ if (strlen(pEpair->key) > 8)
+ strList.Format("%s\t%s", pEpair->key, pEpair->value);
+ else
+ strList.Format("%s\t\t%s", pEpair->key, pEpair->value);
+ int nParent = m_lstEntity.InsertItem(0, pEpair->key);
+ m_lstEntity.SetItem(nParent, 1, LVIF_TEXT, pEpair->value, 0, 0, 0, reinterpret_cast<DWORD>(pEntity));
+
+ }
+ }
+ }
+ *pResult = 0;
+}
+
+void CEntityListDlg::OnDblclkListInfo()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CEntityListDlg::OnDblclkTreeEntity(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ OnSelect();
+ *pResult = 0;
+}
diff --git a/q3radiant/EntityListDlg.h b/q3radiant/EntityListDlg.h
new file mode 100755
index 0000000..53c3534
--- /dev/null
+++ b/q3radiant/EntityListDlg.h
@@ -0,0 +1,72 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_ENTITYLISTDLG_H__C241B9A3_819F_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_ENTITYLISTDLG_H__C241B9A3_819F_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// EntityListDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CEntityListDlg dialog
+
+class CEntityListDlg : public CDialog
+{
+// Construction
+public:
+ CEntityListDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CEntityListDlg)
+ enum { IDD = IDD_DLG_ENTITYLIST };
+ CListCtrl m_lstEntity;
+ CTreeCtrl m_treeEntity;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CEntityListDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CEntityListDlg)
+ afx_msg void OnSelect();
+ virtual BOOL OnInitDialog();
+ afx_msg void OnSelchangedTreeEntity(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDblclkListInfo();
+ afx_msg void OnDblclkTreeEntity(NMHDR* pNMHDR, LRESULT* pResult);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ENTITYLISTDLG_H__C241B9A3_819F_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/EpairsWrapper.h b/q3radiant/EpairsWrapper.h
new file mode 100755
index 0000000..3de691f
--- /dev/null
+++ b/q3radiant/EpairsWrapper.h
@@ -0,0 +1,63 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:17:10 $
+// $Log: EpairsWrapper.h,v $
+// Revision 1.1.1.4 2000/01/18 00:17:10 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:41 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.1.1.3 1999/12/29 18:31:25 TBesset
+// Q3Radiant public version
+//
+// DESCRIPTION:
+// virtual class to allow plugin operations on entities epairs
+// this is the internal header for our implementation
+
+#ifndef _EPAIRSWRAPPER_H_
+#define _EPAIRSWRAPPER_H_
+
+class CEpairsWrapper : public IEpair
+{
+public:
+ int refCount;
+ entity_t *m_pEnt;
+ virtual void IncRef() { refCount++; }
+ virtual void DecRef() { refCount--; if (refCount <= 0) delete this; }
+ CEpairsWrapper() { refCount = 0; }
+ CEpairsWrapper( entity_t* ep ) { refCount = 0; m_pEnt = ep; }
+ virtual ~CEpairsWrapper() { }
+ virtual void GetVectorForKey( char* key, vec3_t vec );
+ virtual float FloatForKey( char *key );
+ virtual char* ValueForKey( char *key );
+ virtual void SetKeyValue( char *key, char *value );
+ virtual void GetEntityOrigin( vec3_t vec );
+ virtual void CalculateRotatedBounds( vec3_t mins, vec3_t maxs );
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/FNMATCH.CPP b/q3radiant/FNMATCH.CPP
new file mode 100755
index 0000000..f7679d5
--- /dev/null
+++ b/q3radiant/FNMATCH.CPP
@@ -0,0 +1,87 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include <stdlib.h>
+
+#define Reg1 register
+int match(char *mask, char *name)
+{
+ Reg1 unsigned char *m = (unsigned char *)mask, *n = (unsigned char *)name;
+ char *ma = mask, *na = name;
+ int wild = 0, q = 0;
+
+ while (1)
+ {
+ if (*m == '*')
+ {
+ while (*m == '*')
+ m++;
+ wild = 1;
+ ma = (char *)m;
+ na = (char *)n;
+ }
+
+ if (!*m)
+ {
+ if (!*n)
+ return 0;
+ for (m--; (m > (unsigned char *)mask) && (*m == '?'); m--)
+ ;
+ if ((*m == '*') && (m > (unsigned char *)mask) &&
+ (m[-1] != '\\'))
+ return 0;
+ if (!wild)
+ return 1;
+ m = (unsigned char *)ma;
+ n = (unsigned char *)++na;
+ }
+ else if (!*n)
+ {
+ while(*m == '*')
+ m++;
+ return (*m != 0);
+ }
+ if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
+ {
+ m++;
+ q = 1;
+ }
+ else
+ q = 0;
+
+ if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q))
+ {
+ if (!wild)
+ return 1;
+ m = (unsigned char *)ma;
+ n = (unsigned char *)++na;
+ }
+ else
+ {
+ if (*m)
+ m++;
+ if (*n)
+ n++;
+ }
+ }
+}
+
diff --git a/q3radiant/FNMATCH.H b/q3radiant/FNMATCH.H
new file mode 100755
index 0000000..b194e2f
--- /dev/null
+++ b/q3radiant/FNMATCH.H
@@ -0,0 +1,27 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef _FNMATCH_H
+#define _FNMATCH_H
+
+int match(char *mask, char *name);
+
+#endif /* fnmatch.h */
diff --git a/q3radiant/FindTextureDlg.cpp b/q3radiant/FindTextureDlg.cpp
new file mode 100755
index 0000000..030abde
--- /dev/null
+++ b/q3radiant/FindTextureDlg.cpp
@@ -0,0 +1,175 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// FindTextureDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "FindTextureDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CFindTextureDlg dialog
+
+CFindTextureDlg g_TexFindDlg;
+CFindTextureDlg& g_dlgFind = g_TexFindDlg;
+static bool g_bFindActive = true;
+
+void CFindTextureDlg::updateTextures(const char *p)
+{
+ if (isOpen())
+ {
+ if (g_bFindActive)
+ {
+ setFindStr(p);
+ }
+ else
+ {
+ setReplaceStr(p);
+ }
+ }
+}
+
+CFindTextureDlg::CFindTextureDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CFindTextureDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CFindTextureDlg)
+ m_bSelectedOnly = FALSE;
+ m_strFind = _T("");
+ m_strReplace = _T("");
+ m_bForce = FALSE;
+ m_bLive = TRUE;
+ //}}AFX_DATA_INIT
+}
+
+
+void CFindTextureDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CFindTextureDlg)
+ DDX_Check(pDX, IDC_CHECK_SELECTED, m_bSelectedOnly);
+ DDX_Text(pDX, IDC_EDIT_FIND, m_strFind);
+ DDX_Text(pDX, IDC_EDIT_REPLACE, m_strReplace);
+ DDX_Check(pDX, IDC_CHECK_FORCE, m_bForce);
+ DDX_Check(pDX, IDC_CHECK_LIVE, m_bLive);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CFindTextureDlg, CDialog)
+ //{{AFX_MSG_MAP(CFindTextureDlg)
+ ON_BN_CLICKED(ID_BTN_APPLY, OnBtnApply)
+ ON_EN_SETFOCUS(IDC_EDIT_FIND, OnSetfocusEditFind)
+ ON_EN_SETFOCUS(IDC_EDIT_REPLACE, OnSetfocusEditReplace)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void CFindTextureDlg::OnBtnApply()
+{
+ UpdateData(TRUE);
+ CRect rct;
+ GetWindowRect(rct);
+ SaveRegistryInfo("Radiant::TextureFindWindow", &rct, sizeof(rct));
+ FindReplaceTextures(m_strFind, m_strReplace, m_bSelectedOnly, m_bForce);
+}
+
+void CFindTextureDlg::OnOK()
+{
+ UpdateData(TRUE);
+ CRect rct;
+ GetWindowRect(rct);
+ SaveRegistryInfo("Radiant::TextureFindWindow", &rct, sizeof(rct));
+ FindReplaceTextures(m_strFind, m_strReplace, m_bSelectedOnly, m_bForce);
+ CDialog::OnOK();
+}
+
+void CFindTextureDlg::show()
+{
+ if (g_dlgFind.GetSafeHwnd() == NULL || IsWindow(g_dlgFind.GetSafeHwnd()) == FALSE)
+ {
+ g_dlgFind.Create(IDD_DIALOG_FINDREPLACE);
+ g_dlgFind.ShowWindow(SW_SHOW);
+ }
+ else
+ {
+ g_dlgFind.ShowWindow(SW_SHOW);
+ }
+ CRect rct;
+ LONG lSize = sizeof(rct);
+ if (LoadRegistryInfo("Radiant::TextureFindWindow", &rct, &lSize))
+ g_dlgFind.SetWindowPos(NULL, rct.left, rct.top, 0,0, SWP_NOSIZE | SWP_SHOWWINDOW);
+}
+
+
+bool CFindTextureDlg::isOpen()
+{
+ return (g_dlgFind.GetSafeHwnd() == NULL || ::IsWindowVisible(g_dlgFind.GetSafeHwnd()) == FALSE) ? false : true;
+}
+
+void CFindTextureDlg::setFindStr(const char * p)
+{
+ g_dlgFind.UpdateData(TRUE);
+ if (g_dlgFind.m_bLive)
+ {
+ g_dlgFind.m_strFind = p;
+ g_dlgFind.UpdateData(FALSE);
+ }
+}
+
+void CFindTextureDlg::setReplaceStr(const char * p)
+{
+ g_dlgFind.UpdateData(TRUE);
+ if (g_dlgFind.m_bLive)
+ {
+ g_dlgFind.m_strReplace = p;
+ g_dlgFind.UpdateData(FALSE);
+ }
+}
+
+
+void CFindTextureDlg::OnCancel()
+{
+ CRect rct;
+ GetWindowRect(rct);
+ SaveRegistryInfo("Radiant::TextureFindWindow", &rct, sizeof(rct));
+ CDialog::OnCancel();
+}
+
+BOOL CFindTextureDlg::DestroyWindow()
+{
+ return CDialog::DestroyWindow();
+}
+
+void CFindTextureDlg::OnSetfocusEditFind()
+{
+ g_bFindActive = true;
+}
+
+void CFindTextureDlg::OnSetfocusEditReplace()
+{
+ g_bFindActive = false;
+}
diff --git a/q3radiant/FindTextureDlg.h b/q3radiant/FindTextureDlg.h
new file mode 100755
index 0000000..c69c95d
--- /dev/null
+++ b/q3radiant/FindTextureDlg.h
@@ -0,0 +1,83 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_FINDTEXTUREDLG_H__34B75D32_9F3A_11D1_B570_00AA00A410FC__INCLUDED_)
+#define AFX_FINDTEXTUREDLG_H__34B75D32_9F3A_11D1_B570_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// FindTextureDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CFindTextureDlg dialog
+
+class CFindTextureDlg : public CDialog
+{
+// Construction
+public:
+ static void setReplaceStr(const char* p);
+ static void setFindStr(const char* p);
+ static bool isOpen();
+ static void show();
+ static void updateTextures(const char* p);
+ CFindTextureDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CFindTextureDlg)
+ enum { IDD = IDD_DIALOG_FINDREPLACE };
+ BOOL m_bSelectedOnly;
+ CString m_strFind;
+ CString m_strReplace;
+ BOOL m_bForce;
+ BOOL m_bLive;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CFindTextureDlg)
+ public:
+ virtual BOOL DestroyWindow();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CFindTextureDlg)
+ afx_msg void OnBtnApply();
+ virtual void OnOK();
+ virtual void OnCancel();
+ afx_msg void OnSetfocusEditFind();
+ afx_msg void OnSetfocusEditReplace();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_FINDTEXTUREDLG_H__34B75D32_9F3A_11D1_B570_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/GLINGR.H b/q3radiant/GLINGR.H
new file mode 100755
index 0000000..5ce0294
--- /dev/null
+++ b/q3radiant/GLINGR.H
@@ -0,0 +1,97 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// This .h file contains constants, typedefs, etc. for Intergraph
+// extensions to OpenGL. These extensions are:
+//
+// Multiple Palette Extension
+// Texture Object Extension
+
+#define GL_INGR_multiple_palette 1
+#define GL_EXT_texture_object 1
+
+
+// New constants and typedefs for the Multiple Palette Extension
+#define GL_PALETTE_INGR 0x80c0
+#define GL_MAX_PALETTES_INGR 0x80c1
+#define GL_MAX_PALETTE_ENTRIES_INGR 0x80c2
+#define GL_CURRENT_PALETTE_INGR 0x80c3
+#define GL_PALETTE_WRITEMASK_INGR 0x80c4
+#define GL_CURRENT_RASTER_PALETTE_INGR 0x80c5
+#define GL_PALETTE_CLEAR_VALUE_INGR 0x80c6
+
+// Function prototypes for the Multiple Palette Extension routines
+typedef void (APIENTRY *PALETTEFUNCPTR)(GLuint);
+typedef void (APIENTRY *PALETTEMASKFUNCPTR)(GLboolean);
+typedef void (APIENTRY *WGLLOADPALETTEFUNCPTR)(GLuint, GLsizei, GLuint *);
+typedef void (APIENTRY *CLEARPALETTEFUNCPTR)(GLuint);
+
+
+// New Constants and typedefs for the Texture Object Extension
+#define GL_TEXTURE_PRIORITY_EXT 0x8066
+#define GL_TEXTURE_RESIDENT_EXT 0x8067
+#define GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define GL_TEXTURE_2D_BINDING_EXT 0x8069
+
+// Function prototypes for the Texture Object Extension routines
+typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *,
+ const GLboolean *);
+typedef void (APIENTRY *BINDTEXFUNCPTR)(GLenum, GLuint);
+typedef void (APIENTRY *DELTEXFUNCPTR)(GLsizei, const GLuint *);
+typedef void (APIENTRY *GENTEXFUNCPTR)(GLsizei, GLuint *);
+typedef GLboolean (APIENTRY *ISTEXFUNCPTR)(GLuint);
+typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
+ const GLclampf *);
+
+
+/* OpenGL ExtEscape escape function constants */
+#ifndef OPENGL_GETINFO
+#define OPENGL_GETINFO 4353 /* for OpenGL ExtEscape */
+#endif
+
+// OPENGL_GETINFO ExtEscape sub-escape numbers. They are defined by
+// Microsoft.
+
+#ifndef OPENGL_GETINFO_DRVNAME
+
+#define OPENGL_GETINFO_DRVNAME 0
+
+
+// Input structure for OPENGL_GETINFO ExtEscape.
+
+typedef struct _OPENGLGETINFO
+{
+ ULONG ulSubEsc;
+} OPENGLGETINFO, *POPENGLGETINFO;
+
+
+// Output structure for OPENGL_GETINFO_DRVNAME ExtEscape.
+
+typedef struct _GLDRVNAMERET
+{
+ ULONG ulVersion; // must be 1 for this version
+ ULONG ulDriverVersion; // driver specific version number
+ WCHAR awch[MAX_PATH+1];
+} GLDRVNAMERET, *PGLDRVNAMERET;
+
+#endif
+
+
diff --git a/q3radiant/GLInterface.cpp b/q3radiant/GLInterface.cpp
new file mode 100755
index 0000000..71c6ff3
--- /dev/null
+++ b/q3radiant/GLInterface.cpp
@@ -0,0 +1,93 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4.2.1 $
+// $Author: ttimo $
+// $Date: 2000/02/04 22:59:34 $
+// $log$
+// Revision 1.1.1.3 1999/12/29 18:31:26 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:45 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.4.1 1999/11/03 20:37:59 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+// Revision 1.1.2.1 1999/10/27 08:34:26 Timo & Christine
+// preview version of the texture tools plugin is ready
+// ( TexTool.dll plugin is in Q3Plugin module )
+// plugins can draw in their own window using Radiant's qgl bindings
+//
+//
+// DESCRIPTION:
+// Quick interface hack for selected face interface
+// this one really needs more work, but I'm in a hurry with TexTool
+
+#include "stdafx.h"
+
+// stores objects that want to be hooked into drawing in the XY window
+//++timo TODO: add support for camera view, Z view ... (texture view?)
+CPtrArray l_GLWindows;
+
+int WINAPI QERApp_ISelectedFace_GetTextureNumber()
+{
+ if (g_ptrSelectedFaces.GetSize() > 0)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ return selFace->d_texture->texture_number;
+ }
+ //++timo hu ? find the appropriate gl bind number
+ return 0;
+}
+
+void WINAPI QERApp_HookXYGLWindow(IGLWindow* pGLW)
+{
+ l_GLWindows.Add( pGLW );
+ pGLW->IncRef();
+}
+
+void WINAPI QERApp_UnHookGLWindow(IGLWindow* pGLW)
+{
+ for( int i = 0; i < l_GLWindows.GetSize(); i++ )
+ {
+ if (l_GLWindows.GetAt(i) == pGLW)
+ {
+ l_GLWindows.RemoveAt(i);
+ pGLW->DecRef();
+ return;
+ }
+ }
+#ifdef _DEBUG
+ Sys_Printf("ERROR: IGLWindow* not found in QERApp_UnHookGLWindow\n");
+#endif
+}
+
+void DrawPluginEntities( VIEWTYPE vt )
+{
+ for(int i = 0; i<l_GLWindows.GetSize(); i++ )
+ static_cast<IGLWindow*>(l_GLWindows.GetAt(i))->Draw( vt );
+} \ No newline at end of file
diff --git a/q3radiant/GLW_WIN.H b/q3radiant/GLW_WIN.H
new file mode 100755
index 0000000..d8b1c89
--- /dev/null
+++ b/q3radiant/GLW_WIN.H
@@ -0,0 +1,49 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef _WIN32
+# error You should not be including this file on this platform
+#endif
+
+#ifndef __GLW_WIN_H__
+#define __GLW_WIN_H__
+
+typedef struct
+{
+ HINSTANCE hInstance;
+ void *wndproc;
+
+ HDC hDC; // handle to device context
+ HWND hWnd; // handle to window
+ HGLRC hGLRC; // handle to GL rendering context
+
+ HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
+
+ qboolean minidriver;
+ qboolean allowdisplaydepthchange;
+ qboolean mcd_accelerated;
+
+ FILE *log_fp;
+} glwstate_t;
+
+extern glwstate_t glw_state;
+
+#endif
diff --git a/q3radiant/GroupBar.cpp b/q3radiant/GroupBar.cpp
new file mode 100755
index 0000000..09d01c6
--- /dev/null
+++ b/q3radiant/GroupBar.cpp
@@ -0,0 +1,84 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// GroupBar.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "GroupBar.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CGroupBar dialog
+
+
+CGroupBar::CGroupBar(CWnd* pParent /*=NULL*/)
+ : CDialogBar()
+{
+ //{{AFX_DATA_INIT(CGroupBar)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CGroupBar::DoDataExchange(CDataExchange* pDX)
+{
+ CDialogBar::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CGroupBar)
+ DDX_Control(pDX, IDC_COMBO_GROUPS, m_wndGroupList);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CGroupBar, CDialogBar)
+ //{{AFX_MSG_MAP(CGroupBar)
+ ON_BN_CLICKED(IDC_BTN_ADDGROUP, OnBtnAddgroup)
+ ON_BN_CLICKED(IDC_BTN_LISTGROUPS, OnBtnListgroups)
+ ON_BN_CLICKED(IDC_BTN_REMOVEGROUP, OnBtnRemovegroup)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CGroupBar message handlers
+
+void CGroupBar::OnBtnAddgroup()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CGroupBar::OnBtnListgroups()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CGroupBar::OnBtnRemovegroup()
+{
+ // TODO: Add your control notification handler code here
+
+}
diff --git a/q3radiant/GroupBar.h b/q3radiant/GroupBar.h
new file mode 100755
index 0000000..8db20f8
--- /dev/null
+++ b/q3radiant/GroupBar.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_GROUPBAR_H__926379A9_F46B_4E81_AD23_71BDDF55BDB3__INCLUDED_)
+#define AFX_GROUPBAR_H__926379A9_F46B_4E81_AD23_71BDDF55BDB3__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// GroupBar.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CGroupBar dialog
+
+class CGroupBar : public CDialogBar
+{
+// Construction
+public:
+ CGroupBar(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CGroupBar)
+ enum { IDD = IDD_GROUPBAR };
+ CComboBox m_wndGroupList;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CGroupBar)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CGroupBar)
+ afx_msg void OnBtnAddgroup();
+ afx_msg void OnBtnListgroups();
+ afx_msg void OnBtnRemovegroup();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_GROUPBAR_H__926379A9_F46B_4E81_AD23_71BDDF55BDB3__INCLUDED_)
diff --git a/q3radiant/GroupDlg.cpp b/q3radiant/GroupDlg.cpp
new file mode 100755
index 0000000..f0d4826
--- /dev/null
+++ b/q3radiant/GroupDlg.cpp
@@ -0,0 +1,655 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// GroupDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "GroupDlg.h"
+#include "NameDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define IMG_PATCH 0
+#define IMG_BRUSH 1
+#define IMG_GROUP 2
+#define IMG_ENTITY 3
+#define IMG_ENTITYGROUP 4
+#define IMG_MODEL 5
+#define IMG_SCRIPT 6
+
+// misc group support
+#define MAX_GROUPS 4096
+#define GROUP_DELIMETER '@'
+#define GROUPNAME "QER_Group_%i"
+
+CGroupDlg g_wndGroup;
+CGroupDlg *g_pGroupDlg = &g_wndGroup;
+
+// group_t are loaded / saved through "group_info" entities
+// they hold epairs for group settings and additionnal access info (tree nodes)
+group_t *g_pGroups = NULL;
+
+void Group_Add(entity_t *e)
+{
+ group_t *g = (group_t*)qmalloc(sizeof(group_t));
+ g->epairs = e->epairs;
+ g->next = NULL;
+ e->epairs = NULL;
+ // create a new group node
+ HTREEITEM hItem = g_wndGroup.m_wndTree.GetSelectedItem();
+ TVINSERTSTRUCT tvInsert;
+ memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
+ tvInsert.item.iImage = IMG_GROUP;
+ tvInsert.item.iSelectedImage = tvInsert.item.iImage;
+ //++timo wasat?
+ // tvInsert.hParent = (hItem) ? hItem : m_hWorld;
+ tvInsert.hParent = g_wndGroup.m_hWorld;
+ tvInsert.hInsertAfter = NULL;
+ tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ char *pipo = ValueForKey(e->epairs, "group");
+ tvInsert.item.pszText = _T(ValueForKey(g->epairs, "group"));
+ g->itemOwner = g_wndGroup.m_wndTree.InsertItem(&tvInsert);
+ g->next = g_pGroups;
+ g_pGroups = g;
+}
+
+group_t* Group_Alloc(char *name)
+{
+ group_t *g = (group_t*)qmalloc(sizeof(group_t));
+ SetKeyValue( g->epairs, "group", name );
+ return g;
+}
+
+group_t* Group_ForName(const char * name)
+{
+ group_t *g = g_pGroups;
+ while (g != NULL)
+ {
+ if (strcmp( ValueForKey(g->epairs,"group"), name ) == 0)
+ break;
+ g = g->next;
+ }
+ return g;
+}
+
+void Group_AddToItem(brush_t *b, HTREEITEM item)
+{
+ char cBuff[1024];
+ int nImage = IMG_BRUSH;
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ const char *pName = NULL;
+ const char *pNamed = Brush_GetKeyValue(b, "name");
+
+ if (!b->owner || (b->owner == world_entity))
+ {
+ if (b->patchBrush)
+ {
+ pName = "Generic Patch";
+ nImage = IMG_PATCH;
+ }
+ else
+ {
+ pName = "Generic Brush";
+ nImage = IMG_BRUSH;
+ }
+ }
+ else
+ {
+ pName = b->owner->eclass->name;
+ if (b->owner->eclass->fixedsize)
+ {
+ nImage = IMG_ENTITY;
+ }
+ else
+ {
+ nImage = IMG_ENTITYGROUP;
+ }
+ }
+
+ strcpy(cBuff, pName);
+
+ TVINSERTSTRUCT tvInsert;
+ memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
+ tvInsert.item.iImage = (b->patchBrush) ? IMG_PATCH : IMG_BRUSH;
+ tvInsert.item.iSelectedImage = tvInsert.item.iImage;
+ tvInsert.hParent = item;
+ tvInsert.hInsertAfter = NULL;
+ tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvInsert.item.pszText = cBuff;
+ HTREEITEM itemNew = g_pGroupDlg->m_wndTree.InsertItem(&tvInsert);
+ g_pGroupDlg->m_wndTree.SetItemData(itemNew, reinterpret_cast<DWORD>(b));
+ b->itemOwner = itemNew;
+ g_pGroupDlg->m_wndTree.RedrawWindow();
+
+}
+
+void Group_RemoveBrush(brush_t *b)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ if (b->itemOwner)
+ {
+ g_pGroupDlg->m_wndTree.DeleteItem(b->itemOwner);
+ b->itemOwner = NULL;
+ g_pGroupDlg->m_wndTree.RedrawWindow();
+ }
+ DeleteKey(b->epairs, "group");
+}
+
+void Group_AddToWorld(brush_t *b)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ HTREEITEM itemParent = g_pGroupDlg->m_wndTree.GetRootItem();
+ Group_AddToItem(b, itemParent);
+}
+
+void Group_AddToProperGroup(brush_t *b)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ // NOTE: we do a local copy of the "group" key because it gets erased by Group_RemoveBrush
+ const char *pGroup = Brush_GetKeyValue(b, "group");
+ // remove the entry in the tree if there's one
+ if (b->itemOwner)
+ {
+ g_pGroupDlg->m_wndTree.DeleteItem(b->itemOwner);
+ b->itemOwner = NULL;
+ g_pGroupDlg->m_wndTree.RedrawWindow();
+ }
+
+ if (*pGroup != 0)
+ {
+ // find the item
+ group_t *g = Group_ForName(pGroup);
+ if (g)
+ Group_AddToItem(b, g->itemOwner);
+#ifdef _DEBUG
+ else
+ Sys_Printf("WARNING: unexpected Group_ForName not found in Group_AddToProperGroup\n");
+#endif
+ }
+ else
+ {
+ Group_AddToWorld(b);
+ }
+}
+
+void Group_AddToSelected(brush_t *b)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ HTREEITEM hItem = g_pGroupDlg->m_wndTree.GetSelectedItem();
+ if (hItem == NULL)
+ {
+ hItem = g_pGroupDlg->m_wndTree.GetRootItem();
+ }
+ Group_AddToItem(b, hItem);
+}
+
+void Group_Save(FILE *f)
+{
+ group_t *g = g_pGroups;
+ while (g)
+ {
+ fprintf(f,"{\n\"classname\" \"group_info\"\n\"group\" \"%s\"\n}\n", ValueForKey( g->epairs, "group" ));
+ g = g->next;
+ }
+}
+
+void Group_Init()
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ // start by cleaning everything
+ // clean the groups
+ //++timo FIXME: we leak, delete the groups on the way (I don't have time to do it now)
+#ifdef _DEBUG
+ Sys_Printf("TODO: fix leak in Group_Init\n");
+#endif
+ group_t *g = g_pGroups;
+ while (g)
+ {
+ epair_t *ep,*enext;
+ for (ep = g->epairs ; ep ; ep=enext )
+ {
+ enext = ep->next;
+ free (ep->key);
+ free (ep->value);
+ free (ep);
+ }
+ g = g->next;
+ }
+ g_pGroups = NULL;
+ g_wndGroup.m_wndTree.DeleteAllItems();
+ TVINSERTSTRUCT tvInsert;
+ memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
+ tvInsert.hParent = NULL;
+ tvInsert.hInsertAfter = NULL;
+ tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvInsert.item.pszText = _T("World");
+ tvInsert.item.iImage = IMG_GROUP;
+ tvInsert.item.iSelectedImage = IMG_GROUP;
+ HTREEITEM hWorld = g_wndGroup.m_wndTree.InsertItem(&tvInsert);
+ // walk through all the brushes, remove the itemOwner key and add them back where they belong
+ brush_t *b;
+ for (b = active_brushes.next; b != &active_brushes; b = b->next)
+ {
+ b->itemOwner = NULL;
+ Group_AddToProperGroup(b);
+ }
+ for (b = selected_brushes.next ; b != &selected_brushes ; b = b->next)
+ {
+ b->itemOwner = NULL;
+ Group_AddToProperGroup(b);
+ }
+}
+
+// scan through world_entity for groups in this map?
+// we use GROUPNAME "QER_group_%i" to look for existing groups and their naming
+//++timo FIXME: is this actually needed for anything?
+void Group_GetListFromWorld(CStringArray *pArray)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+
+ if (world_entity == NULL)
+ {
+ return;
+ }
+
+ pArray->RemoveAll();
+ char cBuff[1024];
+ for (int i =0; i < MAX_GROUPS; i++)
+ {
+ sprintf(cBuff, GROUPNAME, i);
+ char *pGroup = ValueForKey(world_entity, cBuff);
+ if (pGroup && strlen(pGroup) > 0)
+ {
+ pArray->Add(pGroup);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+void Group_RemoveListFromWorld()
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ CStringArray array;
+ Group_GetListFromWorld(&array);
+ int nCount = array.GetSize();
+ for (int i = 0; i < nCount; i++)
+ {
+ DeleteKey(world_entity, array.GetAt(i));
+ }
+}
+
+/*
+void Group_SetListToWorld(CStringArray *pArray)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ char cBuff[1024];
+ Group_RemoveListFromWorld();
+ int nCount = pArray->GetSize();
+ for (int i = 0; i < nCount; i++)
+ {
+ sprintf(cBuff, GROUPNAME, i);
+ SetKeyValue(world_entity, cBuff, pArray->GetAt(i));
+ }
+}
+*/
+
+int CountChar(const char *p, char c)
+{
+ int nCount = 0;
+ int nLen = strlen(p)-1;
+ while (nLen-- >= 0)
+ {
+ if (p[nLen] == c)
+ {
+ nCount++;
+ }
+ }
+ return nCount;
+}
+
+/*
+// this is not very efficient but should get the job done
+// as our trees should never be too big
+void Group_BuildTree(CTreeCtrl *pTree)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ CStringArray array;
+ int i;
+ CString strTemp;
+ CString strRight;
+
+ //++timo WARNING: this is very dangerous! delete all tree items, without checking the brushes
+ pTree->DeleteAllItems();
+ TVINSERTSTRUCT tvInsert;
+ memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
+ tvInsert.hParent = NULL;
+ tvInsert.hInsertAfter = NULL;
+ tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvInsert.item.pszText = _T("World");
+ tvInsert.item.iImage = IMG_GROUP;
+ tvInsert.item.iSelectedImage = IMG_GROUP;
+ HTREEITEM hWorld = pTree->InsertItem(&tvInsert);
+
+ Group_GetListFromWorld(&array);
+
+ // groups use @ to delimit levels, the number of @ signs
+ // start with ROOT item
+ // nothing is a peer with world, it is ancestor to everything
+ // expects things in order so first entry should be a 2nd level item
+ HTREEITEM itemParent = pTree->GetRootItem();
+ HTREEITEM itemLast = itemParent;
+ int nCount = array.GetSize();
+ int nLastLevel = 1;
+ for (i = 0; i < nCount; i++)
+ {
+ strTemp = array.GetAt(i);
+ int nLevel = CountChar(strTemp, GROUP_DELIMETER);
+ if (nLevel < nLastLevel)
+ {
+ int nLevelsUp = nLastLevel - nLevel;
+ while (nLevelsUp-- > 0)
+ {
+ itemParent = pTree->GetParentItem(itemParent);
+ }
+ }
+ else if (nLevel > nLastLevel)
+ {
+ itemParent = itemLast;
+ }
+ nLastLevel = nLevel;
+ char *pLast = strrchr(strTemp, GROUP_DELIMETER);
+ pLast++;
+ itemLast = pTree->InsertItem(pLast, itemParent);
+ }
+}
+*/
+
+void DecomposeSiblingList(const char *p, CStringArray *pArray, CTreeCtrl *pTree, HTREEITEM itemChild)
+{
+ CString str = p;
+ str += GROUP_DELIMETER;
+ while (itemChild)
+ {
+ CString strAdd = str;
+ strAdd += pTree->GetItemText(itemChild);
+ // do not want to add brushes or things, just groups
+ if (pTree->GetItemData(itemChild) == 0)
+ {
+ pArray->Add(strAdd);
+ }
+ if (pTree->ItemHasChildren(itemChild))
+ {
+ HTREEITEM itemOffspring = pTree->GetChildItem(itemChild);
+ DecomposeSiblingList(strAdd, pArray, pTree, itemOffspring);
+ }
+ itemChild = pTree->GetNextSiblingItem(itemChild);
+ }
+}
+
+/*
+void Group_DecomposeTree(CTreeCtrl *pTree)
+{
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ return;
+ }
+ CStringArray array;
+ HTREEITEM itemParent = pTree->GetRootItem();
+ if (pTree->ItemHasChildren(itemParent))
+ {
+ HTREEITEM itemChild = pTree->GetChildItem(itemParent);
+ DecomposeSiblingList(pTree->GetItemText(itemParent), &array, pTree, itemChild);
+ }
+ Group_SetListToWorld(&array);
+}
+*/
+
+/////////////////////////////////////////////////////////////////////////////
+// CGroupDlg dialog
+
+
+CGroupDlg::CGroupDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CGroupDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CGroupDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CGroupDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CGroupDlg)
+ DDX_Control(pDX, IDC_TREE_GROUP, m_wndTree);
+ DDX_Control(pDX, IDC_BTN_EDIT, m_wndEdit);
+ DDX_Control(pDX, IDC_BTN_DEL, m_wndDel);
+ DDX_Control(pDX, IDC_BTN_ADD, m_wndAdd);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CGroupDlg, CDialog)
+ //{{AFX_MSG_MAP(CGroupDlg)
+ ON_WM_SIZE()
+ ON_BN_CLICKED(IDC_BTN_ADD, OnBtnAdd)
+ ON_BN_CLICKED(IDC_BTN_DEL, OnBtnDel)
+ ON_BN_CLICKED(IDC_BTN_EDIT, OnBtnEdit)
+ ON_NOTIFY(NM_RCLICK, IDC_TREE_GROUP, OnRclickTreeGroup)
+ ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE_GROUP, OnEndlabeleditTreeGroup)
+ ON_NOTIFY(NM_CLICK, IDC_TREE_GROUP, OnClickTreeGroup)
+ ON_NOTIFY(TVN_SETDISPINFO, IDC_TREE_GROUP, OnSetdispinfoTreeGroup)
+ ON_NOTIFY(TVN_BEGINDRAG, IDC_TREE_GROUP, OnBegindragTreeGroup)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CGroupDlg message handlers
+
+void CGroupDlg::OnSize(UINT nType, int cx, int cy)
+{
+ CDialog::OnSize(nType, cx, cy);
+ CRect rct;
+ GetClientRect(rct);
+
+ if ( m_wndAdd.GetSafeHwnd())
+ {
+ //all borders at 4, spacing at 6
+ CRect rctButton;
+ m_wndAdd.GetWindowRect(rctButton);
+ int nWidth = rctButton.Width();
+ int nHeight = rctButton.Height();
+
+ int nTop = rct.Height() - nHeight - 4;
+
+ m_wndAdd.SetWindowPos(NULL, 4, nTop, 0, 0, SWP_NOSIZE);
+ m_wndEdit.SetWindowPos(NULL, 8 + nWidth , nTop, 0, 0, SWP_NOSIZE);
+ m_wndDel.SetWindowPos(NULL, 12 + (nWidth * 2), nTop, 0, 0, SWP_NOSIZE);
+ rct.bottom = nTop;
+ m_wndTree.SetWindowPos(NULL, rct.left + 4, rct.top + 4, rct.Width() - 8, rct.Height() - 8, SWP_SHOWWINDOW);
+ }
+}
+
+BOOL CGroupDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ m_imgList.Create(IDB_BITMAP_GROUPS, 16, 0, ILC_COLOR);
+ m_wndTree.SetImageList(&m_imgList, TVSIL_NORMAL);
+ InitGroups();
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CGroupDlg::InitGroups()
+{
+ Group_Init();
+}
+
+// add a new group, put all selected brushes into the group
+void CGroupDlg::OnBtnAdd()
+{
+ CNameDlg dlg("New Group", this);
+ if (dlg.DoModal() == IDOK)
+ {
+ // create a new group node
+ HTREEITEM hItem = m_wndTree.GetSelectedItem();
+ TVINSERTSTRUCT tvInsert;
+ memset(&tvInsert, 0, sizeof(TVINSERTSTRUCT));
+ tvInsert.item.iImage = IMG_GROUP;
+ tvInsert.item.iSelectedImage = tvInsert.item.iImage;
+ //++timo wasat?
+ // tvInsert.hParent = (hItem) ? hItem : m_hWorld;
+ tvInsert.hParent = m_hWorld;
+ tvInsert.hInsertAfter = NULL;
+ tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvInsert.item.pszText = _T(dlg.m_strName.GetBuffer(0));
+ // create a new group
+ group_t *g = Group_Alloc( dlg.m_strName.GetBuffer(0) );
+ g->itemOwner = m_wndTree.InsertItem(&tvInsert);
+ g->next = g_pGroups;
+ g_pGroups = g;
+ // now add the selected brushes
+ // NOTE: it would be much faster to give the group_t for adding
+ // but Select_AddToGroup is the standard way for all other cases
+ Select_AddToGroup( dlg.m_strName.GetBuffer(0) );
+ }
+}
+
+void CGroupDlg::OnBtnDel()
+{
+}
+
+void CGroupDlg::OnBtnEdit()
+{
+}
+
+BOOL CGroupDlg::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
+{
+ return CDialog::OnChildNotify(message, wParam, lParam, pLResult);
+}
+
+BOOL CGroupDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
+{
+ return CDialog::OnNotify(wParam, lParam, pResult);
+}
+
+void CGroupDlg::OnRclickTreeGroup(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+}
+
+void CGroupDlg::OnEndlabeleditTreeGroup(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
+ const char *pText = pTVDispInfo->item.pszText;
+ if (pText && strlen(pText) > 0)
+ {
+ HTREEITEM item = pTVDispInfo->item.hItem;
+ if (m_wndTree.GetRootItem() != item)
+ {
+ m_wndTree.SetItemText(item, pText);
+ if (pTVDispInfo->item.iImage != IMG_GROUP)
+ {
+ // if it is an entity
+ }
+ }
+ else
+ {
+ Sys_Printf("Cannot rename the world\n");
+ }
+ }
+ m_wndTree.RedrawWindow();
+ *pResult = 0;
+}
+
+void CGroupDlg::OnClickTreeGroup(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+}
+
+void CGroupDlg::OnSetdispinfoTreeGroup(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+}
+
+void CGroupDlg::OnCancel()
+{
+ TreeView_EndEditLabelNow(m_wndTree.GetSafeHwnd(), TRUE);
+}
+
+void CGroupDlg::OnOK()
+{
+ TreeView_EndEditLabelNow(m_wndTree.GetSafeHwnd(), FALSE);
+}
+
+void CGroupDlg::OnBegindragTreeGroup(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+}
diff --git a/q3radiant/GroupDlg.h b/q3radiant/GroupDlg.h
new file mode 100755
index 0000000..55672a0
--- /dev/null
+++ b/q3radiant/GroupDlg.h
@@ -0,0 +1,90 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_GROUPDLG_H__92368487_9E05_454E_A66F_23A9A94A753B__INCLUDED_)
+#define AFX_GROUPDLG_H__92368487_9E05_454E_A66F_23A9A94A753B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// GroupDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CGroupDlg dialog
+
+class CGroupDlg : public CDialog
+{
+ CImageList m_imgList;
+// Construction
+public:
+ virtual void OnOK();
+ virtual void OnCancel();
+ void InitGroups();
+ CGroupDlg(CWnd* pParent = NULL); // standard constructor
+
+ HTREEITEM m_hWorld;
+
+// Dialog Data
+ //{{AFX_DATA(CGroupDlg)
+ enum { IDD = IDD_DLG_GROUP };
+ CTreeCtrl m_wndTree;
+ CButton m_wndEdit;
+ CButton m_wndDel;
+ CButton m_wndAdd;
+ //}}AFX_DATA
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CGroupDlg)
+ public:
+ virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult);
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CGroupDlg)
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ virtual BOOL OnInitDialog();
+ afx_msg void OnBtnAdd();
+ afx_msg void OnBtnDel();
+ afx_msg void OnBtnEdit();
+ afx_msg void OnRclickTreeGroup(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnEndlabeleditTreeGroup(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnClickTreeGroup(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnSetdispinfoTreeGroup(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnBegindragTreeGroup(NMHDR* pNMHDR, LRESULT* pResult);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+extern CGroupDlg *g_pGroupDlg;
+
+
+#endif // !defined(AFX_GROUPDLG_H__92368487_9E05_454E_A66F_23A9A94A753B__INCLUDED_)
diff --git a/q3radiant/IBSPFrontend.h b/q3radiant/IBSPFrontend.h
new file mode 100755
index 0000000..7aa4e01
--- /dev/null
+++ b/q3radiant/IBSPFrontend.h
@@ -0,0 +1,101 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.3 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:43:59 $
+// $Log: IBSPFrontend.h,v $
+// Revision 1.3 2000/01/18 00:43:59 ttimo
+// RC
+//
+// Revision 1.2 2000/01/13 00:46:41 ttimo
+// Merged in patches in / out
+//
+// Revision 1.1.1.1.2.1 2000/01/13 00:15:41 ttimo
+// beta of patches in / out - tested with GenSurf
+//
+// Revision 1.1.1.1 2000/01/07 17:17:27 ttimo
+// initial import of Q3Radiant module
+//
+// Revision 1.2 2000/01/07 16:40:09 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.2.4 2000/01/07 00:16:26 TBesset
+// frontend ready for public version
+//
+// Revision 1.1.2.3 2000/01/04 00:26:58 TBesset
+// added a LoadPointFile in BSP frontend
+//
+// Revision 1.1.2.2 1999/12/31 19:43:20 TBesset
+// no message
+//
+// Revision 1.1.2.1 1999/12/29 16:49:39 TBesset
+// adding IBSPFrontend to the repository
+//
+//
+// DESCRIPTION:
+// interface for BSP frontends plugins
+//
+
+// DONE: - change BSP menu to Q3Build menu ?
+// DONE: - detect when Q3Build dies ?
+// DELAYED: - hotkeys !
+// SUCCESS: - try again getting feedback from Q3Build
+
+#ifndef __IBSPFRONTEND_H_
+#define __IBSPFRONTEND_H_
+
+// define a GUID for this interface so plugins can access and reference it
+// {8ED6A480-BA5E-11d3-A3E3-0004AC96D4C3}
+static const GUID QERPlugBSPFrontendTable_GUID =
+{ 0x8ed6a480, 0xba5e, 0x11d3, { 0xa3, 0xe3, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+// ask the plugin about the items to show up in the BSP menu
+typedef char * (WINAPI* PFN_GETBSPMENU) ();
+// dispatch a BSP menu command
+typedef void (WINAPI* PFN_DISPATCHBSPCOMMAND) (char *);
+
+struct _QERPlugBSPFrontendTable
+{
+ int m_nSize;
+ PFN_GETBSPMENU m_pfnGetBSPMenu;
+ PFN_DISPATCHBSPCOMMAND m_pfnDispatchBSPCommand;
+};
+
+// interface provided by Radiant to the plugin
+// {A2CCF366-BA60-11d3-A3E3-0004AC96D4C3}
+static const GUID QERAppBSPFrontendTable_GUID =
+{ 0xa2ccf366, 0xba60, 0x11d3, { 0xa3, 0xe3, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+typedef char * (WINAPI* PFN_GETMAPNAME) ();
+typedef void (WINAPI* PFN_LOADPOINTFILE) ();
+
+struct _QERAppBSPFrontendTable
+{
+ int m_nSize;
+ PFN_GETMAPNAME m_pfnGetMapName;
+ PFN_LOADPOINTFILE m_pfnLoadPointFile;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/ICON1.ICO b/q3radiant/ICON1.ICO
new file mode 100755
index 0000000..d24956b
--- /dev/null
+++ b/q3radiant/ICON1.ICO
Binary files differ
diff --git a/q3radiant/IEpairs.cpp b/q3radiant/IEpairs.cpp
new file mode 100755
index 0000000..626e8cd
--- /dev/null
+++ b/q3radiant/IEpairs.cpp
@@ -0,0 +1,185 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:17:12 $
+// $Log: IEpairs.cpp,v $
+// Revision 1.1.1.4 2000/01/18 00:17:12 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:41 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:10 TBesset
+// merged from BSP frontend
+// Revision 1.1.1.3 1999/12/29 18:31:26 TBesset
+// Q3Radiant public version
+//
+//
+// Revision 1.2 1999/11/22 17:46:45 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.1 1999/11/03 20:37:59 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+//
+// DESCRIPTION:
+// virtual class to allow plugin operations on entities epairs
+//
+
+#include "stdafx.h"
+
+void CEpairsWrapper::GetVectorForKey( char* key, vec3_t vec )
+{
+ ::GetVectorForKey( m_pEnt, key, vec );
+}
+
+float CEpairsWrapper::FloatForKey( char *key )
+{
+ return ::FloatForKey( m_pEnt, key );
+}
+
+char* CEpairsWrapper::ValueForKey( char *key )
+{
+ return ::ValueForKey( m_pEnt, key );
+}
+
+void CEpairsWrapper::SetKeyValue( char *key, char *value )
+{
+ ::SetKeyValue( m_pEnt, key, value );
+}
+
+void CEpairsWrapper::GetEntityOrigin( vec3_t vec )
+{
+ VectorCopy( m_pEnt->origin, vec );
+}
+
+// taken from Ritual's version of Q3Radiant ( Entity_CalculateRotatedBounds )
+void CEpairsWrapper::CalculateRotatedBounds( vec3_t mins, vec3_t maxs )
+{
+ entity_t *ent = m_pEnt;
+ int i;
+ float angle;
+ vec3_t angles;
+ vec3_t forward,right,up;
+ vec3_t rotmins, rotmaxs;
+ float trans[3][3];
+ qboolean changed;
+ char tempangles[ 128 ];
+
+ memset( angles, 0, sizeof(vec3_t) );
+ ::GetVectorForKey (ent, "angles", angles);
+
+ changed = false;
+ while ( angles[0] < 0 )
+ {
+ changed = true;
+ angles[0] += 360;
+ }
+ while ( angles[0] > 359 )
+ {
+ changed = true;
+ angles[0] -= 360;
+ }
+ while ( angles[1] < 0 )
+ {
+ changed = true;
+ angles[1] += 360;
+ }
+ while ( angles[1] > 359 )
+ {
+ changed = true;
+ angles[1] -= 360;
+ }
+ while ( angles[2] < 0 )
+ {
+ changed = true;
+ angles[2] += 360;
+ }
+ while ( angles[2] > 359 )
+ {
+ changed = true;
+ angles[2] -= 360;
+ }
+
+ if ( changed )
+ {
+ sprintf( tempangles, "%d %d %d", (int)angles[0], (int)angles[1], (int)angles[2] );
+ ::SetKeyValue ( ent, "angles", tempangles );
+ }
+
+
+ angle = ::FloatForKey (ent, "angle");
+ if ( fabs(angle) > 2 )
+ {
+ angles[1] = angle;
+ }
+ else if (angle == -1)
+ {
+ angles[0] = -90;
+ }
+ else if (angle == -2)
+ {
+ angles[0] = 90;
+ }
+ ::AngleVectors( angles, forward, right, up );
+ for (i=0 ; i<3 ; i++)
+ {
+ trans[i][0] = forward[i];
+ trans[i][1] = -right[i];
+ trans[i][2] = up[i];
+ }
+ ClearBounds( rotmins, rotmaxs );
+ for ( i = 0; i < 8; i++ )
+ {
+ int j;
+ vec3_t tmp, rottemp;
+
+ if ( i & 1 )
+ tmp[0] = mins[0];
+ else
+ tmp[0] = maxs[0];
+
+ if ( i & 2 )
+ tmp[1] = mins[1];
+ else
+ tmp[1] = maxs[1];
+
+ if ( i & 4 )
+ tmp[2] = mins[2];
+ else
+ tmp[2] = maxs[2];
+
+ for (j=0; j<3 ; j++)
+ {
+ rottemp[j] = DotProduct( tmp, trans[j] );
+ }
+ AddPointToBounds( rottemp, rotmins, rotmaxs );
+ }
+ VectorCopy( rotmins, mins );
+ VectorCopy( rotmaxs, maxs );
+}
diff --git a/q3radiant/IEpairs.h b/q3radiant/IEpairs.h
new file mode 100755
index 0000000..c7ceb09
--- /dev/null
+++ b/q3radiant/IEpairs.h
@@ -0,0 +1,83 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:17:12 $
+// $Log: IEpairs.h,v $
+// Revision 1.1.1.4 2000/01/18 00:17:12 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:42 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:10 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:26 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:35 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:26 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.3 1999/12/29 18:31:26 TBesset
+// Q3Radiant public version
+//
+//
+// Revision 1.2 1999/11/22 17:46:45 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.1 1999/11/03 20:37:59 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+//
+// DESCRIPTION:
+// virtual class to allow plugin operations on entities epairs
+//
+
+#ifndef _IEPAIRS_H_
+#define _IEPAIRS_H_
+
+class IEpair
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ virtual void GetVectorForKey( char* key, vec3_t vec ) = 0;
+ virtual float FloatForKey( char *key ) = 0;
+ virtual char* ValueForKey( char *key ) = 0;
+ virtual void SetKeyValue( char *key, char *value ) = 0;
+ virtual void GetEntityOrigin( vec3_t vec ) = 0;
+ // compute the rotated bounds of the BBox based on "angle" and "angles" keys
+ virtual void CalculateRotatedBounds( vec3_t mins, vec3_t maxs ) = 0;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/IMessaging.h b/q3radiant/IMessaging.h
new file mode 100755
index 0000000..549ad51
--- /dev/null
+++ b/q3radiant/IMessaging.h
@@ -0,0 +1,119 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.2.1 $
+// $Author: ttimo $
+// $Date: 2000/02/04 22:59:34 $
+// $Log: IMessaging.h,v $
+// Revision 1.1.2.1 2000/02/04 22:59:34 ttimo
+// messaging API preview
+//
+//
+// DESCRIPTION:
+// interface for all-purpose messaging in Radiant
+
+#ifndef __IMESSAGING_H_
+#define __IMESSAGING_H_
+
+// this one can be hooked in the GL window procs for customizing GUI through plugins
+class IWindowListener
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ // since Radiant is MFC we don't use a WNDPROC, we wrap the MFC handlers
+ // the handler is called first, if returns false Radiant continues processing
+ //++timo maybe add more later ? OnKeyUp and OnKeyDown for instance
+ //++timo TODO: add handlers everywhere
+ virtual bool OnLButtonDown(UINT nFlags, int x, int y) = 0;
+ virtual bool OnMButtonDown(UINT nFlags, int x, int y) = 0;
+ virtual bool OnRButtonDown(UINT nFlags, int x, int y) = 0;
+ virtual bool OnLButtonUp(UINT nFlags, int x, int y) = 0;
+ virtual bool OnMButtonUp(UINT nFlags, int x, int y) = 0;
+ virtual bool OnRButtonUp(UINT nFlags, int x, int y) = 0;
+ virtual bool OnMouseMove(UINT nFlags, int x, int y) = 0;
+};
+
+// various Radiant messages --------
+// this one holds the total number of supported messages (this is used to allocate structs)
+#define RADIANT_MSGCOUNT 3
+// they start with a 0, can be indexed in an array
+// something was selected / deselected
+#define RADIANT_SELECTION 0
+// a brush face was selected / deselected
+#define RADIANT_SFACE 1
+// current texture / shader changed
+#define RADIANT_TEXTURE 2
+
+// this one can be used to listen for Radiant-specific events
+class IListener
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ // message is one of the RADIANT_* consts
+ virtual void DispatchRadiantMsg( int Msg ) = 0;
+};
+
+// this one is provided by Radiant, it's a wrapper for some usefull functions
+class IXYWndWrapper
+{
+public:
+ virtual void SnapToGrid( int x1, int y1, vec3_t pt ) = 0;
+};
+
+// define a GUID for this interface so plugins can access and reference it
+// {41FD005C-D36B-11d3-A3E9-0004AC96D4C3}
+static const GUID QERMessaging_GUID =
+{ 0x41fd005c, 0xd36b, 0x11d3, { 0xa3, 0xe9, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+// will hook the given IWindowListener to the XY window and increment the ref count
+//++timo TODO: add hooking in the CAM view and Z view
+typedef void (WINAPI* PFN_QERAPP_HOOKWINDOW) (IWindowListener *);
+// will unhook the given IWindowListener
+typedef void (WINAPI* PFN_QERAPP_UNHOOKWINDOW) (IWindowListener *);
+// to retrieve the IXYWndWrapper
+typedef IXYWndWrapper* (WINAPI* PFN_QERAPP_GETXYWNDWRAPPER) ();
+
+// will hook a given listener into Radiant listening for the given message and increment ref count
+// call several times to listen for several messages
+typedef void (WINAPI* PFN_QERAPP_HOOKLISTENER) (IListener *, int Msg);
+// will unhook the listener and return the number of messages the given listener was removed from
+typedef int (WINAPI* PFN_QERAPP_UNHOOKLISTENER)(IListener *);
+
+struct _QERMessagingTable
+{
+ int m_nSize;
+ PFN_QERAPP_HOOKWINDOW m_pfnHookWindow;
+ PFN_QERAPP_UNHOOKWINDOW m_pfnUnHookWindow;
+ PFN_QERAPP_GETXYWNDWRAPPER m_pfnGetXYWndWrapper;
+ PFN_QERAPP_HOOKLISTENER m_pfnHookListener;
+ PFN_QERAPP_UNHOOKLISTENER m_pfnUnHookListener;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/IPluginEntities.h b/q3radiant/IPluginEntities.h
new file mode 100755
index 0000000..bf2c818
--- /dev/null
+++ b/q3radiant/IPluginEntities.h
@@ -0,0 +1,105 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:17:12 $
+// $Log: IPluginEntities.h,v $
+// Revision 1.1.1.4 2000/01/18 00:17:12 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:42 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:10 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:35 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:45 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.1 1999/11/03 20:37:59 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+//
+// DESCRIPTION:
+// _QERPluginEntitiesTable is used by plugins for various plugin entities commands
+// _QERPlugEntitiesFactory is a set of commands Radiant uses to instanciate plugin entities
+// next are basics for plugin entities ( interfaces )
+
+#ifndef __IPLUGINENTITIES_H_
+#define __IPLUGINENTITIES_H_
+
+// define a GUID for this interface so plugins can access and reference it
+// {9613F500-8C7C-11d3-8EF3-C9EB56B6B7BE}
+static const GUID QERPluginEntitiesTable_GUID =
+{ 0x9613f500, 0x8c7c, 0x11d3, { 0x8e, 0xf3, 0xc9, 0xeb, 0x56, 0xb6, 0xb7, 0xbe } };
+
+typedef int (WINAPI* PFN_ECLASSSCANDIR) ( char*, HMODULE );
+
+struct _QERPluginEntitiesTable
+{
+ int m_nSize;
+ PFN_ECLASSSCANDIR m_pfnEClassScanDir;
+};
+
+// plugin entities
+class IPluginEntity
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ // getting bounds of the brush used to select/move the object
+ virtual void GetBounds( vec3_t mins, vec3_t maxs ) = 0;
+ // rendering the object in the camera view
+ virtual void CamRender() = 0;
+};
+
+// {DBC6B300-8E4B-11d3-8EF3-BA5E57D56399}
+static const GUID QERPlugEntitiesFactory_GUID =
+{ 0xdbc6b300, 0x8e4b, 0x11d3, { 0x8e, 0xf3, 0xba, 0x5e, 0x57, 0xd5, 0x63, 0x99 } };
+
+typedef IPluginEntity * (WINAPI* PFN_CREATEENTITY) ( eclass_t *, IEpair * );
+
+struct _QERPlugEntitiesFactory
+{
+ int m_nSize;
+ PFN_CREATEENTITY m_pfnCreateEntity;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/ISelectedFace.h b/q3radiant/ISelectedFace.h
new file mode 100755
index 0000000..e4c5481
--- /dev/null
+++ b/q3radiant/ISelectedFace.h
@@ -0,0 +1,113 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4.2.1 $
+// $Author: ttimo $
+// $Date: 2000/02/10 03:00:20 $
+// $Log: ISelectedFace.h,v $
+// Revision 1.1.1.4.2.1 2000/02/10 03:00:20 ttimo
+// adding IShaders.h
+//
+// Revision 1.1.1.4 2000/01/18 00:17:12 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:42 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:10 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:35 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:45 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.4.3 1999/11/15 22:39:40 Timo & Christine
+// bug fixing / additional features after update 173 from Robert
+//
+// Revision 1.1.4.2 1999/11/14 16:26:10 Timo & Christine
+// first beta of the ritualmap surface plugin
+//
+// Revision 1.1.4.1 1999/11/03 20:37:59 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+// Revision 1.1.2.1 1999/10/27 08:34:26 Timo & Christine
+// preview version of the texture tools plugin is ready
+// ( TexTool.dll plugin is in Q3Plugin module )
+// plugins can draw in their own window using Radiant's qgl bindings
+//
+//
+// DESCRIPTION:
+// Quick interface hack for selected face interface
+// this one really needs more work, but I'm in a hurry with TexTool
+
+#ifndef __ISELECTEDFACE_H_
+#define __ISELECTEDFACE_H_
+
+// define a GUID for this interface so plugins can access and reference it
+// {5416A2A0-8633-11d3-8EF3-88B61F3A3B12}
+static const GUID QERSelectedFaceTable_GUID =
+{ 0x5416a2a0, 0x8633, 0x11d3, { 0x8e, 0xf3, 0x88, 0xb6, 0x1f, 0x3a, 0x3b, 0x12 } };
+
+//++timo TODO: this interface needs some cleanup with the new texture / shaders interface
+
+// retrieve the texture number to bind to
+typedef int (WINAPI* PFN_GETTEXTURENUMBER) ();
+// winding_t is assumed to have MAX_POINTS_ON_WINDING allocated
+typedef int (WINAPI* PFN_GETFACEINFO) (_QERFaceData*, winding_t* );
+// tell editor to update the selected face data
+typedef int (WINAPI* PFN_SETFACEINFO) (_QERFaceData*);
+// retrieving some texture information
+typedef void (WINAPI* PFN_GETTEXTURESIZE) ( int Size[2] );
+// loading the qtexture_t from the texture name
+typedef qtexture_t* (WINAPI* PFN_TEXTUREFORNAME) ( const char *name );
+// straight func pointer to Select_SetTexture
+// last parameter must be casted to an IPluginTexdef
+typedef void (WINAPI* PFN_SELECT_SETTEXTURE) (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef );
+
+// NOTE: some things in there are not really related to the selected face
+// having some stuff moved into a textures-dedicated part ?
+struct _QERSelectedFaceTable
+{
+ int m_nSize;
+ PFN_GETTEXTURENUMBER m_pfnGetTextureNumber;
+ PFN_GETFACEINFO m_pfnGetFaceInfo;
+ PFN_SETFACEINFO m_pfnSetFaceInfo;
+ PFN_GETTEXTURESIZE m_pfnGetTextureSize;
+ PFN_TEXTUREFORNAME m_pfnTextureForName;
+ PFN_SELECT_SETTEXTURE m_pfnSelect_SetTexture;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/IShaders.cpp b/q3radiant/IShaders.cpp
new file mode 100755
index 0000000..b68f2d4
--- /dev/null
+++ b/q3radiant/IShaders.cpp
@@ -0,0 +1,86 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.2.2 $
+// $Author: ttimo $
+// $Date: 2000/02/24 22:24:45 $
+// $Log: IShaders.cpp,v $
+// Revision 1.1.2.2 2000/02/24 22:24:45 ttimo
+// RC2
+//
+// Revision 1.1.2.1 2000/02/11 03:52:30 ttimo
+// working on the IShader interface
+//
+//
+// DESCRIPTION:
+// implementation of the shaders / textures interface
+//
+
+#include "stdafx.h"
+
+//++timo NOTE: this whole part is evolving on a seperate branch on SourceForge
+// will eventually turn into a major rewrite of the shader / texture code
+
+// this is a modified version of Texture_ForName
+qtexture_t* WINAPI QERApp_TryTextureForName(const char* name)
+{
+ qtexture_t *q;
+ char filename[1024];
+ for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+ {
+ if (!strcmp(name, q->filename))
+ return q;
+ }
+ // try loading from file .. this is a copy of the worst part of Texture_ForName
+ char cWork[1024];
+ sprintf (filename, "%s/%s.tga", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name);
+ QE_ConvertDOSToUnixName( cWork, filename );
+ strcpy(filename, cWork);
+ unsigned char* pPixels = NULL;
+ int nWidth;
+ int nHeight;
+ LoadImage(filename, &pPixels, &nWidth, &nHeight);
+ if (pPixels == NULL)
+ {
+ // try jpg
+ // blatant assumption of .tga should be fine since we sprintf'd it above
+ int nLen = strlen(filename);
+ filename[nLen-3] = 'j';
+ filename[nLen-2] = 'p';
+ filename[nLen-1] = 'g';
+ LoadImage(filename, &pPixels, &nWidth, &nHeight);
+ }
+ if (pPixels)
+ {
+ q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
+ //++timo storing the filename .. will be removed by shader code cleanup
+ // this is dirty, and we sure miss some places were we should fill the filename info
+ strcpy( q->filename, name );
+ SetNameShaderInfo(q, filename, name);
+ Sys_Printf ("done.\n", name);
+ free(pPixels);
+ return q;
+ }
+ return NULL;
+}
diff --git a/q3radiant/IShaders.h b/q3radiant/IShaders.h
new file mode 100755
index 0000000..9bd0cf2
--- /dev/null
+++ b/q3radiant/IShaders.h
@@ -0,0 +1,79 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.2.3 $
+// $Author: ttimo $
+// $Date: 2000/02/24 22:24:45 $
+// $Log: IShaders.h,v $
+// Revision 1.1.2.3 2000/02/24 22:24:45 ttimo
+// RC2
+//
+// Revision 1.1.2.2 2000/02/11 03:52:30 ttimo
+// working on the IShader interface
+//
+// Revision 1.1.2.1 2000/02/10 03:00:20 ttimo
+// adding IShaders.h
+//
+//
+// DESCRIPTION:
+// a set of functions to manipulate textures in Radiant
+//
+
+#ifndef __ISHADERS_H_
+#define __ISHADERS_H_
+
+// define a GUID for this interface so plugins can access and reference it
+// {D42F798A-DF57-11d3-A3EE-0004AC96D4C3}
+static const GUID QERShadersTable_GUID =
+{ 0xd42f798a, 0xdf57, 0x11d3, { 0xa3, 0xee, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+//++timo NOTE: global strategy, when there's try before it means .. if the thing can't be found / loaded it will not
+// create a default one
+
+//++timo TODO: duplicate _QERFuncTable_1::m_pfnHasShader here?
+//++timo FIXME: change the names to fit the changes we wanna do in the Radiant shader / textures code
+//++timo NOTE: for Curry, this shader loading thingy is only provided so that we can update the Radiant texture window?
+// don't use yet .. will not implement yet
+// get a shader, load it if needed
+// returns NULL if shader doesn't exist
+//++timo will reload the shader if already loaded? .. no, don't do that yet ..
+//++timo I'm not happy with the name?
+typedef qtexture_t* (WINAPI* PFN_TRYSHADERFORNAME) (const char* name);
+// load a texture
+// will not try loading a shader, will look for the actual image file ..
+// returns NULL on file not found
+// NOTE: don't put the .tga or .jpg filetype extension
+// if returns NULL, it means the texture needs loading, use _QERSelectedFaceTable::m_pfnTextureForName
+//++timo NOTE: all of this is hacks and workarounds, the shader code rewrite is supposed to solve all issues
+typedef qtexture_t* (WINAPI* PFN_TRYTEXTUREFORNAME) (const char* filename);
+
+struct _QERShadersTable
+{
+ int m_nSize;
+ // currently disabled
+// PFN_TRYLOADSHADER m_pfnTryLoadShader;
+ PFN_TRYTEXTUREFORNAME m_pfnTryTextureForName;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/LBMLIB.CPP b/q3radiant/LBMLIB.CPP
new file mode 100755
index 0000000..5d52307
--- /dev/null
+++ b/q3radiant/LBMLIB.CPP
@@ -0,0 +1,1329 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// lbmlib.c
+
+#include "stdafx.h"
+#include "cmdlib.h"
+#include "lbmlib.h"
+#include "bmp.h"
+#include "pakstuff.h"
+#include "jpeglib.h"
+
+
+/*
+============================================================================
+
+ LBM STUFF
+
+============================================================================
+*/
+
+
+typedef unsigned char UBYTE;
+//conflicts with windows typedef short WORD;
+typedef unsigned short UWORD;
+typedef long LONG;
+
+typedef enum
+{
+ ms_none,
+ ms_mask,
+ ms_transcolor,
+ ms_lasso
+} mask_t;
+
+typedef enum
+{
+ cm_none,
+ cm_rle1
+} compress_t;
+
+typedef struct
+{
+ UWORD w,h;
+ short x,y;
+ UBYTE nPlanes;
+ UBYTE masking;
+ UBYTE compression;
+ UBYTE pad1;
+ UWORD transparentColor;
+ UBYTE xAspect,yAspect;
+ short pageWidth,pageHeight;
+} bmhd_t;
+
+extern bmhd_t bmhd; // will be in native byte order
+
+
+
+#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
+#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
+#define PBMID ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
+#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
+#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
+#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
+
+
+bmhd_t bmhd;
+
+int Align (int l)
+{
+ if (l&1)
+ return l+1;
+ return l;
+}
+
+
+
+/*
+================
+LBMRLEdecompress
+
+Source must be evenly aligned!
+================
+*/
+byte *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
+{
+ int count;
+ byte b,rept;
+
+ count = 0;
+
+ do
+ {
+ rept = *source++;
+
+ if (rept > 0x80)
+ {
+ rept = (rept^0xff)+2;
+ b = *source++;
+ memset(unpacked,b,rept);
+ unpacked += rept;
+ }
+ else if (rept < 0x80)
+ {
+ rept++;
+ memcpy(unpacked,source,rept);
+ unpacked += rept;
+ source += rept;
+ }
+ else
+ rept = 0; // rept of 0x80 is NOP
+
+ count += rept;
+
+ } while (count<bpwidth);
+
+ if (count>bpwidth)
+ Error ("Decompression exceeded width!\n");
+
+
+ return source;
+}
+
+
+/*
+=================
+LoadLBM
+=================
+*/
+void LoadLBM (char *filename, byte **picture, byte **palette)
+{
+ byte *LBMbuffer, *picbuffer, *cmapbuffer;
+ int y;
+ byte *LBM_P, *LBMEND_P;
+ byte *pic_p;
+ byte *body_p;
+
+ int formtype,formlength;
+ int chunktype,chunklength;
+
+// qiet compiler warnings
+ picbuffer = NULL;
+ cmapbuffer = NULL;
+
+//
+// load the LBM
+//
+ LoadFile (filename, (void **)&LBMbuffer);
+
+ if (LBMbuffer == NULL)
+ {
+ return;
+ }
+//
+// parse the LBM header
+//
+ LBM_P = LBMbuffer;
+ if ( *(int *)LBMbuffer != LittleLong(FORMID) )
+ Error ("No FORM ID at start of file!\n");
+
+ LBM_P += 4;
+ formlength = BigLong( *(int *)LBM_P );
+ LBM_P += 4;
+ LBMEND_P = LBM_P + Align(formlength);
+
+ formtype = LittleLong(*(int *)LBM_P);
+
+ if (formtype != ILBMID && formtype != PBMID)
+ Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
+ ,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
+
+ LBM_P += 4;
+
+//
+// parse chunks
+//
+
+ while (LBM_P < LBMEND_P)
+ {
+ chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
+ LBM_P += 4;
+ chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
+ LBM_P += 4;
+
+ switch ( chunktype )
+ {
+ case BMHDID:
+ memcpy (&bmhd,LBM_P,sizeof(bmhd));
+ bmhd.w = BigShort(bmhd.w);
+ bmhd.h = BigShort(bmhd.h);
+ bmhd.x = BigShort(bmhd.x);
+ bmhd.y = BigShort(bmhd.y);
+ bmhd.pageWidth = BigShort(bmhd.pageWidth);
+ bmhd.pageHeight = BigShort(bmhd.pageHeight);
+ break;
+
+ case CMAPID:
+ cmapbuffer = (unsigned char*)malloc (768);
+ memset (cmapbuffer, 0, 768);
+ memcpy (cmapbuffer, LBM_P, chunklength);
+ break;
+
+ case BODYID:
+ body_p = LBM_P;
+
+ pic_p = picbuffer = (unsigned char*)malloc (bmhd.w*bmhd.h);
+ if (formtype == PBMID)
+ {
+ //
+ // unpack PBM
+ //
+ for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
+ {
+ if (bmhd.compression == cm_rle1)
+ body_p = LBMRLEDecompress ((byte *)body_p
+ , pic_p , bmhd.w);
+ else if (bmhd.compression == cm_none)
+ {
+ memcpy (pic_p,body_p,bmhd.w);
+ body_p += Align(bmhd.w);
+ }
+ }
+
+ }
+ else
+ {
+ //
+ // unpack ILBM
+ //
+ Error ("%s is an interlaced LBM, not packed", filename);
+ }
+ break;
+ }
+
+ LBM_P += Align(chunklength);
+ }
+
+ free (LBMbuffer);
+
+ *picture = picbuffer;
+
+ if (palette)
+ *palette = cmapbuffer;
+}
+
+
+/*
+============================================================================
+
+ WRITE LBM
+
+============================================================================
+*/
+
+/*
+==============
+WriteLBMfile
+==============
+*/
+void WriteLBMfile (char *filename, byte *data,
+ int width, int height, byte *palette)
+{
+ byte *lbm, *lbmptr;
+ int *formlength, *bmhdlength, *cmaplength, *bodylength;
+ int length;
+ bmhd_t basebmhd;
+
+ lbm = lbmptr = (unsigned char*)malloc (width*height+1000);
+
+//
+// start FORM
+//
+ *lbmptr++ = 'F';
+ *lbmptr++ = 'O';
+ *lbmptr++ = 'R';
+ *lbmptr++ = 'M';
+
+ formlength = (int*)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ *lbmptr++ = 'P';
+ *lbmptr++ = 'B';
+ *lbmptr++ = 'M';
+ *lbmptr++ = ' ';
+
+//
+// write BMHD
+//
+ *lbmptr++ = 'B';
+ *lbmptr++ = 'M';
+ *lbmptr++ = 'H';
+ *lbmptr++ = 'D';
+
+ bmhdlength = (int *)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ memset (&basebmhd,0,sizeof(basebmhd));
+ basebmhd.w = BigShort((short)width);
+ basebmhd.h = BigShort((short)height);
+ basebmhd.nPlanes = 8;
+ basebmhd.xAspect = 5;
+ basebmhd.yAspect = 6;
+ basebmhd.pageWidth = BigShort((short)width);
+ basebmhd.pageHeight = BigShort((short)height);
+
+ memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
+ lbmptr += sizeof(basebmhd);
+
+ length = lbmptr-(byte *)bmhdlength-4;
+ *bmhdlength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// write CMAP
+//
+ *lbmptr++ = 'C';
+ *lbmptr++ = 'M';
+ *lbmptr++ = 'A';
+ *lbmptr++ = 'P';
+
+ cmaplength = (int *)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ memcpy (lbmptr,palette,768);
+ lbmptr += 768;
+
+ length = lbmptr-(byte *)cmaplength-4;
+ *cmaplength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// write BODY
+//
+ *lbmptr++ = 'B';
+ *lbmptr++ = 'O';
+ *lbmptr++ = 'D';
+ *lbmptr++ = 'Y';
+
+ bodylength = (int *)lbmptr;
+ lbmptr+=4; // leave space for length
+
+ memcpy (lbmptr,data,width*height);
+ lbmptr += width*height;
+
+ length = lbmptr-(byte *)bodylength-4;
+ *bodylength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// done
+//
+ length = lbmptr-(byte *)formlength-4;
+ *formlength = BigLong(length);
+ if (length&1)
+ *lbmptr++ = 0; // pad chunk to even offset
+
+//
+// write output file
+//
+ SaveFile (filename, lbm, lbmptr-lbm);
+ free (lbm);
+}
+
+/*
+============================================================================
+
+LOAD PCX
+
+============================================================================
+*/
+typedef struct
+{
+ char manufacturer;
+ char version;
+ char encoding;
+ char bits_per_pixel;
+ unsigned short xmin,ymin,xmax,ymax;
+ unsigned short hres,vres;
+ unsigned char palette[48];
+ char reserved;
+ char color_planes;
+ unsigned short bytes_per_line;
+ unsigned short palette_type;
+ char filler[58];
+ unsigned char data; // unbounded
+} pcx_t;
+
+/*
+==============
+LoadPCX
+==============
+*/
+void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
+{
+ byte *raw = 0;
+ pcx_t *pcx;
+ int x, y;
+ int len;
+ int dataByte, runLength;
+ byte *out, *pix;
+
+ if (pic)
+ *pic = NULL;
+ if (palette)
+ *palette = NULL;
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+
+ //
+ // load the file
+ //
+ len = LoadFile (filename, (void **)&raw);
+ if (len == -1)
+ return;
+
+ //
+ // parse the PCX file
+ //
+ pcx = (pcx_t *)raw;
+ raw = &pcx->data;
+
+ pcx->xmin = LittleShort(pcx->xmin);
+ pcx->ymin = LittleShort(pcx->ymin);
+ pcx->xmax = LittleShort(pcx->xmax);
+ pcx->ymax = LittleShort(pcx->ymax);
+ pcx->hres = LittleShort(pcx->hres);
+ pcx->vres = LittleShort(pcx->vres);
+ pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
+ pcx->palette_type = LittleShort(pcx->palette_type);
+
+ if (pcx->manufacturer != 0x0a
+ || pcx->version != 5
+ || pcx->encoding != 1
+ || pcx->bits_per_pixel != 8
+ || pcx->xmax >= 640
+ || pcx->ymax >= 480)
+ Error ("Bad pcx file %s", filename);
+
+ if (palette)
+ {
+ *palette = (unsigned char*)malloc(768);
+ memcpy (*palette, (byte *)pcx + len - 768, 768);
+ }
+
+ if (width)
+ *width = pcx->xmax+1;
+ if (height)
+ *height = pcx->ymax+1;
+
+ if (!pic)
+ {
+ free(pcx);
+ return;
+ }
+
+ out = (unsigned char*)malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
+ if (!out)
+ Error ("Skin_Cache: couldn't allocate");
+
+ *pic = out;
+
+ pix = out;
+
+ for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
+ {
+ for (x=0 ; x<=pcx->xmax ; )
+ {
+ dataByte = *raw++;
+
+ if((dataByte & 0xC0) == 0xC0)
+ {
+ runLength = dataByte & 0x3F;
+ dataByte = *raw++;
+ }
+ else
+ runLength = 1;
+
+ while(runLength-- > 0)
+ pix[x++] = dataByte;
+ }
+
+ }
+
+ if ( raw - (byte *)pcx > len)
+ Error ("PCX file %s was malformed", filename);
+
+ free (pcx);
+}
+/*
+==============
+WritePCXfile
+==============
+*/
+void WritePCXfile (char *filename, byte *data,
+ int width, int height, byte *palette)
+{
+ int i, j, length;
+ pcx_t *pcx;
+ byte *pack;
+
+ pcx = (pcx_t*)malloc (width*height*2+1000);
+ memset (pcx, 0, sizeof(*pcx));
+
+ pcx->manufacturer = 0x0a; // PCX id
+ pcx->version = 5; // 256 color
+ pcx->encoding = 1; // uncompressed
+ pcx->bits_per_pixel = 8; // 256 color
+ pcx->xmin = 0;
+ pcx->ymin = 0;
+ pcx->xmax = LittleShort((short)(width-1));
+ pcx->ymax = LittleShort((short)(height-1));
+ pcx->hres = LittleShort((short)width);
+ pcx->vres = LittleShort((short)height);
+ pcx->color_planes = 1; // chunky image
+ pcx->bytes_per_line = LittleShort((short)width);
+ pcx->palette_type = LittleShort(2); // not a grey scale
+
+ // pack the image
+ pack = &pcx->data;
+
+ for (i=0 ; i<height ; i++)
+ {
+ for (j=0 ; j<width ; j++)
+ {
+ if ( (*data & 0xc0) != 0xc0)
+ *pack++ = *data++;
+ else
+ {
+ *pack++ = 0xc1;
+ *pack++ = *data++;
+ }
+ }
+ }
+
+ // write the palette
+ *pack++ = 0x0c; // palette ID byte
+ for (i=0 ; i<768 ; i++)
+ *pack++ = *palette++;
+
+// write output file
+ length = pack - (byte *)pcx;
+ SaveFile (filename, pcx, length);
+
+ free (pcx);
+}
+
+/*
+============================================================================
+
+LOAD IMAGE
+
+============================================================================
+*/
+
+/*
+==============
+Load256Image
+
+Will load either an lbm or pcx, depending on extension.
+Any of the return pointers can be NULL if you don't want them.
+==============
+*/
+void Load256Image (char *name, byte **pixels, byte **palette,
+ int *width, int *height)
+{
+ char ext[128];
+ bitmap_t bmp;
+
+ ExtractFileExtension (name, ext);
+ if (stricmp(ext, "lbm"))
+ {
+ LoadLBM (name, pixels, palette);
+ if (width)
+ *width = bmhd.w;
+ if (height)
+ *height = bmhd.h;
+ }
+ else if (stricmp (ext, "pcx"))
+ {
+ LoadPCX (name, pixels, palette, width, height);
+ }
+ else if (stricmp (ext, "bmp"))
+ {
+ LoadBMP (name, &bmp);
+ if (bmp.palette)
+ {
+ *palette = (unsigned char*)malloc (768);
+ memcpy (*palette, bmp.palette, 768);
+ }
+ FreeBMP (&bmp);
+ }
+ else
+ Error ("%s doesn't have a known image extension", name);
+}
+
+
+/*
+==============
+Save256Image
+
+Will save either an lbm or pcx, depending on extension.
+==============
+*/
+void Save256Image (char *name, byte *pixels, byte *palette,
+ int width, int height)
+{
+ char ext[128];
+
+ ExtractFileExtension (name, ext);
+ if (!strcmp (ext, "lbm"))
+ {
+ WriteLBMfile (name, pixels, width, height, palette);
+ }
+ else if (!stricmp (ext, "pcx"))
+ {
+ WritePCXfile (name, pixels, width, height, palette);
+ }
+ else
+ Error ("%s doesn't have a known image extension", name);
+}
+
+
+
+/*
+============================================================================
+
+TARGA IMAGE
+
+============================================================================
+*/
+typedef struct _TargaHeader {
+ unsigned char id_length, colormap_type, image_type;
+ unsigned short colormap_index, colormap_length;
+ unsigned char colormap_size;
+ unsigned short x_origin, y_origin, width, height;
+ unsigned char pixel_size, attributes;
+} TargaHeader;
+
+int fgetLittleShort (FILE *f)
+{
+ byte b1, b2;
+
+ b1 = fgetc(f);
+ b2 = fgetc(f);
+
+ return (short)(b1 + b2*256);
+}
+
+int getLittleShort (byte*& p)
+{
+ byte b1, b2;
+ b1 = *p++;
+ b2 = *p++;
+ return (short)(b1 + b2*256);
+}
+
+int getLittleLong (byte*& p)
+{
+ byte b1, b2, b3, b4;
+
+ b1 = *p++;
+ b2 = *p++;
+ b3 = *p++;
+ b4 = *p++;
+ return b1 + (b2<<8) + (b3<<16) + (b4<<24);
+}
+
+char getc(byte*& p)
+{
+ return *p++;
+}
+
+/*
+=========================================================
+
+BMP LOADING
+
+=========================================================
+*/
+typedef struct
+{
+ char id[2];
+ unsigned long fileSize;
+ unsigned long reserved0;
+ unsigned long bitmapDataOffset;
+ unsigned long bitmapHeaderSize;
+ unsigned long width;
+ unsigned long height;
+ unsigned short planes;
+ unsigned short bitsPerPixel;
+ unsigned long compression;
+ unsigned long bitmapDataSize;
+ unsigned long hRes;
+ unsigned long vRes;
+ unsigned long colors;
+ unsigned long importantColors;
+ unsigned char palette[256][4];
+} BMPHeader_t;
+
+static void LoadBMP( const char *name, byte **pic, int *width, int *height )
+{
+ int columns, rows, numPixels;
+ byte *pixbuf;
+ int row, column;
+ byte *buf_p;
+ byte *buffer;
+ unsigned int length;
+ BMPHeader_t bmpHeader;
+ byte *bmpRGBA;
+
+ *pic = NULL;
+
+ //
+ // load the file
+ //
+ length = LoadFile( ( char * ) name, (void **)&buffer);
+ if (length == -1)
+ {
+ length = PakLoadAnyFile( (char*)name, (void**)&buffer);
+ if (length == -1)
+ {
+ return;
+ }
+ }
+
+ buf_p = buffer;
+
+ bmpHeader.id[0] = *buf_p++;
+ bmpHeader.id[1] = *buf_p++;
+ bmpHeader.fileSize = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.reserved0 = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.bitmapDataOffset = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.bitmapHeaderSize = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.width = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.height = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.planes = LittleShort( * ( short * ) buf_p );
+ buf_p += 2;
+ bmpHeader.bitsPerPixel = LittleShort( * ( short * ) buf_p );
+ buf_p += 2;
+ bmpHeader.compression = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.bitmapDataSize = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.hRes = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.vRes = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.colors = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+ bmpHeader.importantColors = LittleLong( * ( long * ) buf_p );
+ buf_p += 4;
+
+ memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );
+
+ if ( bmpHeader.bitsPerPixel == 8 )
+ buf_p += 1024;
+
+ if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
+ {
+ Sys_Printf("LoadBMP: only Windows-style BMP files supported (%s)\n", name );
+ }
+ if ( bmpHeader.fileSize != length )
+ {
+ Sys_Printf("LoadBMP: header size does not match file size (%d vs. %d) (%s)\n", bmpHeader.fileSize, length, name );
+ }
+ if ( bmpHeader.compression != 0 )
+ {
+ Sys_Printf("LoadBMP: only uncompressed BMP files supported (%s)\n", name );
+ }
+ if ( bmpHeader.bitsPerPixel < 8 )
+ {
+ Sys_Printf("LoadBMP: monochrome and 4-bit BMP files not supported (%s)\n", name );
+ }
+
+ columns = bmpHeader.width;
+ rows = bmpHeader.height;
+ if ( rows < 0 )
+ rows = -rows;
+ numPixels = columns * rows;
+
+ if ( width )
+ *width = columns;
+ if ( height )
+ *height = rows;
+
+ bmpRGBA = reinterpret_cast<unsigned char*>(malloc( numPixels * 4 ));
+ *pic = bmpRGBA;
+
+
+ for ( row = rows-1; row >= 0; row-- )
+ {
+ pixbuf = bmpRGBA + row*columns*4;
+
+ for ( column = 0; column < columns; column++ )
+ {
+ unsigned char red, green, blue, alpha;
+ int palIndex;
+ unsigned short shortPixel;
+
+ switch ( bmpHeader.bitsPerPixel )
+ {
+ case 8:
+ palIndex = *buf_p++;
+ *pixbuf++ = bmpHeader.palette[palIndex][2];
+ *pixbuf++ = bmpHeader.palette[palIndex][1];
+ *pixbuf++ = bmpHeader.palette[palIndex][0];
+ *pixbuf++ = 0xff;
+ break;
+ case 16:
+ shortPixel = * ( unsigned short * ) pixbuf;
+ pixbuf += 2;
+ *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
+ *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
+ *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
+ *pixbuf++ = 0xff;
+ break;
+
+ case 24:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alpha = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = alpha;
+ break;
+ default:
+ Sys_Printf("LoadBMP: illegal pixel_size '%d' in file '%s'\n", bmpHeader.bitsPerPixel, name );
+ break;
+ }
+ }
+ }
+
+ free( buffer );
+
+}
+
+
+/*
+=================================================================
+
+PCX LOADING
+
+=================================================================
+*/
+
+
+/*
+==============
+LoadPCX
+==============
+*/
+static void LoadPCX ( const char *filename, byte **pic, byte **palette, int *width, int *height)
+{
+ byte *raw;
+ pcx_t *pcx;
+ int x, y;
+ int len;
+ int dataByte, runLength;
+ byte *out, *pix;
+ int xmax, ymax;
+
+ *pic = NULL;
+ *palette = NULL;
+
+ //
+ // load the file
+ //
+ len = LoadFile( ( char * ) filename, (void **)&raw);
+ if (len == -1)
+ {
+ len = PakLoadAnyFile( (char*)filename, (void**)&raw);
+ if (len == -1)
+ {
+ return;
+ }
+ }
+
+ //
+ // parse the PCX file
+ //
+ pcx = (pcx_t *)raw;
+ raw = &pcx->data;
+
+ xmax = LittleShort(pcx->xmax);
+ ymax = LittleShort(pcx->ymax);
+
+ if (pcx->manufacturer != 0x0a
+ || pcx->version != 5
+ || pcx->encoding != 1
+ || pcx->bits_per_pixel != 8
+ || xmax >= 1024
+ || ymax >= 1024)
+ {
+ Sys_Printf ("Bad pcx file %s (%i x %i) (%i x %i)\n", filename, xmax+1, ymax+1, pcx->xmax, pcx->ymax);
+ return;
+ }
+
+ out = reinterpret_cast<unsigned char*>(malloc ( (ymax+1) * (xmax+1) ));
+
+ *pic = out;
+
+ pix = out;
+
+ if (palette)
+ {
+ *palette = reinterpret_cast<unsigned char*>(malloc(768));
+ memcpy (*palette, (byte *)pcx + len - 768, 768);
+ }
+
+ if (width)
+ *width = xmax+1;
+ if (height)
+ *height = ymax+1;
+// FIXME: use bytes_per_line here?
+
+ for (y=0 ; y<=ymax ; y++, pix += xmax+1)
+ {
+ for (x=0 ; x<=xmax ; )
+ {
+ dataByte = *raw++;
+
+ if((dataByte & 0xC0) == 0xC0)
+ {
+ runLength = dataByte & 0x3F;
+ dataByte = *raw++;
+ }
+ else
+ runLength = 1;
+
+ while(runLength-- > 0)
+ pix[x++] = dataByte;
+ }
+
+ }
+
+ if ( raw - (byte *)pcx > len)
+ {
+ Sys_Printf ("PCX file %s was malformed", filename);
+ free (*pic);
+ *pic = NULL;
+ }
+
+ free(pcx);
+}
+
+
+/*
+==============
+LoadPCX32
+==============
+*/
+static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *height) {
+ byte *palette;
+ byte *pic8;
+ int i, c, p;
+ byte *pic32;
+
+ LoadPCX (filename, &pic8, &palette, width, height);
+ if (!pic8) {
+ *pic = NULL;
+ return;
+ }
+
+ c = (*width) * (*height);
+ pic32 = *pic = reinterpret_cast<unsigned char*>(malloc(4 * c ));
+ for (i = 0 ; i < c ; i++) {
+ p = pic8[i];
+ pic32[0] = palette[p*3];
+ pic32[1] = palette[p*3 + 1];
+ pic32[2] = palette[p*3 + 2];
+ pic32[3] = 255;
+ pic32 += 4;
+ }
+
+ free (pic8);
+ free (palette);
+}
+
+/*
+=========================================================
+
+TARGA LOADING
+
+=========================================================
+*/
+
+/*
+=============
+LoadTGA
+=============
+*/
+void LoadTGA ( const char *name, byte **pic, int *width, int *height)
+{
+ int columns, rows, numPixels;
+ byte *pixbuf;
+ int row, column;
+ byte *buf_p;
+ byte *buffer;
+ TargaHeader targa_header;
+ byte *targa_rgba;
+
+ *pic = NULL;
+
+ //
+ // load the file
+ //
+ int nLen = LoadFile ( ( char * ) name, (void **)&buffer);
+ if (nLen == -1)
+ {
+ nLen = PakLoadAnyFile((char*)name, (void**)&buffer);
+ if (nLen == -1)
+ {
+ return;
+ }
+ }
+
+ buf_p = buffer;
+
+ targa_header.id_length = *buf_p++;
+ targa_header.colormap_type = *buf_p++;
+ targa_header.image_type = *buf_p++;
+
+ targa_header.colormap_index = LittleShort ( *(short *)buf_p );
+ buf_p += 2;
+ targa_header.colormap_length = LittleShort ( *(short *)buf_p );
+ buf_p += 2;
+ targa_header.colormap_size = *buf_p++;
+ targa_header.x_origin = LittleShort ( *(short *)buf_p );
+ buf_p += 2;
+ targa_header.y_origin = LittleShort ( *(short *)buf_p );
+ buf_p += 2;
+ targa_header.width = LittleShort ( *(short *)buf_p );
+ buf_p += 2;
+ targa_header.height = LittleShort ( *(short *)buf_p );
+ buf_p += 2;
+ targa_header.pixel_size = *buf_p++;
+ targa_header.attributes = *buf_p++;
+
+ //++timo debug
+ if (targa_header.pixel_size == 32)
+ Sys_Printf("%s is 32bit\n", name);
+ bool bAlphaOK = false;
+
+ if (targa_header.image_type!=2
+ && targa_header.image_type!=10
+ && targa_header.image_type != 3 )
+ {
+ Sys_Printf("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
+ }
+
+ if ( targa_header.colormap_type != 0 )
+ {
+ Sys_Printf("LoadTGA: colormaps not supported\n" );
+ }
+
+ if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
+ {
+ Sys_Printf("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+ }
+
+ columns = targa_header.width;
+ rows = targa_header.height;
+ numPixels = columns * rows;
+
+ if (width)
+ *width = columns;
+ if (height)
+ *height = rows;
+
+ targa_rgba = reinterpret_cast<unsigned char*>(malloc (numPixels*4));
+ *pic = targa_rgba;
+
+ if (targa_header.id_length != 0)
+ buf_p += targa_header.id_length; // skip TARGA image comment
+
+ if ( targa_header.image_type==2 || targa_header.image_type == 3 )
+ {
+ // Uncompressed RGB or gray scale image
+ for(row=rows-1; row>=0; row--)
+ {
+ pixbuf = targa_rgba + row*columns*4;
+ for(column=0; column<columns; column++)
+ {
+ unsigned char red,green,blue,alphabyte;
+ switch (targa_header.pixel_size)
+ {
+
+ case 8:
+ blue = *buf_p++;
+ green = blue;
+ red = blue;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = 255;
+ break;
+
+ case 24:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = *buf_p++;
+ //++timo debug: detect if the whole alpha channel is 0
+ if (alphabyte != 0)
+ bAlphaOK = true;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = alphabyte;
+ break;
+ default:
+ Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
+ break;
+ }
+ }
+ }
+
+ //++timo debug
+ if (bAlphaOK)
+ Sys_Printf("alpha channel OK");
+ else
+ Sys_Printf("empty alpha channel!");
+ }
+ else if (targa_header.image_type==10) { // Runlength encoded RGB images
+
+ //++timo debug
+ Sys_Printf("runlength encode RGB image");
+
+ unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
+
+ red = 0;
+ green = 0;
+ blue = 0;
+ alphabyte = 0xff;
+
+ for(row=rows-1; row>=0; row--) {
+ pixbuf = targa_rgba + row*columns*4;
+ for(column=0; column<columns; ) {
+ packetHeader= *buf_p++;
+ packetSize = 1 + (packetHeader & 0x7f);
+ if (packetHeader & 0x80) { // run-length packet
+ switch (targa_header.pixel_size) {
+ case 24:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = *buf_p++;
+ break;
+ default:
+ Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
+ break;
+ }
+
+ for(j=0;j<packetSize;j++) {
+ *pixbuf++=red;
+ *pixbuf++=green;
+ *pixbuf++=blue;
+ *pixbuf++=alphabyte;
+ column++;
+ if (column==columns) { // run spans across rows
+ column=0;
+ if (row>0)
+ row--;
+ else
+ goto breakOut;
+ pixbuf = targa_rgba + row*columns*4;
+ }
+ }
+ }
+ else { // non run-length packet
+ for(j=0;j<packetSize;j++) {
+ switch (targa_header.pixel_size) {
+ case 24:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = 255;
+ break;
+ case 32:
+ blue = *buf_p++;
+ green = *buf_p++;
+ red = *buf_p++;
+ alphabyte = *buf_p++;
+ *pixbuf++ = red;
+ *pixbuf++ = green;
+ *pixbuf++ = blue;
+ *pixbuf++ = alphabyte;
+ break;
+ default:
+ Sys_Printf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
+ break;
+ }
+ column++;
+ if (column==columns) { // pixel packet run spans across rows
+ column=0;
+ if (row>0)
+ row--;
+ else
+ goto breakOut;
+ pixbuf = targa_rgba + row*columns*4;
+ }
+ }
+ }
+ }
+ breakOut:;
+ }
+ }
+
+ free(buffer);
+}
+
+
+
+
+void LoadJPG( const char *filename, unsigned char **pic, int *width, int *height )
+{
+ byte *fbuffer = NULL;
+ int nLen = LoadFile( ( char * ) filename, (void **)&fbuffer);
+ if (nLen == -1)
+ {
+ nLen = PakLoadAnyFile((char*)filename, (void**)&fbuffer);
+ if (nLen == -1)
+ {
+ return;
+ }
+ }
+ LoadJPGBuff(fbuffer, pic, width, height);
+ free(fbuffer);
+}
+
+//===================================================================
+
+/*
+=================
+LoadImage
+
+Loads any of the supported image types into a cannonical
+32 bit format.
+=================
+*/
+void LoadImage( const char *name, byte **pic, int *width, int *height )
+{
+ int len;
+ *pic = NULL;
+ *width = 0;
+ *height = 0;
+
+ len = strlen(name);
+ if (len<5)
+ {
+ return;
+ }
+
+ if ( !stricmp( name+len-4, ".tga" ) )
+ {
+ LoadTGA( name, pic, width, height );
+ }
+ else if ( !stricmp(name+len-4, ".pcx") )
+ {
+ LoadPCX32( name, pic, width, height );
+ }
+ else if ( !stricmp( name+len-4, ".bmp" ) )
+ {
+ LoadBMP( name, pic, width, height );
+ }
+ else if ( !stricmp( name+len-4, ".jpg" ) )
+ {
+ LoadJPG( name, pic, width, height );
+ }
+}
+
diff --git a/q3radiant/LBMLIB.H b/q3radiant/LBMLIB.H
new file mode 100755
index 0000000..16b747f
--- /dev/null
+++ b/q3radiant/LBMLIB.H
@@ -0,0 +1,40 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// piclib.h
+
+
+void LoadLBM (char *filename, byte **picture, byte **palette);
+void WriteLBMfile (char *filename, byte *data, int width, int height
+ , byte *palette);
+void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
+void WritePCXfile (char *filename, byte *data, int width, int height
+ , byte *palette);
+
+// loads / saves either lbm or pcx, depending on extension
+void Load256Image (char *name, byte **pixels, byte **palette,
+ int *width, int *height);
+void Save256Image (char *name, byte *pixels, byte *palette,
+ int width, int height);
+
+
+void LoadTGA (char *filename, byte **pixels, int *width, int *height);
+void LoadImage( const char *name, byte **pic, int *width, int *height );
diff --git a/q3radiant/LstToolBar.cpp b/q3radiant/LstToolBar.cpp
new file mode 100755
index 0000000..3c9e352
--- /dev/null
+++ b/q3radiant/LstToolBar.cpp
@@ -0,0 +1,59 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// LstToolBar.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "LstToolBar.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CLstToolBar
+
+CLstToolBar::CLstToolBar()
+{
+}
+
+CLstToolBar::~CLstToolBar()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CLstToolBar, CToolBar)
+ //{{AFX_MSG_MAP(CLstToolBar)
+ ON_WM_PARENTNOTIFY()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CLstToolBar message handlers
+
+void CLstToolBar::OnParentNotify(UINT message, LPARAM lParam)
+{
+ CToolBar::OnParentNotify(message, lParam);
+}
diff --git a/q3radiant/LstToolBar.h b/q3radiant/LstToolBar.h
new file mode 100755
index 0000000..acfb9a2
--- /dev/null
+++ b/q3radiant/LstToolBar.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_LSTTOOLBAR_H__279AAE23_78C5_11D1_B53C_00AA00A410FC__INCLUDED_)
+#define AFX_LSTTOOLBAR_H__279AAE23_78C5_11D1_B53C_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// LstToolBar.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CLstToolBar window
+
+class CLstToolBar : public CToolBar
+{
+// Construction
+public:
+ CLstToolBar();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CLstToolBar)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CLstToolBar();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CLstToolBar)
+ afx_msg void OnParentNotify(UINT message, LPARAM lParam);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_LSTTOOLBAR_H__279AAE23_78C5_11D1_B53C_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/MAP.CPP b/q3radiant/MAP.CPP
new file mode 100755
index 0000000..8207c54
--- /dev/null
+++ b/q3radiant/MAP.CPP
@@ -0,0 +1,1062 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// map.c
+
+#include "stdafx.h"
+#include "qe3.h"
+#include "PrefsDlg.h"
+
+qboolean modified; // for quit confirmation (0 = clean, 1 = unsaved,
+ // 2 = autosaved, but not regular saved)
+
+char currentmap[1024];
+
+
+brush_t active_brushes; // brushes currently being displayed
+brush_t selected_brushes; // highlighted
+
+face_t *selected_face;
+brush_t *selected_face_brush;
+
+brush_t filtered_brushes; // brushes that have been filtered or regioned
+
+entity_t entities; // head/tail of doubly linked list
+
+entity_t *world_entity = NULL; // "classname" "worldspawn" !
+
+void AddRegionBrushes (void);
+void RemoveRegionBrushes (void);
+
+
+void DupLists()
+{
+ DWORD dw = GetTickCount();
+
+}
+
+/*
+=============================================================
+
+ Cross map selection saving
+
+ this could fuck up if you have only part of a complex entity selected...
+=============================================================
+*/
+
+brush_t between_brushes;
+entity_t between_entities;
+
+bool g_bRestoreBetween = false;
+
+void Map_SaveBetween (void)
+{
+
+ if (g_pParentWnd->ActiveXY())
+ {
+ g_bRestoreBetween = true;
+ g_pParentWnd->ActiveXY()->Copy();
+ }
+ return;
+
+#if 0
+
+ brush_t *b;
+ entity_t *e, *e2;
+
+ between_brushes.next = selected_brushes.next;
+ between_brushes.prev = selected_brushes.prev;
+ between_brushes.next->prev = &between_brushes;
+ between_brushes.prev->next = &between_brushes;
+
+ between_entities.next = between_entities.prev = &between_entities;
+ selected_brushes.next = selected_brushes.prev = &selected_brushes;
+
+ for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
+ {
+ e = b->owner;
+ if (e == world_entity)
+ b->owner = NULL;
+ else
+ {
+ for (e2=between_entities.next ; e2 != &between_entities ; e2=e2->next)
+ if (e2 == e)
+ goto next; // allready got the entity
+ // move the entity over
+ e->prev->next = e->next;
+ e->next->prev = e->prev;
+ e->next = between_entities.next;
+ e->prev = &between_entities;
+ e->next->prev = e;
+ e->prev->next = e;
+ }
+next: ;
+ }
+#endif
+}
+
+void Map_RestoreBetween (void)
+{
+ if (g_pParentWnd->ActiveXY() && g_bRestoreBetween)
+ g_pParentWnd->ActiveXY()->Paste();
+ return;
+
+#if 0
+ entity_t *head, *tail;
+ brush_t *b;
+
+ if (!between_brushes.next)
+ return;
+
+ for (b=between_brushes.next ; b != &between_brushes ; b=b->next)
+ {
+ if (!b->owner)
+ {
+ b->owner = world_entity;
+ b->onext = world_entity->brushes.onext;
+ b->oprev = &world_entity->brushes;
+ b->onext->oprev = b;
+ b->oprev->onext = b;
+ }
+ }
+
+ selected_brushes.next = between_brushes.next;
+ selected_brushes.prev = between_brushes.prev;
+ selected_brushes.next->prev = &selected_brushes;
+ selected_brushes.prev->next = &selected_brushes;
+
+ head = between_entities.next;
+ tail = between_entities.prev;
+
+ if (head != tail)
+ {
+ entities.prev->next = head;
+ head->prev = entities.prev;
+ tail->next = &entities;
+ entities.prev = tail;
+ }
+
+ between_brushes.next = NULL;
+ between_entities.next = NULL;
+#endif
+}
+
+//============================================================================
+
+bool CheckForTinyBrush(brush_t* b, int n, float fSize)
+{
+ bool bTiny = false;
+ for (int i=0 ; i<3 ; i++)
+ {
+ if (b->maxs[i] - b->mins[i] < fSize)
+ bTiny = true;
+ }
+ if (bTiny)
+ Sys_Printf("Possible problem brush (too small) #%i ", n);
+ return bTiny;
+}
+
+void Map_BuildBrushData(void)
+{
+ brush_t *b, *next;
+
+ if (active_brushes.next == NULL)
+ return;
+
+ Sys_BeginWait (); // this could take a while
+
+ int n = 0;
+ for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
+ {
+ next = b->next;
+ Brush_Build( b, true, false, false );
+ if (!b->brush_faces || (g_PrefsDlg.m_bCleanTiny && CheckForTinyBrush(b, n++, g_PrefsDlg.m_fTinySize)))
+ {
+ Brush_Free (b);
+ Sys_Printf ("Removed degenerate brush\n");
+ }
+ }
+ Sys_EndWait();
+}
+
+entity_t *Map_FindClass (char *cname)
+{
+ entity_t *ent;
+
+ for (ent = entities.next ; ent != &entities ; ent=ent->next)
+ {
+ if (!strcmp(cname, ValueForKey (ent, "classname")))
+ return ent;
+ }
+ return NULL;
+}
+
+/*
+================
+Map_Free
+================
+*/
+void Map_Free (void)
+{
+ g_bRestoreBetween = false;
+ if (selected_brushes.next &&
+ (selected_brushes.next != &selected_brushes) )
+ {
+ if (MessageBox(g_qeglobals.d_hwndMain, "Copy selection?", "", MB_YESNO) == IDYES)
+ Map_SaveBetween ();
+ }
+
+ Texture_ClearInuse ();
+ Pointfile_Clear ();
+ strcpy (currentmap, "unnamed.map");
+ Sys_SetTitle (currentmap);
+ g_qeglobals.d_num_entities = 0;
+ g_qeglobals.d_numterrapoints = 0;
+
+ if (!active_brushes.next)
+ { // first map
+ active_brushes.prev = active_brushes.next = &active_brushes;
+ selected_brushes.prev = selected_brushes.next = &selected_brushes;
+ filtered_brushes.prev = filtered_brushes.next = &filtered_brushes;
+
+ entities.prev = entities.next = &entities;
+ }
+ else
+ {
+ while (active_brushes.next != &active_brushes)
+ Brush_Free (active_brushes.next);
+ while (selected_brushes.next != &selected_brushes)
+ Brush_Free (selected_brushes.next);
+ while (filtered_brushes.next != &filtered_brushes)
+ Brush_Free (filtered_brushes.next);
+
+ while (entities.next != &entities)
+ Entity_Free (entities.next);
+ }
+
+ if (world_entity)
+ Entity_Free(world_entity);
+ world_entity = NULL;
+}
+
+entity_t *AngledEntity()
+{
+ entity_t *ent = Map_FindClass ("info_player_start");
+ if (!ent)
+ {
+ ent = Map_FindClass ("info_player_deathmatch");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("info_player_deathmatch");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_redplayer");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_blueplayer");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_redspawn");
+ }
+ if (!ent)
+ {
+ ent = Map_FindClass ("team_CTF_bluespawn");
+ }
+ return ent;
+}
+
+
+
+/*
+================
+Map_LoadFile
+================
+*/
+void Map_LoadFile (char *filename)
+{
+ char *buf;
+ entity_t *ent;
+ char temp[1024];
+
+ Sys_BeginWait ();
+ Select_Deselect();
+ //SetInspectorMode(W_CONSOLE);
+
+ QE_ConvertDOSToUnixName( temp, filename );
+ Sys_Printf ("Map_LoadFile: %s\n", temp );
+
+ Map_Free ();
+ //++timo FIXME: maybe even easier to have Group_Init called from Map_Free?
+ Group_Init();
+
+ g_qeglobals.d_parsed_brushes = 0;
+ strcpy (currentmap, filename);
+
+ if (LoadFile (filename, (void **)&buf) != -1)
+ {
+
+ StartTokenParsing (buf);
+ g_qeglobals.d_num_entities = 0;
+
+ // Timo
+ // will be used in Entity_Parse to detect if a conversion between brush formats is needed
+ g_qeglobals.bNeedConvert = false;
+ g_qeglobals.bOldBrushes = false;
+ g_qeglobals.bPrimitBrushes = false;
+
+ while (1)
+ {
+ ent = Entity_Parse (false, &active_brushes);
+ if (!ent)
+ break;
+ if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
+ {
+ if (world_entity)
+ Sys_Printf ("WARNING: multiple worldspawn\n");
+ world_entity = ent;
+ }
+ else if (!strcmp(ValueForKey (ent, "classname"), "group_info"))
+ {
+ // it's a group thing!
+ Group_Add(ent);
+ Entity_Free(ent);
+ }
+ else
+ {
+ // add the entity to the end of the entity list
+ ent->next = &entities;
+ ent->prev = entities.prev;
+ entities.prev->next = ent;
+ entities.prev = ent;
+ g_qeglobals.d_num_entities++;
+ }
+ }
+ }
+
+ free (buf);
+
+ if (!world_entity)
+ {
+ Sys_Printf ("No worldspawn in map.\n");
+ Map_New ();
+ return;
+ }
+
+ Sys_Printf ("--- LoadMapFile ---\n");
+ Sys_Printf ("%s\n", temp );
+
+ Sys_Printf ("%5i brushes\n", g_qeglobals.d_parsed_brushes );
+ Sys_Printf ("%5i entities\n", g_qeglobals.d_num_entities);
+
+ Map_RestoreBetween ();
+
+ Sys_Printf ("Map_BuildAllDisplayLists\n");
+ Map_BuildBrushData();
+
+ // reset the "need conversion" flag
+ // conversion to the good format done in Map_BuildBrushData
+ g_qeglobals.bNeedConvert=false;
+
+ //
+ // move the view to a start position
+ //
+ ent = AngledEntity();
+
+ g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
+ if (ent)
+ {
+ GetVectorForKey (ent, "origin", g_pParentWnd->GetCamera()->Camera().origin);
+ GetVectorForKey (ent, "origin", g_pParentWnd->GetXYWnd()->GetOrigin());
+ g_pParentWnd->GetCamera()->Camera().angles[YAW] = FloatForKey (ent, "angle");
+ }
+ else
+ {
+ g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
+ VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
+ VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
+ }
+
+ Map_RegionOff ();
+
+
+ modified = false;
+ Sys_SetTitle (temp);
+
+ Texture_ShowInuse ();
+
+ Sys_EndWait();
+ Sys_UpdateWindows (W_ALL);
+
+}
+
+/*
+===========
+Map_SaveFile
+===========
+*/
+void Map_SaveFile (char *filename, qboolean use_region )
+{
+ entity_t *e, *next;
+ FILE *f;
+ char temp[1024];
+ int count;
+
+ if (filename == NULL || strlen(filename) == 0)
+ {
+ CFileDialog dlgSave(FALSE, "map", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Map Files (*.map)|*.map||", AfxGetMainWnd());
+ if (dlgSave.DoModal() == IDOK)
+ filename = strdup(dlgSave.m_ofn.lpstrFile);
+ else
+ return;
+ }
+
+ Pointfile_Clear ();
+ QE_ConvertDOSToUnixName( temp, filename );
+
+ if (!use_region)
+ {
+ char backup[1024];
+
+ // rename current to .bak
+ strcpy (backup, filename);
+ StripExtension (backup);
+ strcat (backup, ".bak");
+ _unlink (backup);
+ rename (filename, backup);
+ }
+
+ Sys_Printf ("Map_SaveFile: %s\n", filename);
+
+ f = fopen(filename, "w");
+
+ if (!f)
+ {
+ Sys_Printf ("ERROR!!!! Couldn't open %s\n", filename);
+ return;
+ }
+
+ if (use_region)
+ {
+ AddRegionBrushes ();
+ }
+
+ // write world entity first
+ Entity_Write (world_entity, f, use_region);
+
+ // then write all other ents
+ count = 1;
+ for (e=entities.next ; e != &entities ; e=next)
+ {
+ next = e->next;
+ if (e->brushes.onext == &e->brushes)
+ {
+ Entity_Free (e); // no brushes left, so remove it
+ }
+ else
+ {
+ fprintf (f, "// entity %i\n", count);
+ count++;
+ Entity_Write (e, f, use_region);
+ }
+ }
+
+ // save the group info stuff
+ Group_Save(f);
+
+ fclose (f);
+
+ if (use_region)
+ RemoveRegionBrushes ();
+
+ Sys_Printf ("Saved.\n");
+ modified = false;
+
+ if ( !strstr( temp, "autosave" ) )
+ Sys_SetTitle (temp);
+
+ if (!use_region)
+ {
+ time_t timer;
+ FILE *f;
+
+ time (&timer);
+ MessageBeep (MB_ICONEXCLAMATION);
+ f = fopen ("c:/tstamps.log", "a");
+ if (f)
+ {
+ fprintf (f, "%s", filename);
+ //fprintf (f, "%4i : %35s : %s", g_qeglobals.d_workcount, filename, ctime(&timer));
+ fclose (f);
+ g_qeglobals.d_workcount = 0;
+ }
+ fclose (f);
+ Sys_Status ("Saved.\n", 0);
+ }
+
+ //Curve_WriteFile (filename); //.trinity
+ //Patch_WriteFile (filename);
+}
+
+/*
+===========
+Map_New
+===========
+*/
+void Map_New (void)
+{
+ Sys_Printf ("Map_New\n");
+ Map_Free ();
+
+ Patch_Cleanup();
+
+ world_entity = (entity_s*)qmalloc(sizeof(*world_entity));
+ world_entity->brushes.onext =
+ world_entity->brushes.oprev = &world_entity->brushes;
+ SetKeyValue (world_entity, "classname", "worldspawn");
+ world_entity->eclass = Eclass_ForName ("worldspawn", true);
+
+ g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
+ g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
+ VectorCopy (vec3_origin, g_pParentWnd->GetCamera()->Camera().origin);
+ g_pParentWnd->GetCamera()->Camera().origin[2] = 48;
+ VectorCopy (vec3_origin, g_pParentWnd->GetXYWnd()->GetOrigin());
+
+ Map_RestoreBetween ();
+
+ Group_Init();
+
+ Sys_UpdateWindows (W_ALL);
+ modified = false;
+}
+
+/*
+===========================================================
+
+ REGION
+
+===========================================================
+*/
+
+qboolean region_active;
+vec3_t region_mins = {MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD};
+vec3_t region_maxs = {MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD};
+
+brush_t *region_sides[4];
+/*
+===========
+AddRegionBrushes
+
+a regioned map will have temp walls put up at the region boundary
+===========
+*/
+void AddRegionBrushes (void)
+{
+ vec3_t mins, maxs;
+ int i;
+ texdef_t td;
+
+ if (!region_active)
+ return;
+
+ memset (&td, 0, sizeof(td));
+ //strcpy (td.name, "REGION");
+ td.SetName("REGION");
+
+ mins[0] = region_mins[0] - 16;
+ maxs[0] = region_mins[0] + 1;
+ mins[1] = region_mins[1] - 16;
+ maxs[1] = region_maxs[1] + 16;
+ mins[2] = MIN_WORLD_COORD;
+ maxs[2] = MAX_WORLD_COORD;
+ region_sides[0] = Brush_Create (mins, maxs, &td);
+
+ mins[0] = region_maxs[0] - 1;
+ maxs[0] = region_maxs[0] + 16;
+ region_sides[1] = Brush_Create (mins, maxs, &td);
+
+ mins[0] = region_mins[0] - 16;
+ maxs[0] = region_maxs[0] + 16;
+ mins[1] = region_mins[1] - 16;
+ maxs[1] = region_mins[1] + 1;
+ region_sides[2] = Brush_Create (mins, maxs, &td);
+
+ mins[1] = region_maxs[1] - 1;
+ maxs[1] = region_maxs[1] + 16;
+ region_sides[3] = Brush_Create (mins, maxs, &td);
+
+ for (i=0 ; i<4 ; i++)
+ {
+ Brush_AddToList (region_sides[i], &selected_brushes);
+ Entity_LinkBrush (world_entity, region_sides[i]);
+ Brush_Build( region_sides[i] );
+ }
+}
+
+void RemoveRegionBrushes (void)
+{
+ int i;
+
+ if (!region_active)
+ return;
+ for (i=0 ; i<4 ; i++)
+ Brush_Free (region_sides[i]);
+}
+
+
+qboolean Map_IsBrushFiltered (brush_t *b)
+{
+ int i;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (b->mins[i] > region_maxs[i])
+ return true;
+ if (b->maxs[i] < region_mins[i])
+ return true;
+ }
+ return false;
+}
+
+/*
+===========
+Map_RegionOff
+
+Other filtering options may still be on
+===========
+*/
+void Map_RegionOff (void)
+{
+ brush_t *b, *next;
+ int i;
+
+ region_active = false;
+ for (i=0 ; i<3 ; i++)
+ {
+ region_maxs[i] = MAX_WORLD_COORD;//4096;
+ region_mins[i] = MIN_WORLD_COORD;//-4096;
+ }
+
+ for (b=filtered_brushes.next ; b != &filtered_brushes ; b=next)
+ {
+ next = b->next;
+ if (Map_IsBrushFiltered (b))
+ continue; // still filtered
+ Brush_RemoveFromList (b);
+ if (active_brushes.next == NULL || active_brushes.prev == NULL)
+ {
+ active_brushes.next = &active_brushes;
+ active_brushes.prev = &active_brushes;
+ }
+ Brush_AddToList (b, &active_brushes);
+ }
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Map_ApplyRegion (void)
+{
+ brush_t *b, *next;
+
+ region_active = true;
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+ if (!Map_IsBrushFiltered (b))
+ continue; // still filtered
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &filtered_brushes);
+ }
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+========================
+Map_RegionSelectedBrushes
+========================
+*/
+void Map_RegionSelectedBrushes (void)
+{
+ Map_RegionOff ();
+
+ if (selected_brushes.next == &selected_brushes) // nothing selected
+ {
+ Sys_Printf("Tried to region with no selection...\n");
+ return;
+ }
+ region_active = true;
+ Select_GetBounds (region_mins, region_maxs);
+
+ // move the entire active_brushes list to filtered_brushes
+ filtered_brushes.next = active_brushes.next;
+ filtered_brushes.prev = active_brushes.prev;
+ filtered_brushes.next->prev = &filtered_brushes;
+ filtered_brushes.prev->next = &filtered_brushes;
+
+ // move the entire selected_brushes list to active_brushes
+ active_brushes.next = selected_brushes.next;
+ active_brushes.prev = selected_brushes.prev;
+ active_brushes.next->prev = &active_brushes;
+ active_brushes.prev->next = &active_brushes;
+
+ // clear selected_brushes
+ selected_brushes.next = selected_brushes.prev = &selected_brushes;
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+===========
+Map_RegionXY
+===========
+*/
+void Map_RegionXY (void)
+{
+ Map_RegionOff ();
+
+ region_mins[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] - 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
+ region_maxs[0] = g_pParentWnd->GetXYWnd()->GetOrigin()[0] + 0.5 * g_pParentWnd->GetXYWnd()->Width() / g_pParentWnd->GetXYWnd()->Scale();
+ region_mins[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] - 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
+ region_maxs[1] = g_pParentWnd->GetXYWnd()->GetOrigin()[1] + 0.5 * g_pParentWnd->GetXYWnd()->Height() / g_pParentWnd->GetXYWnd()->Scale();
+ region_mins[2] = -MIN_WORLD_COORD;
+ region_maxs[2] = MAX_WORLD_COORD;
+ Map_ApplyRegion ();
+}
+
+/*
+===========
+Map_RegionTallBrush
+===========
+*/
+void Map_RegionTallBrush (void)
+{
+ brush_t *b;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ b = selected_brushes.next;
+
+ Map_RegionOff ();
+
+ VectorCopy (b->mins, region_mins);
+ VectorCopy (b->maxs, region_maxs);
+ region_mins[2] = MIN_WORLD_COORD;
+ region_maxs[2] = MAX_WORLD_COORD;
+
+
+ Select_Delete ();
+ Map_ApplyRegion ();
+}
+/*
+===========
+Map_RegionBrush
+===========
+*/
+void Map_RegionBrush (void)
+{
+ brush_t *b;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ b = selected_brushes.next;
+
+ Map_RegionOff ();
+
+ VectorCopy (b->mins, region_mins);
+ VectorCopy (b->maxs, region_maxs);
+
+ Select_Delete ();
+ Map_ApplyRegion ();
+}
+
+
+
+void UniqueTargetName(CString& rStr)
+{
+ // make a unique target value
+ int maxtarg = 0;
+ for (entity_t* e=entities.next ; e != &entities ; e=e->next)
+ {
+ char* tn = ValueForKey (e, "targetname");
+ if (tn && tn[0])
+ {
+ int targetnum = atoi(tn+1);
+ if (targetnum > maxtarg)
+ maxtarg = targetnum;
+ }
+ else
+ {
+ tn = ValueForKey (e, "target");
+ if (tn && tn[0])
+ {
+ int targetnum = atoi(tn+1);
+ if (targetnum > maxtarg)
+ maxtarg = targetnum;
+ }
+ }
+ }
+ rStr.Format("t%i", maxtarg+1);
+}
+
+//
+//================
+//Map_ImportFile
+// Timo 09/01/99 : called by CXYWnd::Paste & Map_ImportFile
+// if Map_ImportFile ( prefab ), the buffer may contain brushes in old format ( conversion needed )
+//================
+//
+void Map_ImportBuffer (char* buf)
+{
+ entity_t* ent;
+ brush_t* b = NULL;
+ CPtrArray ptrs;
+
+ Select_Deselect();
+
+ Undo_Start("import buffer");
+
+ g_qeglobals.d_parsed_brushes = 0;
+ if (buf)
+ {
+ CMapStringToString mapStr;
+ StartTokenParsing (buf);
+ g_qeglobals.d_num_entities = 0;
+
+ // Timo
+ // will be used in Entity_Parse to detect if a conversion between brush formats is needed
+ g_qeglobals.bNeedConvert = false;
+ g_qeglobals.bOldBrushes = false;
+ g_qeglobals.bPrimitBrushes = false;
+
+ while (1)
+ {
+
+ // use the selected brushes list as it's handy
+ //ent = Entity_Parse (false, &selected_brushes);
+ ent = Entity_Parse (false, &active_brushes);
+ if (!ent)
+ break;
+ //end entity for undo
+ Undo_EndEntity(ent);
+ //end brushes for undo
+ for(b = ent->brushes.onext; b && b != &ent->brushes; b = b->onext)
+ {
+ Undo_EndBrush(b);
+ }
+
+ if (!strcmp(ValueForKey (ent, "classname"), "worldspawn"))
+ {
+ // world brushes need to be added to the current world entity
+
+ b=ent->brushes.onext;
+ while (b && b != &ent->brushes)
+ {
+ brush_t* bNext = b->onext;
+ Entity_UnlinkBrush(b);
+ Entity_LinkBrush(world_entity, b);
+ ptrs.Add(b);
+ b = bNext;
+ }
+ }
+ else
+ {
+ // the following bit remaps conflicting target/targetname key/value pairs
+ CString str = ValueForKey(ent, "target");
+ CString strKey;
+ CString strTarget("");
+ if (str.GetLength() > 0)
+ {
+ if (FindEntity("target", str.GetBuffer(0)))
+ {
+ if (!mapStr.Lookup(str, strKey))
+ {
+ UniqueTargetName(strKey);
+ mapStr.SetAt(str, strKey);
+ }
+ strTarget = strKey;
+ SetKeyValue(ent, "target", strTarget.GetBuffer(0));
+ }
+ }
+ str = ValueForKey(ent, "targetname");
+ if (str.GetLength() > 0)
+ {
+ if (FindEntity("targetname", str.GetBuffer(0)))
+ {
+ if (!mapStr.Lookup(str, strKey))
+ {
+ UniqueTargetName(strKey);
+ mapStr.SetAt(str, strKey);
+ }
+ SetKeyValue(ent, "targetname", strKey.GetBuffer(0));
+ }
+ }
+ //if (strTarget.GetLength() > 0)
+ // SetKeyValue(ent, "target", strTarget.GetBuffer(0));
+
+ // add the entity to the end of the entity list
+ ent->next = &entities;
+ ent->prev = entities.prev;
+ entities.prev->next = ent;
+ entities.prev = ent;
+ g_qeglobals.d_num_entities++;
+
+ for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
+ {
+ ptrs.Add(b);
+ }
+ }
+ }
+ }
+
+ //::ShowWindow(g_qeglobals.d_hwndEntity, FALSE);
+ //::LockWindowUpdate(g_qeglobals.d_hwndEntity);
+ g_bScreenUpdates = false;
+ for (int i = 0; i < ptrs.GetSize(); i++)
+ {
+ Brush_Build(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
+ Select_Brush(reinterpret_cast<brush_t*>(ptrs[i]), true, false);
+ }
+ //::LockWindowUpdate(NULL);
+ g_bScreenUpdates = true;
+
+ ptrs.RemoveAll();
+
+ // reset the "need conversion" flag
+ // conversion to the good format done in Map_BuildBrushData
+ g_qeglobals.bNeedConvert=false;
+
+ Sys_UpdateWindows (W_ALL);
+ //Sys_MarkMapModified();
+ modified = true;
+
+ Undo_End();
+
+}
+
+
+//
+//================
+//Map_ImportFile
+//================
+//
+void Map_ImportFile (char *filename)
+{
+ char* buf;
+ char temp[1024];
+ Sys_BeginWait ();
+ QE_ConvertDOSToUnixName( temp, filename );
+ if (LoadFile (filename, (void **)&buf) != -1)
+ {
+ Map_ImportBuffer(buf);
+ free(buf);
+ Map_BuildBrushData();
+ }
+ Sys_UpdateWindows (W_ALL);
+ modified = true;
+ Sys_EndWait();
+}
+
+//
+//===========
+//Map_SaveSelected
+//===========
+//
+// Saves selected world brushes and whole entities with partial/full selections
+//
+void Map_SaveSelected(char* pFilename)
+{
+ entity_t *e, *next;
+ FILE *f;
+ char temp[1024];
+ int count;
+
+ QE_ConvertDOSToUnixName(temp, pFilename);
+ f = fopen(pFilename, "w");
+
+ if (!f)
+ {
+ Sys_Printf ("ERROR!!!! Couldn't open %s\n", pFilename);
+ return;
+ }
+
+ // write world entity first
+ Entity_WriteSelected(world_entity, f);
+
+ // then write all other ents
+ count = 1;
+ for (e=entities.next ; e != &entities ; e=next)
+ {
+ fprintf (f, "// entity %i\n", count);
+ count++;
+ Entity_WriteSelected(e, f);
+ next = e->next;
+ }
+ fclose (f);
+}
+
+
+//
+//===========
+//Map_SaveSelected
+//===========
+//
+// Saves selected world brushes and whole entities with partial/full selections
+//
+void Map_SaveSelected(CMemFile* pMemFile, CMemFile* pPatchFile)
+{
+ entity_t *e, *next;
+ int count;
+ CString strTemp;
+
+ // write world entity first
+ Entity_WriteSelected(world_entity, pMemFile);
+
+ // then write all other ents
+ count = 1;
+ for (e=entities.next ; e != &entities ; e=next)
+ {
+ MemFile_fprintf(pMemFile, "// entity %i\n", count);
+ count++;
+ Entity_WriteSelected(e, pMemFile);
+ next = e->next;
+ }
+
+ //if (pPatchFile)
+ // Patch_WriteFile(pPatchFile);
+}
+
+
+void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...)
+{
+ char Buffer[4096];
+ va_list args;
+ va_start (args,pText);
+ vsprintf(Buffer, pText, args);
+ pMemFile->Write(Buffer, strlen(Buffer));
+} \ No newline at end of file
diff --git a/q3radiant/MAP.H b/q3radiant/MAP.H
new file mode 100755
index 0000000..8c1c070
--- /dev/null
+++ b/q3radiant/MAP.H
@@ -0,0 +1,59 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// map.h -- the state of the current world that all views are displaying
+
+extern char currentmap[1024];
+
+// head/tail of doubly linked lists
+extern brush_t active_brushes; // brushes currently being displayed
+extern brush_t selected_brushes; // highlighted
+
+
+extern CPtrArray& g_ptrSelectedFaces;
+extern CPtrArray& g_ptrSelectedFaceBrushes;
+//extern face_t *selected_face;
+//extern brush_t *selected_face_brush;
+extern brush_t filtered_brushes; // brushes that have been filtered or regioned
+
+extern entity_t entities;
+extern entity_t *world_entity; // the world entity is NOT included in
+ // the entities chain
+
+extern qboolean modified; // for quit confirmations
+
+extern vec3_t region_mins, region_maxs;
+extern qboolean region_active;
+
+void Map_LoadFile (char *filename);
+void Map_SaveFile (char *filename, qboolean use_region);
+void Map_New (void);
+void Map_BuildBrushData(void);
+
+void Map_RegionOff (void);
+void Map_RegionXY (void);
+void Map_RegionTallBrush (void);
+void Map_RegionBrush (void);
+void Map_RegionSelectedBrushes (void);
+qboolean Map_IsBrushFiltered (brush_t *b);
+
+void Map_SaveSelected(CMemFile* pMemFile, CMemFile* pPatchFile = NULL);
+void Map_ImportBuffer (char* buf);
diff --git a/q3radiant/MATHLIB.CPP b/q3radiant/MATHLIB.CPP
new file mode 100755
index 0000000..d112578
--- /dev/null
+++ b/q3radiant/MATHLIB.CPP
@@ -0,0 +1,311 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// mathlib.c -- math primitives
+
+#include "stdafx.h"
+#include "cmdlib.h"
+#include "mathlib.h"
+
+vec3_t vec3_origin = {0.0f,0.0f,0.0f};
+
+
+float VectorLength(vec3_t v)
+{
+ int i;
+ float length;
+
+ length = 0.0f;
+ for (i=0 ; i< 3 ; i++)
+ length += v[i]*v[i];
+ length = (float)sqrt (length);
+
+ return length;
+}
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2)
+{
+ int i;
+
+ for (i=0 ; i<3 ; i++)
+ if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
+ return false;
+
+ return true;
+}
+
+vec_t Q_rint (vec_t in)
+{
+ if (g_PrefsDlg.m_bNoClamp)
+ return in;
+ else
+ return (float)floor (in + 0.5);
+}
+
+void VectorMA (vec3_t va, float scale, vec3_t vb, vec3_t vc)
+{
+ vc[0] = va[0] + scale*vb[0];
+ vc[1] = va[1] + scale*vb[1];
+ vc[2] = va[2] + scale*vb[2];
+}
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
+{
+ cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
+ cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
+ cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+vec_t _DotProduct (vec3_t v1, vec3_t v2)
+{
+ return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
+{
+ out[0] = va[0]-vb[0];
+ out[1] = va[1]-vb[1];
+ out[2] = va[2]-vb[2];
+}
+
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
+{
+ out[0] = va[0]+vb[0];
+ out[1] = va[1]+vb[1];
+ out[2] = va[2]+vb[2];
+}
+
+void _VectorCopy (vec3_t in, vec3_t out)
+{
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+}
+
+vec_t VectorNormalize (vec3_t v)
+{
+ int i;
+ float length;
+
+ length = 0.0f;
+ for (i=0 ; i< 3 ; i++)
+ length += v[i]*v[i];
+ length = (float)sqrt (length);
+ if (length == 0)
+ return (vec_t)0;
+
+ for (i=0 ; i< 3 ; i++)
+ v[i] /= length;
+
+ return length;
+}
+
+void VectorInverse (vec3_t v)
+{
+ v[0] = -v[0];
+ v[1] = -v[1];
+ v[2] = -v[2];
+}
+
+void VectorScale (vec3_t v, vec_t scale, vec3_t out)
+{
+ out[0] = v[0] * scale;
+ out[1] = v[1] * scale;
+ out[2] = v[2] * scale;
+}
+
+
+void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t out)
+{
+ vec3_t vWork, va;
+ VectorCopy(vIn, va);
+ VectorCopy(va, vWork);
+ int nIndex[3][2];
+ nIndex[0][0] = 1; nIndex[0][1] = 2;
+ nIndex[1][0] = 2; nIndex[1][1] = 0;
+ nIndex[2][0] = 0; nIndex[2][1] = 1;
+
+ for (int i = 0; i < 3; i++)
+ {
+ if (vRotation[i] != 0)
+ {
+ double dAngle = vRotation[i] * Q_PI / 180.0;
+ double c = cos(dAngle);
+ double s = sin(dAngle);
+ vWork[nIndex[i][0]] = va[nIndex[i][0]] * c - va[nIndex[i][1]] * s;
+ vWork[nIndex[i][1]] = va[nIndex[i][0]] * s + va[nIndex[i][1]] * c;
+ }
+ VectorCopy(vWork, va);
+ }
+ VectorCopy(vWork, out);
+}
+
+void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out)
+{
+ vec3_t vTemp, vTemp2;
+ VectorSubtract(vIn, vOrigin, vTemp);
+ VectorRotate(vTemp, vRotation, vTemp2);
+ VectorAdd(vTemp2, vOrigin, out);
+}
+
+void VectorPolar(vec3_t v, float radius, float theta, float phi)
+{
+ v[0]=float(radius * cos(theta) * cos(phi));
+ v[1]=float(radius * sin(theta) * cos(phi));
+ v[2]=float(radius * sin(phi));
+}
+
+void VectorSnap(vec3_t v)
+{
+ for (int i = 0; i < 3; i++)
+ {
+ v[i] = floor (v[i] + 0.5);
+ }
+}
+
+
+void _Vector5Add (vec5_t va, vec5_t vb, vec5_t out)
+{
+ out[0] = va[0]+vb[0];
+ out[1] = va[1]+vb[1];
+ out[2] = va[2]+vb[2];
+ out[3] = va[3]+vb[3];
+ out[4] = va[4]+vb[4];
+}
+
+void _Vector5Scale (vec5_t v, vec_t scale, vec5_t out)
+{
+ out[0] = v[0] * scale;
+ out[1] = v[1] * scale;
+ out[2] = v[2] * scale;
+ out[3] = v[3] * scale;
+ out[4] = v[4] * scale;
+}
+
+void _Vector53Copy (vec5_t in, vec3_t out)
+{
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+}
+
+// NOTE: added these from Ritual's Q3Radiant
+void ClearBounds (vec3_t mins, vec3_t maxs)
+{
+ mins[0] = mins[1] = mins[2] = 99999;
+ maxs[0] = maxs[1] = maxs[2] = -99999;
+}
+
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
+{
+ int i;
+ vec_t val;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ val = v[i];
+ if (val < mins[i])
+ mins[i] = val;
+ if (val > maxs[i])
+ maxs[i] = val;
+ }
+}
+
+#define PITCH 0 // up / down
+#define YAW 1 // left / right
+#define ROLL 2 // fall over
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+#endif
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
+{
+ float angle;
+ static float sr, sp, sy, cr, cp, cy;
+ // static to help MS compiler fp bugs
+
+ angle = angles[YAW] * (M_PI*2 / 360);
+ sy = sin(angle);
+ cy = cos(angle);
+ angle = angles[PITCH] * (M_PI*2 / 360);
+ sp = sin(angle);
+ cp = cos(angle);
+ angle = angles[ROLL] * (M_PI*2 / 360);
+ sr = sin(angle);
+ cr = cos(angle);
+
+ if (forward)
+ {
+ forward[0] = cp*cy;
+ forward[1] = cp*sy;
+ forward[2] = -sp;
+ }
+ if (right)
+ {
+ right[0] = -sr*sp*cy+cr*sy;
+ right[1] = -sr*sp*sy-cr*cy;
+ right[2] = -sr*cp;
+ }
+ if (up)
+ {
+ up[0] = cr*sp*cy+sr*sy;
+ up[1] = cr*sp*sy-sr*cy;
+ up[2] = cr*cp;
+ }
+}
+
+void VectorToAngles( vec3_t vec, vec3_t angles )
+{
+ float forward;
+ float yaw, pitch;
+
+ if ( ( vec[ 0 ] == 0 ) && ( vec[ 1 ] == 0 ) )
+ {
+ yaw = 0;
+ if ( vec[ 2 ] > 0 )
+ {
+ pitch = 90;
+ }
+ else
+ {
+ pitch = 270;
+ }
+ }
+ else
+ {
+ yaw = atan2( vec[ 1 ], vec[ 0 ] ) * 180 / M_PI;
+ if ( yaw < 0 )
+ {
+ yaw += 360;
+ }
+
+ forward = ( float )sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] );
+ pitch = atan2( vec[ 2 ], forward ) * 180 / M_PI;
+ if ( pitch < 0 )
+ {
+ pitch += 360;
+ }
+ }
+
+ angles[ 0 ] = pitch;
+ angles[ 1 ] = yaw;
+ angles[ 2 ] = 0;
+}
diff --git a/q3radiant/MATHLIB.H b/q3radiant/MATHLIB.H
new file mode 100755
index 0000000..6119be8
--- /dev/null
+++ b/q3radiant/MATHLIB.H
@@ -0,0 +1,86 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __MATHLIB__
+#define __MATHLIB__
+
+// mathlib.h
+
+#include <math.h>
+
+typedef float vec_t;
+typedef vec_t vec3_t[3];
+typedef vec_t vec5_t[5];
+
+#define SIDE_FRONT 0
+#define SIDE_ON 2
+#define SIDE_BACK 1
+#define SIDE_CROSS -2
+
+#define Q_PI 3.14159265358979323846
+
+extern vec3_t vec3_origin;
+
+#define EQUAL_EPSILON 0.001
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2);
+
+#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
+#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
+#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
+#define VectorSet(v, a, b, c) {v[0]=a;v[1]=b;v[2]=c;}
+
+vec_t Q_rint (vec_t in);
+vec_t _DotProduct (vec3_t v1, vec3_t v2);
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorCopy (vec3_t in, vec3_t out);
+
+float VectorLength(vec3_t v);
+
+void VectorMA (vec3_t va, float scale, vec3_t vb, vec3_t vc);
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
+vec_t VectorNormalize (vec3_t v);
+void VectorInverse (vec3_t v);
+void VectorScale (vec3_t v, vec_t scale, vec3_t out);
+void VectorPolar(vec3_t v, float radius, float theta, float phi);
+void VectorSnap(vec3_t v);
+
+void _Vector53Copy (vec5_t in, vec3_t out);
+void _Vector5Scale (vec5_t v, vec_t scale, vec5_t out);
+void _Vector5Add (vec5_t va, vec5_t vb, vec5_t out);
+
+// NOTE: added these from Ritual's Q3Radiant
+void ClearBounds (vec3_t mins, vec3_t maxs);
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
+void VectorToAngles( vec3_t vec, vec3_t angles );
+#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
+
+#define ZERO_EPSILON 1.0E-6
+#define RAD2DEG( a ) ( ( (a) * 180.0f ) / Q_PI )
+#define DEG2RAD( a ) ( ( (a) * Q_PI ) / 180.0f )
+
+
+#endif
diff --git a/q3radiant/MRU.CPP b/q3radiant/MRU.CPP
new file mode 100755
index 0000000..d675362
--- /dev/null
+++ b/q3radiant/MRU.CPP
@@ -0,0 +1,671 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//*************************************************************
+// File name: mru.c
+//
+// Description:
+//
+// Routines for MRU support
+//
+// Development Team:
+//
+// Gilles Vollant (100144.2636@compuserve.com)
+//
+//*************************************************************
+
+#include "stdafx.h"
+#include <windows.h>
+#include <windowsx.h>
+#include <string.h>
+
+#include "mru.h"
+// CreateMruMenu : MRUMENU constructor
+// wNbLruShowInit : nb of item showed in menu
+// wNbLruMenuInit : nb of item stored in memory
+// wMaxSizeLruItemInit : size max. of filename
+
+
+//*************************************************************
+//
+// CreateMruMenu()
+//
+// Purpose:
+//
+// Allocate and Initialize an MRU and return a pointer on it
+//
+//
+// Parameters:
+//
+// WORD wNbLruShowInit - Maximum number of item displayed on menu
+// WORD wNbLruMenuInit - Maximum number of item stored in memory
+// WORD wMaxSizeLruItemInit - Maximum size of an item (ie size of pathname)
+// WORD wIdMruInit - ID of the first item in the menu (default:IDMRU)
+//
+//
+// Return: (LPMRUMENU)
+//
+// Pointer on a MRUMENU structure, used by other function
+//
+//
+// Comments:
+// wNbLruShowInit <= wNbLruMenuInit
+//
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+
+LPMRUMENU CreateMruMenu (WORD wNbLruShowInit,
+ WORD wNbLruMenuInit,WORD wMaxSizeLruItemInit,WORD wIdMruInit)
+{
+LPMRUMENU lpMruMenu;
+ lpMruMenu = (LPMRUMENU)GlobalAllocPtr(GHND,sizeof(MRUMENU));
+
+ lpMruMenu->wNbItemFill = 0;
+ lpMruMenu->wNbLruMenu = wNbLruMenuInit;
+ lpMruMenu->wNbLruShow = wNbLruShowInit;
+ lpMruMenu->wIdMru = wIdMruInit;
+ lpMruMenu->wMaxSizeLruItem = wMaxSizeLruItemInit;
+ lpMruMenu->lpMRU = (LPSTR)GlobalAllocPtr(GHND,
+ lpMruMenu->wNbLruMenu*(UINT)lpMruMenu->wMaxSizeLruItem);
+ if (lpMruMenu->lpMRU == NULL)
+ {
+ GlobalFreePtr(lpMruMenu);
+ lpMruMenu = NULL;
+ }
+ return lpMruMenu;
+}
+
+//*************************************************************
+//
+// CreateMruMenuDefault()
+//
+// Purpose:
+//
+// Allocate and Initialize an MRU and return a pointer on it
+// Use default parameter
+//
+//
+// Parameters:
+//
+//
+// Return: (LPMRUMENU)
+//
+// Pointer on a MRUMENU structure, used by other function
+//
+//
+// Comments:
+//
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+
+LPMRUMENU CreateMruMenuDefault()
+{
+ return CreateMruMenu (NBMRUMENUSHOW,NBMRUMENU,MAXSIZEMRUITEM,IDMRU);
+}
+
+
+//*************************************************************
+//
+// DeleteMruMenu()
+//
+// Purpose:
+// Destructor :
+// Clean and free a MRUMENU structure
+//
+// Parameters:
+//
+// LPMRUMENU lpMruMenu - pointer on MRUMENU, allocated
+// by CreateMruMenu() or CreateMruMenuDefault()
+//
+//
+// Return: void
+//
+//
+// Comments:
+//
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+void DeleteMruMenu(LPMRUMENU lpMruMenu)
+{
+ GlobalFreePtr(lpMruMenu->lpMRU);
+ GlobalFreePtr(lpMruMenu);
+}
+
+//*************************************************************
+//
+// SetNbLruShow()
+//
+// Purpose:
+// Change the maximum number of item displayed on menu
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// WORD wNbLruShowInit - Maximum number of item displayed on menu
+//
+//
+// Return: void
+//
+//
+// Comments:
+//
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+void SetNbLruShow (LPMRUMENU lpMruMenu,WORD wNbLruShowInit)
+{
+ lpMruMenu->wNbLruShow = min(wNbLruShowInit,lpMruMenu->wNbLruMenu);
+}
+
+//*************************************************************
+//
+// SetMenuItem()
+//
+// Purpose:
+// Set the filename of an item
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// WORD wItem - Number of Item to set, zero based
+// LPSTR lpItem - String, contain the filename of the item
+//
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// used when load .INI or reg database
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL SetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,LPSTR lpItem)
+{
+ if (wItem >= NBMRUMENU)
+ return FALSE;
+ _fstrncpy((lpMruMenu->lpMRU) +
+ ((lpMruMenu->wMaxSizeLruItem) * (UINT)wItem),
+ lpItem,lpMruMenu->wMaxSizeLruItem-1);
+ lpMruMenu->wNbItemFill = max(lpMruMenu->wNbItemFill,wItem+1);
+ return TRUE;
+}
+
+//*************************************************************
+//
+// GetMenuItem()
+//
+// Purpose:
+// Get the filename of an item
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// WORD wItem - Number of Item to set, zero based
+// BOOL fIDMBased - TRUE : wItem is based on ID menu item
+// FALSE : wItem is zero-based
+// LPSTR lpItem - String where the filename of the item will be
+// stored by GetMenuItem()
+// UINT uiSize - Size of the lpItem buffer
+//
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// Used for saving in .INI or reg database, or when user select
+// an MRU in File menu
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL GetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,
+ BOOL fIDMBased,LPSTR lpItem,UINT uiSize)
+{
+ if (fIDMBased)
+ wItem -= (lpMruMenu->wIdMru + 1);
+ if (wItem >= lpMruMenu->wNbItemFill)
+ return FALSE;
+ _fstrncpy(lpItem,(lpMruMenu->lpMRU) +
+ ((lpMruMenu->wMaxSizeLruItem) * (UINT)(wItem)),uiSize);
+ *(lpItem+uiSize-1) = '\0';
+ return TRUE;
+}
+
+//*************************************************************
+//
+// AddNewItem()
+//
+// Purpose:
+// Add an item at the begin of the list
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// LPSTR lpItem - String contain the filename to add
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// Used when used open a file (using File Open common
+// dialog, Drag and drop or MRU)
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+void AddNewItem (LPMRUMENU lpMruMenu,LPSTR lpItem)
+{
+WORD i,j;
+ for (i=0;i<lpMruMenu->wNbItemFill;i++)
+ if (lstrcmpi(lpItem,(lpMruMenu->lpMRU) +
+ ((lpMruMenu->wMaxSizeLruItem) * (UINT)i)) == 0)
+ {
+ // Shift the other items
+ for (j=i;j>0;j--)
+ lstrcpy((lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)j),
+ (lpMruMenu->lpMRU) + (lpMruMenu->wMaxSizeLruItem * (UINT)(j-1)));
+ _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1);
+ return ;
+ }
+ lpMruMenu->wNbItemFill = min(lpMruMenu->wNbItemFill+1,lpMruMenu->wNbLruMenu);
+ for (i=lpMruMenu->wNbItemFill-1;i>0;i--)
+ lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i),
+ lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i-1)));
+ _fstrncpy(lpMruMenu->lpMRU,lpItem,lpMruMenu->wMaxSizeLruItem-1);
+}
+
+//*************************************************************
+//
+// DelMenuItem()
+//
+// Purpose:
+// Delete an item
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// WORD wItem - Number of Item to set, zero based
+// BOOL fIDMBased - TRUE : wItem is based on ID menu item
+// FALSE : wItem is zero-based
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// Used when used open a file, using MRU, and when an error
+// occured (by example, when file was deleted)
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL DelMenuItem(LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased)
+{
+WORD i;
+ if (fIDMBased)
+ wItem -= (lpMruMenu->wIdMru + 1);
+ if (lpMruMenu->wNbItemFill <= wItem)
+ return FALSE;
+ lpMruMenu->wNbItemFill--;
+ for (i=wItem;i<lpMruMenu->wNbItemFill;i++)
+ lstrcpy(lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)i),
+ lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem * (UINT)(i+1)));
+ return TRUE;
+}
+
+//*************************************************************
+//
+// PlaceMenuMRUItem()
+//
+// Purpose:
+// Add MRU at the end of a menu
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// HMENU hMenu - Handle of menu where MRU must be added
+// UINT uiItem - Item of menu entry where MRU must be added
+//
+// Return: void
+//
+//
+// Comments:
+// Used MRU is modified, for refresh the File menu
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+void PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem)
+{
+int i;
+WORD wNbShow;
+ if (hMenu == NULL)
+ return;
+ // remove old MRU in menu
+ for (i=0;i<=(int)(lpMruMenu->wNbLruMenu);i++)
+ RemoveMenu(hMenu,i+lpMruMenu->wIdMru,MF_BYCOMMAND);
+
+ if (lpMruMenu->wNbItemFill == 0)
+ return;
+
+ // If they are item, insert a separator before the files
+ InsertMenu(hMenu,uiItem,MF_SEPARATOR,lpMruMenu->wIdMru,NULL);
+
+ wNbShow = min(lpMruMenu->wNbItemFill,lpMruMenu->wNbLruShow);
+ for (i=(int)wNbShow-1;i>=0;i--)
+ {
+ LPSTR lpTxt;
+ if (lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20))
+ {
+ wsprintf(lpTxt,"&%lu %s",
+ (DWORD)(i+1),lpMruMenu->lpMRU + (lpMruMenu->wMaxSizeLruItem*(UINT)i));
+ InsertMenu(hMenu,(((WORD)i)!=(wNbShow-1)) ? (lpMruMenu->wIdMru+i+2) : lpMruMenu->wIdMru,
+ MF_STRING,lpMruMenu->wIdMru+i+1,lpTxt);
+ GlobalFreePtr(lpTxt);
+ }
+ }
+
+}
+
+///////////////////////////////////////////
+
+
+
+//*************************************************************
+//
+// SaveMruInIni()
+//
+// Purpose:
+// Save MRU in a private .INI
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// LPSTR lpszSection - Points to a null-terminated string containing
+// the name of the section
+// LPSTR lpszFile - Points to a null-terminated string that names
+// the initialization file.
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// See WritePrivateProfileString API for more info on lpszSection and lpszFile
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL SaveMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)
+{
+LPSTR lpTxt;
+WORD i;
+
+ lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
+ if (lpTxt == NULL)
+ return FALSE;
+
+ for (i=0;i<lpMruMenu->wNbLruMenu;i++)
+ {
+ char szEntry[16];
+ wsprintf(szEntry,"File%lu",(DWORD)i+1);
+ if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10))
+ *lpTxt = '\0';
+ WritePrivateProfileString(lpszSection,szEntry,lpTxt,lpszFile);
+ }
+ GlobalFreePtr(lpTxt);
+ WritePrivateProfileString(NULL,NULL,NULL,lpszFile); // flush cache
+ return TRUE;
+}
+
+
+//*************************************************************
+//
+// LoadMruInIni()
+//
+// Purpose:
+// Load MRU from a private .INI
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// LPSTR lpszSection - Points to a null-terminated string containing
+// the name of the section
+// LPSTR lpszFile - Points to a null-terminated string that names
+// the initialization file.
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// See GetPrivateProfileString API for more info on lpszSection and lpszFile
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL LoadMruInIni(LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile)
+{
+LPSTR lpTxt;
+WORD i;
+ lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
+ if (lpTxt == NULL)
+ return FALSE;
+
+ for (i=0;i<lpMruMenu->wNbLruMenu;i++)
+ {
+ char szEntry[16];
+
+ wsprintf(szEntry,"File%lu",(DWORD)i+1);
+ GetPrivateProfileString(lpszSection,szEntry,"",lpTxt,
+ lpMruMenu->wMaxSizeLruItem + 10,lpszFile);
+ if (*lpTxt == '\0')
+ break;
+ SetMenuItem(lpMruMenu,i,lpTxt);
+ }
+ GlobalFreePtr(lpTxt);
+ return TRUE;
+}
+
+#ifdef WIN32
+
+BOOL IsWin395OrHigher(void)
+{
+ WORD wVer;
+
+ wVer = LOWORD(GetVersion());
+ wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer);
+
+ return (wVer >= 0x035F); // 5F = 95 dec
+}
+
+
+//*************************************************************
+//
+// SaveMruInReg()
+//
+// Purpose:
+// Save MRU in the registry
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// LPSTR lpszKey - Points to a null-terminated string
+// specifying the name of a key that
+// this function opens or creates.
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// Win32 function designed for Windows NT and Windows 95
+// See RegCreateKeyEx API for more info on lpszKey
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL SaveMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)
+{
+LPSTR lpTxt;
+WORD i;
+HKEY hCurKey;
+DWORD dwDisp;
+
+ lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
+ if (lpTxt == NULL)
+ return FALSE;
+
+ RegCreateKeyEx(HKEY_CURRENT_USER,lpszKey,0,NULL,
+ REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hCurKey,&dwDisp);
+
+ for (i=0;i<lpMruMenu->wNbLruMenu;i++)
+ {
+ char szEntry[16];
+ wsprintf(szEntry,"File%lu",(DWORD)i+1);
+ if (!GetMenuItem(lpMruMenu,i,FALSE,lpTxt,lpMruMenu->wMaxSizeLruItem + 10))
+ *lpTxt = '\0';
+ RegSetValueEx(hCurKey,szEntry,0,REG_SZ,(unsigned char*)lpTxt,lstrlen(lpTxt));
+ }
+ RegCloseKey(hCurKey);
+ GlobalFreePtr(lpTxt);
+ return TRUE;
+}
+
+//*************************************************************
+//
+// LoadMruInReg()
+//
+// Purpose:
+// Load MRU from the registry
+//
+// Parameters:
+// LPMRUMENU lpMruMenu - pointer on MRUMENU
+// LPSTR lpszKey - Points to a null-terminated string
+// specifying the name of a key that
+// this function opens or creates.
+//
+// Return: (BOOL)
+// TRUE - Function run successfully
+// FALSE - Function don't run successfully
+//
+//
+// Comments:
+// Win32 function designed for Windows NT and Windows 95
+// See RegOpenKeyEx API for more info on lpszKey
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+BOOL LoadMruInReg(LPMRUMENU lpMruMenu,LPSTR lpszKey)
+{
+LPSTR lpTxt;
+WORD i;
+HKEY hCurKey;
+DWORD dwType;
+ lpTxt = (LPSTR)GlobalAllocPtr(GHND,lpMruMenu->wMaxSizeLruItem + 20);
+ if (lpTxt == NULL)
+ return FALSE;
+
+ RegOpenKeyEx(HKEY_CURRENT_USER,lpszKey,0,KEY_READ,&hCurKey);
+
+
+ for (i=0;i<lpMruMenu->wNbLruMenu;i++)
+ {
+ char szEntry[16];
+ DWORD dwSizeBuf;
+ wsprintf(szEntry,"File%lu",(DWORD)i+1);
+ *lpTxt = '\0';
+ dwSizeBuf = lpMruMenu->wMaxSizeLruItem + 10;
+ RegQueryValueEx(hCurKey,szEntry,NULL,&dwType,(LPBYTE)lpTxt,&dwSizeBuf);
+ *(lpTxt+dwSizeBuf)='\0';
+ if (*lpTxt == '\0')
+ break;
+ SetMenuItem(lpMruMenu,i,lpTxt);
+ }
+ RegCloseKey(hCurKey);
+ GlobalFreePtr(lpTxt);
+ return TRUE;
+}
+
+
+//*************************************************************
+//
+// GetWin32Kind()
+//
+// Purpose:
+// Get the Win32 platform
+//
+// Parameters:
+//
+// Return: (WIN32KIND)
+// WINNT - Run under Windows NT
+// WIN32S - Run under Windows 3.1x + Win32s
+// WIN95ORGREATHER - Run under Windows 95
+//
+//
+// Comments:
+// Win32 function designed for Windows NT and Windows 95
+// See RegOpenKeyEx API for more info on lpszKey
+//
+// History: Date Author Comment
+// 09/24/94 G. Vollant Created
+//
+//*************************************************************
+WIN32KIND GetWin32Kind()
+{
+BOOL IsWin395OrHigher(void);
+
+ WORD wVer;
+
+ if ((GetVersion() & 0x80000000) == 0)
+ return WINNT;
+ wVer = LOWORD(GetVersion());
+ wVer = (((WORD)LOBYTE(wVer)) << 8) | (WORD)HIBYTE(wVer);
+
+ if (wVer >= 0x035F)
+ return WIN95ORGREATHER;
+ else
+ return WIN32S;
+}
+#endif
diff --git a/q3radiant/MRU.H b/q3radiant/MRU.H
new file mode 100755
index 0000000..e508ac7
--- /dev/null
+++ b/q3radiant/MRU.H
@@ -0,0 +1,100 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//*************************************************************
+// File name: mru.h
+//
+// Description:
+//
+// Header for MRU support
+//
+// Development Team:
+//
+// Gilles Vollant (100144.2636@compuserve.com)
+//
+//*************************************************************
+
+#ifndef __MRU_H__
+#define __MRU_H__
+
+#define NBMRUMENUSHOW 6 // Default number of MRU showed in the menu File
+#define NBMRUMENU 9 // Default number of MRU stored
+#define IDMRU 8000 // Default First ID of MRU
+#ifdef OFS_MAXPATHNAME
+#define MAXSIZEMRUITEM OFS_MAXPATHNAME
+#else
+#define MAXSIZEMRUITEM 128 // Default max size of an entry
+#endif
+
+typedef struct
+{
+WORD wNbItemFill;
+WORD wNbLruShow;
+WORD wNbLruMenu;
+WORD wMaxSizeLruItem;
+WORD wIdMru;
+LPSTR lpMRU;
+} MRUMENU;
+
+typedef MRUMENU FAR * LPMRUMENU;
+
+#ifdef __cplusplus
+LPMRUMENU CreateMruMenu (WORD wNbLruShowInit=NBMRUMENUSHOW,
+ WORD wNbLruMenuInit=NBMRUMENU,
+ WORD wMaxSizeLruItemInit=MAXSIZEMRUITEM,
+ WORD wIdMruInit=IDMRU);
+#else
+LPMRUMENU CreateMruMenu (WORD wNbLruShowInit,
+ WORD wNbLruMenuInit,
+ WORD wMaxSizeLruItemInit,
+ WORD wIdMruInit);
+#endif
+
+LPMRUMENU CreateMruMenuDefault();
+void DeleteMruMenu (LPMRUMENU lpMruMenu);
+
+void SetNbLruShow (LPMRUMENU lpMruMenu,WORD wNbLruShowInit);
+BOOL SetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,
+ LPSTR lpItem);
+BOOL GetMenuItem (LPMRUMENU lpMruMenu,WORD wItem,
+ BOOL fIDMBased,LPSTR lpItem,UINT uiSize);
+BOOL DelMenuItem (LPMRUMENU lpMruMenu,WORD wItem,BOOL fIDMBased);
+void AddNewItem (LPMRUMENU lpMruMenu,LPSTR lpItem);
+void PlaceMenuMRUItem(LPMRUMENU lpMruMenu,HMENU hMenu,UINT uiItem);
+
+BOOL SaveMruInIni (LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile);
+BOOL LoadMruInIni (LPMRUMENU lpMruMenu,LPSTR lpszSection,LPSTR lpszFile);
+#ifdef WIN32
+BOOL SaveMruInReg (LPMRUMENU lpMruMenu,LPSTR lpszKey);
+BOOL LoadMruInReg (LPMRUMENU lpMruMenu,LPSTR lpszKey);
+
+typedef enum
+{
+WIN32S,
+WINNT,
+WIN95ORGREATHER
+} WIN32KIND;
+WIN32KIND GetWin32Kind();
+#endif
+
+
+//////////////////////////////////////////////////////////////
+#endif
diff --git a/q3radiant/MainFrm.cpp b/q3radiant/MainFrm.cpp
new file mode 100755
index 0000000..b148f4f
--- /dev/null
+++ b/q3radiant/MainFrm.cpp
@@ -0,0 +1,5224 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// MainFrm.cpp : implementation of the CMainFrame class
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "qe3.h"
+#include "ZWnd.h"
+#include "CamWnd.h"
+#include "TexWnd.h"
+#include "EditWnd.h"
+#include "entityw.h"
+#include "PrefsDlg.h"
+#include "MapInfo.h"
+#include "MainFrm.h"
+#include "RotateDlg.h"
+#include "EntityListDlg.h"
+#include "ScriptDlg.h"
+#include "NewProjDlg.h"
+#include "CommandsDlg.h"
+#include "ScaleDialog.h"
+#include "FindTextureDlg.h"
+#include "SurfaceDlg.h"
+#include "shlobj.h"
+#include "DialogTextures.h"
+#include "PatchDensityDlg.h"
+#include "DialogThick.h"
+#include "PatchDialog.h"
+#include "Undo.h"
+#include "NameDlg.h"
+#include "../libs/pakstuff.h"
+#include "splines/splines.h"
+#include "dlgcamera.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+
+// globals
+CString g_strAppPath; // holds the full path of the executable
+CEdit* g_pEdit = NULL; // used originally to make qe4 work with mfc.. still used
+CMainFrame* g_pParentWnd = NULL; // used to precast to CMainFrame
+CPrefsDlg g_Preferences; // global prefs instance
+CPrefsDlg& g_PrefsDlg = g_Preferences; // reference used throughout
+int g_nUpdateBits = 0; // window update flags
+bool g_bScreenUpdates = true; // whether window painting is active, used in a few places
+ // to disable updates for speed reasons
+ // both of the above should be made members of CMainFrame
+
+//bool g_bSnapToGrid = true; // early use, no longer in use, clamping pref will be used
+CString g_strProject; // holds the active project filename
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame
+
+// command mapping stuff
+//
+// m_strCommand is the command string
+// m_nKey is the windows VK_??? equivelant
+// m_nModifiers are key states as follows
+// bit
+// 0 - shift
+// 1 - alt
+// 2 - control
+// 4 - press only
+//
+#define SPEED_MOVE 32
+#define SPEED_TURN 22.5
+
+
+SCommandInfo g_Commands[] =
+{
+ {"ToggleOutlineDraw", 'J', 0x00, ID_SELECTION_NOOUTLINE},
+ {"CSGMerge", 'U', 0x04, ID_SELECTION_CSGMERGE},
+ {"CSGSubtract", 'U', 0x01, ID_SELECTION_CSGSUBTRACT},
+ {"ViewGroups", 'G', 0x00, ID_VIEW_GROUPS},
+ {"HideSelected", 'H', 0x00, ID_VIEW_HIDESHOW_HIDESELECTED},
+ {"ShowHidden", 'H', 0x01, ID_VIEW_HIDESHOW_SHOWHIDDEN},
+ {"BendMode", 'B', 0x00, ID_PATCH_BEND},
+ {"FitFace", 'B', 0x04, ID_FITFACE},
+ {"FitBrush", 'B', 0x01, ID_FITBRUSH},
+ {"FreezePatchVertices", 'F', 0x00, ID_CURVE_FREEZE},
+ {"UnFreezePatchVertices", 'F', 0x04, ID_CURVE_UNFREEZE},
+ {"UnFreezeAllPatchVertices", 'F', 0x05, ID_CURVE_UNFREEZEALL},
+ {"ViewTextures", 'T', 0, ID_VIEW_TEXTURE},
+ {"ThickenPatch", 'T', 0x04, ID_CURVE_THICKEN},
+ {"MakeOverlayPatch", 'Y', 0, ID_CURVE_OVERLAY_SET},
+ {"ClearPatchOverlays", 'Y', 0x02, ID_CURVE_OVERLAY_CLEAR},
+ {"SurfaceInspector", 'S', 0, ID_TEXTURES_INSPECTOR},
+ {"PatchInspector", 'S', 0x01, ID_PATCH_INSPECTOR},
+ {"ToggleShowPatches", 'P', 0x05, ID_CURVE_CYCLECAP},
+ {"ToggleShowPatches", 'P', 0x04, ID_VIEW_SHOWCURVES},
+ {"RedisperseRows", 'E', 0x04, ID_CURVE_REDISPERSE_ROWS},
+ {"RedisperseCols", 'E', 0x05, ID_CURVE_REDISPERSE_COLS},
+ {"InvertCurveTextureX", 'I', 0x05, ID_CURVE_NEGATIVETEXTUREY},
+ {"InvertCurveTextureY", 'I', 0x01, ID_CURVE_NEGATIVETEXTUREX},
+ {"InvertCurve", 'I', 0x04, ID_CURVE_NEGATIVE},
+ {"IncPatchColumn", VK_ADD, 0x05, ID_CURVE_INSERTCOLUMN},
+ {"IncPatchRow", VK_ADD, 0x04, ID_CURVE_INSERTROW},
+ {"DecPatchColumn", VK_SUBTRACT, 0x05, ID_CURVE_DELETECOLUMN},
+ {"DecPatchRow", VK_SUBTRACT, 0x04, ID_CURVE_DELETEROW},
+ {"Patch TAB", VK_TAB, 0x00, ID_PATCH_TAB},
+ {"Patch TAB", VK_TAB, 0x01, ID_PATCH_TAB},
+ {"SelectNudgeDown", VK_DOWN, 0x02, ID_SELECTION_SELECT_NUDGEDOWN},
+ {"EntityColor",'K', 0, ID_MISC_SELECTENTITYCOLOR},
+ {"CameraForward", VK_UP, 0, ID_CAMERA_FORWARD},
+ {"CameraBack", VK_DOWN, 0, ID_CAMERA_BACK},
+ {"CameraLeft", VK_LEFT, 0, ID_CAMERA_LEFT},
+ {"CameraRight", VK_RIGHT, 0, ID_CAMERA_RIGHT},
+ {"CameraUp", 'D', 0, ID_CAMERA_UP},
+ {"CameraDown", 'C', 0, ID_CAMERA_DOWN},
+ {"CameraAngleUp", 'A', 0, ID_CAMERA_ANGLEUP},
+ {"CameraAngleDown", 'Z', 0, ID_CAMERA_ANGLEDOWN},
+ {"CameraStrafeRight", VK_PERIOD, 0, ID_CAMERA_STRAFERIGHT},
+ {"CameraStrafeLeft", VK_COMMA, 0, ID_CAMERA_STRAFELEFT},
+ {"ToggleGrid", '0', 0, ID_GRID_TOGGLE},
+ {"SetGrid1", '1', 0, ID_GRID_1},
+ {"SetGrid2", '2', 0, ID_GRID_2},
+ {"SetGrid4", '3', 0, ID_GRID_4},
+ {"SetGrid8", '4', 0, ID_GRID_8},
+ {"SetGrid16", '5', 0, ID_GRID_16},
+ {"SetGrid32", '6', 0, ID_GRID_32},
+ {"SetGrid64", '7', 0, ID_GRID_64},
+ {"DragEdges", 'E', 0, ID_SELECTION_DRAGEDGES},
+ {"DragVertices", 'V', 0, ID_SELECTION_DRAGVERTECIES},
+ {"ViewEntityInfo", 'N', 0, ID_VIEW_ENTITY},
+ {"ViewConsole", 'O', 0, ID_VIEW_CONSOLE},
+ {"CloneSelection", VK_SPACE, 0, ID_SELECTION_CLONE},
+ {"DeleteSelection", VK_BACK, 0, ID_SELECTION_DELETE},
+ {"UnSelectSelection", VK_ESCAPE, 0, ID_SELECTION_DESELECT},
+ {"CenterView", VK_END, 0, ID_VIEW_CENTER},
+ {"ZoomOut", VK_INSERT, 0, ID_VIEW_ZOOMOUT},
+ {"ZoomIn", VK_DELETE, 0, ID_VIEW_ZOOMIN},
+ {"UpFloor", VK_PRIOR, 0, ID_VIEW_UPFLOOR},
+ {"DownFloor", VK_NEXT, 0, ID_VIEW_DOWNFLOOR},
+ {"ToggleClipper", 'X', 0, ID_VIEW_CLIPPER},
+ {"ToggleCrosshairs", 'X', 0x01, ID_VIEW_CROSSHAIR},
+ {"TogTexLock", 'T', 0x01, ID_TOGGLE_LOCK},
+ {"TogTexRotLock", 'R', 0x01, ID_TOGGLE_ROTATELOCK},
+ {"ToggleRealtime", 'R', 0x04, ID_VIEW_CAMERAUPDATE},
+ {"RaiseLowerTerrain", 'T', 0x06, ID_TERRAIN_RAISELOWERTERRAIN},
+ {"EntityList", 'L', 0, ID_EDIT_ENTITYINFO},
+ {"Preferences", 'P', 0, ID_PREFS},
+ {"ToggleCamera", 'C', 0x05, ID_TOGGLECAMERA},
+ {"ToggleConsole", 'O', 0, ID_TOGGLECONSOLE},
+ {"ToggleView", 'V', 0x05, ID_TOGGLEVIEW},
+ {"ToggleZ", 'Z', 0x05, ID_TOGGLEZ},
+ {"ConnectSelection", 'K', 0x04, ID_SELECTION_CONNECT},
+ {"Brush3Sided", '3', 0x04, ID_BRUSH_3SIDED},
+ {"Brush4Sided", '4', 0x04, ID_BRUSH_4SIDED},
+ {"Brush5Sided", '5', 0x04, ID_BRUSH_5SIDED},
+ {"Brush6Sided", '6', 0x04, ID_BRUSH_6SIDED},
+ {"Brush7Sided", '7', 0x04, ID_BRUSH_7SIDED},
+ {"Brush8Sided", '8', 0x04, ID_BRUSH_8SIDED},
+ {"Brush9Sided", '9', 0x04, ID_BRUSH_9SIDED},
+ {"ShowDetail", 'D', 0x04, ID_VIEW_SHOWDETAIL},
+ {"MakeDetail", 'M', 0x05, ID_CURVE_MATRIX_TRANSPOSE},
+ {"MakeDetail", 'M', 0x04, ID_SELECTION_MAKE_DETAIL},
+ {"MapInfo", 'M', 0, ID_EDIT_MAPINFO},
+ {"NextLeakSpot", 'K', 0x05, ID_MISC_NEXTLEAKSPOT},
+ {"PrevLeakSpot", 'L', 0x05, ID_MISC_PREVIOUSLEAKSPOT},
+ {"FileOpen", 'O', 0x04, ID_FILE_OPEN},
+ {"FileSave", 'S', 0x04, ID_FILE_SAVE},
+ {"Exit", 'X', 0x04, ID_FILE_EXIT},
+ {"NextView", VK_TAB, 0x04, ID_VIEW_NEXTVIEW},
+ {"ClipSelected", VK_RETURN, 0x00, ID_CLIP_SELECTED},
+ {"SplitSelected", VK_RETURN, 0x01, ID_SPLIT_SELECTED},
+ {"FlipClip", VK_RETURN, 0x04, ID_FLIP_CLIP},
+ {"MouseRotate", 'R', 0x00, ID_SELECT_MOUSEROTATE},
+ {"Copy", 'C', 0x04, ID_EDIT_COPYBRUSH},
+ {"Paste", 'V', 0x04, ID_EDIT_PASTEBRUSH},
+ {"Undo", 'Z', 0x04, ID_EDIT_UNDO},
+ {"Redo", 'Y', 0x04, ID_EDIT_REDO},
+ {"ZZoomOut", VK_INSERT, 0x04, ID_VIEW_ZZOOMOUT},
+ {"ZZoomIn", VK_DELETE, 0x04, ID_VIEW_ZZOOMIN},
+ {"TexDecrement", VK_SUBTRACT, 0x01, ID_SELECTION_TEXTURE_DEC},
+ {"TexIncrement", VK_ADD, 0x01, ID_SELECTION_TEXTURE_INC},
+ {"TextureFit", '5', 0x01, ID_SELECTION_TEXTURE_FIT},
+ {"TexRotateClock", VK_NEXT, 0x01, ID_SELECTION_TEXTURE_ROTATECLOCK},
+ {"TexRotateCounter", VK_PRIOR, 0x01, ID_SELECTION_TEXTURE_ROTATECOUNTER},
+ {"TexScaleUp", VK_UP, 0x04, ID_SELECTION_TEXTURE_SCALEUP},
+ {"TexScaleDown", VK_DOWN, 0x04, ID_SELECTION_TEXTURE_SCALEDOWN},
+ {"TexShiftLeft", VK_LEFT, 0x01, ID_SELECTION_TEXTURE_SHIFTLEFT},
+ {"TexShiftRight", VK_RIGHT, 0x01, ID_SELECTION_TEXTURE_SHIFTRIGHT},
+ {"TexShiftUp", VK_UP, 0x01, ID_SELECTION_TEXTURE_SHIFTUP},
+ {"TexShiftDown", VK_DOWN, 0x01, ID_SELECTION_TEXTURE_SHIFTDOWN},
+ {"GridDown", 219, 0x00, ID_GRID_PREV},
+ {"GridUp", 221, 0x00, ID_GRID_NEXT},
+ {"TexScaleLeft", VK_LEFT, 0x04, ID_SELECTION_TEXTURE_SCALELEFT},
+ {"TexScaleRight", VK_RIGHT, 0x04, ID_SELECTION_TEXTURE_SCALERIGHT},
+ {"CubicClipZoomOut", 219, 0x04, ID_VIEW_CUBEOUT},
+ {"CubicClipZoomIn", 221, 0x04, ID_VIEW_CUBEIN},
+ {"ToggleCubicClip", 220, 0x04, ID_VIEW_CUBICCLIPPING},
+// {"ToggleCubicClip", '\\', 0x04, ID_VIEW_CUBICCLIPPING},
+ {"MoveSelectionDOWN", VK_SUBTRACT, 0x00, ID_SELECTION_MOVEDOWN},
+ {"MoveSelectionUP", VK_ADD, 0x00, ID_SELECTION_MOVEUP},
+ {"DumpSelectedBrush", 'D', 0x01, ID_SELECTION_PRINT},
+ {"ToggleSizePaint", 'Q', 0x08, ID_SELECTION_TOGGLESIZEPAINT},
+ {"SelectNudgeLeft", VK_LEFT, 0x02, ID_SELECTION_SELECT_NUDGELEFT},
+ {"SelectNudgeRight", VK_RIGHT, 0x02, ID_SELECTION_SELECT_NUDGERIGHT},
+ {"SelectNudgeUp", VK_UP, 0x02, ID_SELECTION_SELECT_NUDGEUP},
+ {"CycleCapTexturePatch", 'N', 0x05, ID_CURVE_CYCLECAP},
+ {"NaturalizePatch", 'N', 0x04, ID_PATCH_NATURALIZE},
+ {"SnapPatchToGrid", 'G', 0x04, ID_SELECT_SNAPTOGRID},
+ {"ShowAllTextures", 'A', 0x04, ID_TEXTURES_SHOWALL},
+ {"SelectAllOfType", 'A', 0x01, ID_SELECT_ALL},
+ {"CapCurrentCurve", 'C', 0x01, ID_CURVE_CAP},
+ {"MakeStructural", 'S', 0x05, ID_SELECTION_MAKE_STRUCTURAL}
+ //{"ForceCameraWalk", 'Q', 0x08, ID_CAMERA_ACTIVE}
+};
+
+int g_nCommandCount = sizeof(g_Commands) / sizeof(SCommandInfo);
+
+SKeyInfo g_Keys[] =
+{
+ {"Space", VK_SPACE},
+ {"Backspace", VK_BACK},
+ {"Escape", VK_ESCAPE},
+ {"End", VK_END},
+ {"Insert", VK_INSERT},
+ {"Delete", VK_DELETE},
+ {"PageUp", VK_PRIOR},
+ {"PageDown", VK_NEXT},
+ {"Up", VK_UP},
+ {"Down", VK_DOWN},
+ {"Left", VK_LEFT},
+ {"Right", VK_RIGHT},
+ {"F1", VK_F1},
+ {"F2", VK_F2},
+ {"F3", VK_F3},
+ {"F4", VK_F4},
+ {"F5", VK_F5},
+ {"F6", VK_F6},
+ {"F7", VK_F7},
+ {"F8", VK_F8},
+ {"F9", VK_F9},
+ {"F10", VK_F10},
+ {"F11", VK_F11},
+ {"F12", VK_F12},
+ {"Tab", VK_TAB},
+ {"Return", VK_RETURN},
+ {"Comma", VK_COMMA},
+ {"Period", VK_PERIOD},
+ {"Plus", VK_ADD},
+ {"Multiply", VK_MULTIPLY},
+ {"Subtract", VK_SUBTRACT},
+ {"NumPad0", VK_NUMPAD0},
+ {"NumPad1", VK_NUMPAD1},
+ {"NumPad2", VK_NUMPAD2},
+ {"NumPad3", VK_NUMPAD3},
+ {"NumPad4", VK_NUMPAD4},
+ {"NumPad5", VK_NUMPAD5},
+ {"NumPad6", VK_NUMPAD6},
+ {"NumPad7", VK_NUMPAD7},
+ {"NumPad8", VK_NUMPAD8},
+ {"NumPad9", VK_NUMPAD9},
+ {"[", 219},
+ {"]", 221},
+ {"\\", 220}
+};
+
+int g_nKeyCount = sizeof(g_Keys) / sizeof(SKeyInfo);
+
+const int CMD_TEXTUREWAD_END = CMD_TEXTUREWAD + 127;
+const int CMD_BSPCOMMAND_END = CMD_BSPCOMMAND + 127;
+const int IDMRU_END = IDMRU+9;
+
+const int g_msgBSPDone = RegisterWindowMessage("_BSPDone");
+const int g_msgBSPStatus = RegisterWindowMessage("_BSPStatus");
+
+IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
+
+BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
+ //{{AFX_MSG_MAP(CMainFrame)
+ ON_WM_PARENTNOTIFY()
+ ON_WM_CREATE()
+ ON_WM_TIMER()
+ ON_WM_DESTROY()
+ ON_WM_CLOSE()
+ ON_WM_KEYDOWN()
+ ON_WM_SIZE()
+ ON_COMMAND(ID_VIEW_CAMERATOGGLE, ToggleCamera)
+ ON_COMMAND(ID_FILE_CLOSE, OnFileClose)
+ ON_COMMAND(ID_FILE_EXIT, OnFileExit)
+ ON_COMMAND(ID_FILE_LOADPROJECT, OnFileLoadproject)
+ ON_COMMAND(ID_FILE_NEW, OnFileNew)
+ ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
+ ON_COMMAND(ID_FILE_POINTFILE, OnFilePointfile)
+ ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
+ ON_COMMAND(ID_FILE_PRINT_PREVIEW, OnFilePrintPreview)
+ ON_COMMAND(ID_FILE_SAVE, OnFileSave)
+ ON_COMMAND(ID_FILE_SAVEAS, OnFileSaveas)
+ ON_COMMAND(ID_VIEW_100, OnView100)
+ ON_COMMAND(ID_VIEW_CENTER, OnViewCenter)
+ ON_COMMAND(ID_VIEW_CONSOLE, OnViewConsole)
+ ON_COMMAND(ID_VIEW_DOWNFLOOR, OnViewDownfloor)
+ ON_COMMAND(ID_VIEW_ENTITY, OnViewEntity)
+ ON_COMMAND(ID_VIEW_FRONT, OnViewFront)
+ ON_COMMAND(ID_VIEW_SHOWBLOCKS, OnViewShowblocks)
+ ON_COMMAND(ID_VIEW_SHOWCLIP, OnViewShowclip)
+ ON_COMMAND(ID_VIEW_SHOWCOORDINATES, OnViewShowcoordinates)
+ ON_COMMAND(ID_VIEW_SHOWDETAIL, OnViewShowdetail)
+ ON_COMMAND(ID_VIEW_SHOWENT, OnViewShowent)
+ ON_COMMAND(ID_VIEW_SHOWLIGHTS, OnViewShowlights)
+ ON_COMMAND(ID_VIEW_SHOWNAMES, OnViewShownames)
+ ON_COMMAND(ID_VIEW_SHOWPATH, OnViewShowpath)
+ ON_COMMAND(ID_VIEW_SHOWWATER, OnViewShowwater)
+ ON_COMMAND(ID_VIEW_SHOWWORLD, OnViewShowworld)
+ ON_COMMAND(ID_VIEW_TEXTURE, OnViewTexture)
+ ON_COMMAND(ID_VIEW_UPFLOOR, OnViewUpfloor)
+ ON_COMMAND(ID_VIEW_XY, OnViewXy)
+ ON_COMMAND(ID_VIEW_Z100, OnViewZ100)
+ ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomin)
+ ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomout)
+ ON_COMMAND(ID_VIEW_ZZOOMIN, OnViewZzoomin)
+ ON_COMMAND(ID_VIEW_ZZOOMOUT, OnViewZzoomout)
+ ON_COMMAND(ID_VIEW_SIDE, OnViewSide)
+ ON_COMMAND(ID_TEXTURES_SHOWINUSE, OnTexturesShowinuse)
+ ON_COMMAND(ID_TEXTURES_INSPECTOR, OnTexturesInspector)
+ ON_COMMAND(ID_MISC_BENCHMARK, OnMiscBenchmark)
+ ON_COMMAND(ID_MISC_FINDBRUSH, OnMiscFindbrush)
+ ON_COMMAND(ID_MISC_GAMMA, OnMiscGamma)
+ ON_COMMAND(ID_MISC_NEXTLEAKSPOT, OnMiscNextleakspot)
+ ON_COMMAND(ID_MISC_PREVIOUSLEAKSPOT, OnMiscPreviousleakspot)
+ ON_COMMAND(ID_MISC_PRINTXY, OnMiscPrintxy)
+ ON_COMMAND(ID_MISC_SELECTENTITYCOLOR, OnMiscSelectentitycolor)
+ ON_COMMAND(ID_TEXTUREBK, OnTexturebk)
+ ON_COMMAND(ID_COLORS_MAJOR, OnColorsMajor)
+ ON_COMMAND(ID_COLORS_MINOR, OnColorsMinor)
+ ON_COMMAND(ID_COLORS_XYBK, OnColorsXybk)
+ ON_COMMAND(ID_BRUSH_3SIDED, OnBrush3sided)
+ ON_COMMAND(ID_BRUSH_4SIDED, OnBrush4sided)
+ ON_COMMAND(ID_BRUSH_5SIDED, OnBrush5sided)
+ ON_COMMAND(ID_BRUSH_6SIDED, OnBrush6sided)
+ ON_COMMAND(ID_BRUSH_7SIDED, OnBrush7sided)
+ ON_COMMAND(ID_BRUSH_8SIDED, OnBrush8sided)
+ ON_COMMAND(ID_BRUSH_9SIDED, OnBrush9sided)
+ ON_COMMAND(ID_BRUSH_ARBITRARYSIDED, OnBrushArbitrarysided)
+ ON_COMMAND(ID_BRUSH_FLIPX, OnBrushFlipx)
+ ON_COMMAND(ID_BRUSH_FLIPY, OnBrushFlipy)
+ ON_COMMAND(ID_BRUSH_FLIPZ, OnBrushFlipz)
+ ON_COMMAND(ID_BRUSH_ROTATEX, OnBrushRotatex)
+ ON_COMMAND(ID_BRUSH_ROTATEY, OnBrushRotatey)
+ ON_COMMAND(ID_BRUSH_ROTATEZ, OnBrushRotatez)
+ ON_COMMAND(ID_REGION_OFF, OnRegionOff)
+ ON_COMMAND(ID_REGION_SETBRUSH, OnRegionSetbrush)
+ ON_COMMAND(ID_REGION_SETSELECTION, OnRegionSetselection)
+ ON_COMMAND(ID_REGION_SETTALLBRUSH, OnRegionSettallbrush)
+ ON_COMMAND(ID_REGION_SETXY, OnRegionSetxy)
+ ON_COMMAND(ID_SELECTION_ARBITRARYROTATION, OnSelectionArbitraryrotation)
+ ON_COMMAND(ID_SELECTION_CLONE, OnSelectionClone)
+ ON_COMMAND(ID_SELECTION_CONNECT, OnSelectionConnect)
+ ON_COMMAND(ID_SELECTION_CSGSUBTRACT, OnSelectionCsgsubtract)
+ ON_COMMAND(ID_SELECTION_CSGMERGE, OnSelectionCsgmerge)
+ ON_COMMAND(ID_SELECTION_NOOUTLINE, OnSelectionNoOutline)
+ ON_COMMAND(ID_SELECTION_DELETE, OnSelectionDelete)
+ ON_COMMAND(ID_SELECTION_DESELECT, OnSelectionDeselect)
+ ON_COMMAND(ID_SELECTION_DRAGEDGES, OnSelectionDragedges)
+ ON_COMMAND(ID_SELECTION_DRAGVERTECIES, OnSelectionDragvertecies)
+ ON_COMMAND(ID_SELECTION_MAKE_DETAIL, OnSelectionMakeDetail)
+ ON_COMMAND(ID_SELECTION_MAKE_STRUCTURAL, OnSelectionMakeStructural)
+ ON_COMMAND(ID_SELECTION_MAKEHOLLOW, OnSelectionMakehollow)
+ ON_COMMAND(ID_SELECTION_SELECTCOMPLETETALL, OnSelectionSelectcompletetall)
+ ON_COMMAND(ID_SELECTION_SELECTINSIDE, OnSelectionSelectinside)
+ ON_COMMAND(ID_SELECTION_SELECTPARTIALTALL, OnSelectionSelectpartialtall)
+ ON_COMMAND(ID_SELECTION_SELECTTOUCHING, OnSelectionSelecttouching)
+ ON_COMMAND(ID_SELECTION_UNGROUPENTITY, OnSelectionUngroupentity)
+ ON_COMMAND(ID_TEXTURES_POPUP, OnTexturesPopup)
+ ON_COMMAND(ID_SPLINES_POPUP, OnSplinesPopup)
+ ON_COMMAND(ID_POPUP_SELECTION, OnPopupSelection)
+ ON_COMMAND(ID_VIEW_CHANGE, OnViewChange)
+ ON_COMMAND(ID_VIEW_CAMERAUPDATE, OnViewCameraupdate)
+ ON_COMMAND(ID_TERRAIN_RAISELOWERTERRAIN, OnRaiseLowerTerrain)
+ ON_UPDATE_COMMAND_UI(ID_VIEW_CAMERAUPDATE, OnUpdateViewCameraupdate)
+ ON_WM_SIZING()
+ ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)
+ ON_COMMAND(ID_VIEW_CLIPPER, OnViewClipper)
+ ON_COMMAND(ID_CAMERA_ANGLEDOWN, OnCameraAngledown)
+ ON_COMMAND(ID_CAMERA_ANGLEUP, OnCameraAngleup)
+ ON_COMMAND(ID_CAMERA_BACK, OnCameraBack)
+ ON_COMMAND(ID_CAMERA_DOWN, OnCameraDown)
+ ON_COMMAND(ID_CAMERA_FORWARD, OnCameraForward)
+ ON_COMMAND(ID_CAMERA_LEFT, OnCameraLeft)
+ ON_COMMAND(ID_CAMERA_RIGHT, OnCameraRight)
+ ON_COMMAND(ID_CAMERA_STRAFELEFT, OnCameraStrafeleft)
+ ON_COMMAND(ID_CAMERA_STRAFERIGHT, OnCameraStraferight)
+ ON_COMMAND(ID_CAMERA_UP, OnCameraUp)
+ ON_COMMAND(ID_GRID_TOGGLE, OnGridToggle)
+ ON_COMMAND(ID_PREFS, OnPrefs)
+ ON_COMMAND(ID_TOGGLECAMERA, OnTogglecamera)
+ ON_COMMAND(ID_TOGGLECONSOLE, OnToggleconsole)
+ ON_COMMAND(ID_TOGGLEVIEW, OnToggleview)
+ ON_COMMAND(ID_TOGGLEZ, OnTogglez)
+ ON_COMMAND(ID_TOGGLE_LOCK, OnToggleLock)
+ ON_COMMAND(ID_EDIT_MAPINFO, OnEditMapinfo)
+ ON_COMMAND(ID_EDIT_ENTITYINFO, OnEditEntityinfo)
+ ON_COMMAND(ID_BRUSH_SCRIPTS, OnBrushScripts)
+ ON_COMMAND(ID_VIEW_NEXTVIEW, OnViewNextview)
+ ON_COMMAND(ID_HELP_COMMANDLIST, OnHelpCommandlist)
+ ON_COMMAND(ID_FILE_NEWPROJECT, OnFileNewproject)
+ ON_COMMAND(ID_FLIP_CLIP, OnFlipClip)
+ ON_COMMAND(ID_CLIP_SELECTED, OnClipSelected)
+ ON_COMMAND(ID_SPLIT_SELECTED, OnSplitSelected)
+ ON_COMMAND(ID_TOGGLEVIEW_XZ, OnToggleviewXz)
+ ON_COMMAND(ID_TOGGLEVIEW_YZ, OnToggleviewYz)
+ ON_COMMAND(ID_COLORS_BRUSH, OnColorsBrush)
+ ON_COMMAND(ID_COLORS_CLIPPER, OnColorsClipper)
+ ON_COMMAND(ID_COLORS_GRIDTEXT, OnColorsGridtext)
+ ON_COMMAND(ID_COLORS_SELECTEDBRUSH, OnColorsSelectedbrush)
+ ON_COMMAND(ID_COLORS_GRIDBLOCK, OnColorsGridblock)
+ ON_COMMAND(ID_COLORS_VIEWNAME, OnColorsViewname)
+ ON_COMMAND(ID_COLOR_SETORIGINAL, OnColorSetoriginal)
+ ON_COMMAND(ID_COLOR_SETQER, OnColorSetqer)
+ ON_COMMAND(ID_COLOR_SETBLACK, OnColorSetblack)
+ ON_COMMAND(ID_SNAPTOGRID, OnSnaptogrid)
+ ON_COMMAND(ID_SELECT_SCALE, OnSelectScale)
+ ON_COMMAND(ID_SELECT_MOUSEROTATE, OnSelectMouserotate)
+ ON_COMMAND(ID_EDIT_COPYBRUSH, OnEditCopybrush)
+ ON_COMMAND(ID_EDIT_PASTEBRUSH, OnEditPastebrush)
+ ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
+ ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
+ ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
+ ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
+ ON_COMMAND(ID_SELECTION_INVERT, OnSelectionInvert)
+ ON_COMMAND(ID_SELECTION_TEXTURE_DEC, OnSelectionTextureDec)
+ ON_COMMAND(ID_SELECTION_TEXTURE_FIT, OnSelectionTextureFit)
+ ON_COMMAND(ID_SELECTION_TEXTURE_INC, OnSelectionTextureInc)
+ ON_COMMAND(ID_SELECTION_TEXTURE_ROTATECLOCK, OnSelectionTextureRotateclock)
+ ON_COMMAND(ID_SELECTION_TEXTURE_ROTATECOUNTER, OnSelectionTextureRotatecounter)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SCALEDOWN, OnSelectionTextureScaledown)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SCALEUP, OnSelectionTextureScaleup)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SHIFTDOWN, OnSelectionTextureShiftdown)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SHIFTLEFT, OnSelectionTextureShiftleft)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SHIFTRIGHT, OnSelectionTextureShiftright)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SHIFTUP, OnSelectionTextureShiftup)
+ ON_COMMAND(ID_GRID_NEXT, OnGridNext)
+ ON_COMMAND(ID_GRID_PREV, OnGridPrev)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SCALELEFT, OnSelectionTextureScaleLeft)
+ ON_COMMAND(ID_SELECTION_TEXTURE_SCALERIGHT, OnSelectionTextureScaleRight)
+ ON_COMMAND(ID_TEXTURE_REPLACEALL, OnTextureReplaceall)
+ ON_COMMAND(ID_SCALELOCKX, OnScalelockx)
+ ON_COMMAND(ID_SCALELOCKY, OnScalelocky)
+ ON_COMMAND(ID_SCALELOCKZ, OnScalelockz)
+ ON_COMMAND(ID_SELECT_MOUSESCALE, OnSelectMousescale)
+ ON_COMMAND(ID_VIEW_CUBICCLIPPING, OnViewCubicclipping)
+ ON_COMMAND(ID_FILE_IMPORT, OnFileImport)
+ ON_COMMAND(ID_FILE_PROJECTSETTINGS, OnFileProjectsettings)
+ ON_UPDATE_COMMAND_UI(ID_FILE_IMPORT, OnUpdateFileImport)
+ ON_COMMAND(ID_VIEW_CUBEIN, OnViewCubein)
+ ON_COMMAND(ID_VIEW_CUBEOUT, OnViewCubeout)
+ ON_COMMAND(ID_FILE_SAVEREGION, OnFileSaveregion)
+ ON_UPDATE_COMMAND_UI(ID_FILE_SAVEREGION, OnUpdateFileSaveregion)
+ ON_COMMAND(ID_SELECTION_MOVEDOWN, OnSelectionMovedown)
+ ON_COMMAND(ID_SELECTION_MOVEUP, OnSelectionMoveup)
+ ON_COMMAND(ID_TOOLBAR_MAIN, OnToolbarMain)
+ ON_COMMAND(ID_TOOLBAR_TEXTURE, OnToolbarTexture)
+ ON_COMMAND(ID_SELECTION_PRINT, OnSelectionPrint)
+ ON_COMMAND(ID_SELECTION_TOGGLESIZEPAINT, OnSelectionTogglesizepaint)
+ ON_COMMAND(ID_BRUSH_MAKECONE, OnBrushMakecone)
+ ON_COMMAND(ID_TEXTURES_LOAD, OnTexturesLoad)
+ ON_COMMAND(ID_TOGGLE_ROTATELOCK, OnToggleRotatelock)
+ ON_COMMAND(ID_CURVE_BEVEL, OnCurveBevel)
+ ON_COMMAND(ID_CURVE_CYLINDER, OnCurveCylinder)
+ ON_COMMAND(ID_CURVE_EIGHTHSPHERE, OnCurveEighthsphere)
+ ON_COMMAND(ID_CURVE_ENDCAP, OnCurveEndcap)
+ ON_COMMAND(ID_CURVE_HEMISPHERE, OnCurveHemisphere)
+ ON_COMMAND(ID_CURVE_INVERTCURVE, OnCurveInvertcurve)
+ ON_COMMAND(ID_CURVE_QUARTER, OnCurveQuarter)
+ ON_COMMAND(ID_CURVE_SPHERE, OnCurveSphere)
+ ON_COMMAND(ID_FILE_IMPORTMAP, OnFileImportmap)
+ ON_COMMAND(ID_FILE_EXPORTMAP, OnFileExportmap)
+ ON_COMMAND(ID_EDIT_LOADPREFAB, OnEditLoadprefab)
+ ON_COMMAND(ID_VIEW_SHOWCURVES, OnViewShowcurves)
+ ON_COMMAND(ID_SELECTION_SELECT_NUDGEDOWN, OnSelectionSelectNudgedown)
+ ON_COMMAND(ID_SELECTION_SELECT_NUDGELEFT, OnSelectionSelectNudgeleft)
+ ON_COMMAND(ID_SELECTION_SELECT_NUDGERIGHT, OnSelectionSelectNudgeright)
+ ON_COMMAND(ID_SELECTION_SELECT_NUDGEUP, OnSelectionSelectNudgeup)
+ ON_WM_SYSKEYDOWN()
+ ON_COMMAND(ID_TEXTURES_LOADLIST, OnTexturesLoadlist)
+ ON_COMMAND(ID_DONTSELECTCURVE, OnDontselectcurve)
+ ON_COMMAND(ID_CONVERTCURVES, OnConvertcurves)
+ ON_COMMAND(ID_DYNAMIC_LIGHTING, OnDynamicLighting)
+ ON_COMMAND(ID_CURVE_SIMPLEPATCHMESH, OnCurveSimplepatchmesh)
+ ON_COMMAND(ID_PATCH_SHOWBOUNDINGBOX, OnPatchToggleBox)
+ ON_COMMAND(ID_PATCH_WIREFRAME, OnPatchWireframe)
+ ON_COMMAND(ID_CURVE_PATCHCONE, OnCurvePatchcone)
+ ON_COMMAND(ID_CURVE_PATCHTUBE, OnCurvePatchtube)
+ ON_COMMAND(ID_PATCH_WELD, OnPatchWeld)
+ ON_COMMAND(ID_CURVE_PATCHBEVEL, OnCurvePatchbevel)
+ ON_COMMAND(ID_CURVE_PATCHENDCAP, OnCurvePatchendcap)
+ ON_COMMAND(ID_CURVE_PATCHINVERTEDBEVEL, OnCurvePatchinvertedbevel)
+ ON_COMMAND(ID_CURVE_PATCHINVERTEDENDCAP, OnCurvePatchinvertedendcap)
+ ON_COMMAND(ID_PATCH_DRILLDOWN, OnPatchDrilldown)
+ ON_COMMAND(ID_CURVE_INSERTCOLUMN, OnCurveInsertcolumn)
+ ON_COMMAND(ID_CURVE_INSERTROW, OnCurveInsertrow)
+ ON_COMMAND(ID_CURVE_DELETECOLUMN, OnCurveDeletecolumn)
+ ON_COMMAND(ID_CURVE_DELETEROW, OnCurveDeleterow)
+ ON_COMMAND(ID_CURVE_INSERT_ADDCOLUMN, OnCurveInsertAddcolumn)
+ ON_COMMAND(ID_CURVE_INSERT_ADDROW, OnCurveInsertAddrow)
+ ON_COMMAND(ID_CURVE_INSERT_INSERTCOLUMN, OnCurveInsertInsertcolumn)
+ ON_COMMAND(ID_CURVE_INSERT_INSERTROW, OnCurveInsertInsertrow)
+ ON_COMMAND(ID_CURVE_NEGATIVE, OnCurveNegative)
+ ON_COMMAND(ID_CURVE_NEGATIVETEXTUREX, OnCurveNegativeTextureX)
+ ON_COMMAND(ID_CURVE_NEGATIVETEXTUREY, OnCurveNegativeTextureY)
+ ON_COMMAND(ID_CURVE_DELETE_FIRSTCOLUMN, OnCurveDeleteFirstcolumn)
+ ON_COMMAND(ID_CURVE_DELETE_FIRSTROW, OnCurveDeleteFirstrow)
+ ON_COMMAND(ID_CURVE_DELETE_LASTCOLUMN, OnCurveDeleteLastcolumn)
+ ON_COMMAND(ID_CURVE_DELETE_LASTROW, OnCurveDeleteLastrow)
+ ON_COMMAND(ID_PATCH_BEND, OnPatchBend)
+ ON_COMMAND(ID_PATCH_INSDEL, OnPatchInsdel)
+ ON_COMMAND(ID_PATCH_ENTER, OnPatchEnter)
+ ON_COMMAND(ID_PATCH_TAB, OnPatchTab)
+ ON_COMMAND(ID_CURVE_PATCHDENSETUBE, OnCurvePatchdensetube)
+ ON_COMMAND(ID_CURVE_PATCHVERYDENSETUBE, OnCurvePatchverydensetube)
+ ON_COMMAND(ID_CURVE_CAP, OnCurveCap)
+ ON_COMMAND(ID_CURVE_CAP_INVERTEDBEVEL, OnCurveCapInvertedbevel)
+ ON_COMMAND(ID_CURVE_CAP_INVERTEDENDCAP, OnCurveCapInvertedendcap)
+ ON_COMMAND(ID_CURVE_REDISPERSE_COLS, OnCurveRedisperseCols)
+ ON_COMMAND(ID_CURVE_REDISPERSE_ROWS, OnCurveRedisperseRows)
+ ON_COMMAND(ID_PATCH_NATURALIZE, OnPatchNaturalize)
+ ON_COMMAND(ID_SELECT_SNAPTOGRID, OnSnapToGrid)
+ ON_COMMAND(ID_CURVE_PATCHSQUARE, OnCurvePatchsquare)
+ ON_COMMAND(ID_TERRAIN_CREATETERRAINFROMBRUSH, OnTerrainCreateFromBrush)
+ ON_COMMAND(ID_TEXTURES_TEXTUREWINDOWSCALE_10, OnTexturesTexturewindowscale10)
+ ON_COMMAND(ID_TEXTURES_TEXTUREWINDOWSCALE_100, OnTexturesTexturewindowscale100)
+ ON_COMMAND(ID_TEXTURES_TEXTUREWINDOWSCALE_200, OnTexturesTexturewindowscale200)
+ ON_COMMAND(ID_TEXTURES_TEXTUREWINDOWSCALE_25, OnTexturesTexturewindowscale25)
+ ON_COMMAND(ID_TEXTURES_TEXTUREWINDOWSCALE_50, OnTexturesTexturewindowscale50)
+ ON_COMMAND(ID_TEXTURES_FLUSH, OnTexturesFlush)
+ ON_COMMAND(ID_CURVE_OVERLAY_CLEAR, OnCurveOverlayClear)
+ ON_COMMAND(ID_CURVE_OVERLAY_SET, OnCurveOverlaySet)
+ ON_COMMAND(ID_CURVE_THICKEN, OnCurveThicken)
+ ON_COMMAND(ID_CURVE_CYCLECAP, OnCurveCyclecap)
+ ON_COMMAND(ID_CURVE_MATRIX_TRANSPOSE, OnCurveMatrixTranspose)
+ ON_COMMAND(ID_TEXTURES_RELOADSHADERS, OnTexturesReloadshaders)
+ ON_COMMAND(ID_SHOW_ENTITIES, OnShowEntities)
+ ON_COMMAND(ID_VIEW_ENTITIESAS_BOUNDINGBOX, OnViewEntitiesasBoundingbox)
+ ON_COMMAND(ID_VIEW_ENTITIESAS_SELECTEDSKINNED, OnViewEntitiesasSelectedskinned)
+ ON_COMMAND(ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME, OnViewEntitiesasSelectedwireframe)
+ ON_COMMAND(ID_VIEW_ENTITIESAS_SKINNED, OnViewEntitiesasSkinned)
+ ON_COMMAND(ID_VIEW_ENTITIESAS_SKINNEDANDBOXED, OnViewEntitiesasSkinnedandboxed)
+ ON_COMMAND(ID_VIEW_ENTITIESAS_WIREFRAME, OnViewEntitiesasWireframe)
+ ON_COMMAND(ID_PLUGINS_REFRESH, OnPluginsRefresh)
+ ON_COMMAND(ID_VIEW_SHOWHINT, OnViewShowhint)
+ ON_UPDATE_COMMAND_UI(ID_TEXTURES_SHOWINUSE, OnUpdateTexturesShowinuse)
+ ON_COMMAND(ID_TEXTURES_SHOWALL, OnTexturesShowall)
+ ON_COMMAND(ID_PATCH_INSPECTOR, OnPatchInspector)
+ ON_COMMAND(ID_VIEW_OPENGLLIGHTING, OnViewOpengllighting)
+ ON_COMMAND(ID_SELECT_ALL, OnSelectAll)
+ ON_COMMAND(ID_VIEW_SHOWCAULK, OnViewShowcaulk)
+ ON_COMMAND(ID_CURVE_FREEZE, OnCurveFreeze)
+ ON_COMMAND(ID_CURVE_UNFREEZE, OnCurveUnFreeze)
+ ON_COMMAND(ID_CURVE_UNFREEZEALL, OnCurveUnFreezeAll)
+ ON_COMMAND(ID_SELECT_RESELECT, OnSelectReselect)
+ ON_COMMAND(ID_VIEW_SHOWANGLES, OnViewShowangles)
+ ON_COMMAND(ID_EDIT_SAVEPREFAB, OnEditSaveprefab)
+ ON_COMMAND(ID_CURVE_MOREENDCAPSBEVELS_SQUAREBEVEL, OnCurveMoreendcapsbevelsSquarebevel)
+ ON_COMMAND(ID_CURVE_MOREENDCAPSBEVELS_SQUAREENDCAP, OnCurveMoreendcapsbevelsSquareendcap)
+ ON_COMMAND(ID_BRUSH_PRIMITIVES_SPHERE, OnBrushPrimitivesSphere)
+ ON_COMMAND(ID_VIEW_CROSSHAIR, OnViewCrosshair)
+ ON_COMMAND(ID_VIEW_HIDESHOW_HIDESELECTED, OnViewHideshowHideselected)
+ ON_COMMAND(ID_VIEW_HIDESHOW_SHOWHIDDEN, OnViewHideshowShowhidden)
+ ON_COMMAND(ID_TEXTURES_SHADERS_SHOW, OnTexturesShadersShow)
+ ON_COMMAND(ID_TEXTURES_FLUSH_UNUSED, OnTexturesFlushUnused)
+ ON_COMMAND(ID_VIEW_GROUPS, OnViewGroups)
+ ON_COMMAND(ID_DROP_GROUP_ADDTO_WORLD, OnDropGroupAddtoWorld)
+ ON_COMMAND(ID_DROP_GROUP_NAME, OnDropGroupName)
+ ON_COMMAND(ID_DROP_GROUP_NEWGROUP, OnDropGroupNewgroup)
+ ON_COMMAND(ID_DROP_GROUP_REMOVE, OnDropGroupRemove)
+ ON_COMMAND(ID_SPLINES_MODE, OnSplinesMode)
+ ON_COMMAND(ID_SPLINES_LOAD, OnSplinesLoad)
+ ON_COMMAND(ID_SPLINES_SAVE, OnSplinesSave)
+ ON_COMMAND(ID_SPLINES_EDIT, OnSplinesEdit)
+ ON_COMMAND(ID_SPLINE_TEST, OnSplineTest)
+ ON_COMMAND(ID_POPUP_NEWCAMERA_INTERPOLATED, OnPopupNewcameraInterpolated)
+ ON_COMMAND(ID_POPUP_NEWCAMERA_SPLINE, OnPopupNewcameraSpline)
+ ON_COMMAND(ID_POPUP_NEWCAMERA_FIXED, OnPopupNewcameraFixed)
+ //}}AFX_MSG_MAP
+ ON_COMMAND_RANGE(CMD_TEXTUREWAD, CMD_TEXTUREWAD_END, OnTextureWad)
+ ON_COMMAND_RANGE(CMD_BSPCOMMAND, CMD_BSPCOMMAND_END, OnBspCommand)
+ ON_COMMAND_RANGE(IDMRU, IDMRU_END, OnMru)
+ ON_COMMAND_RANGE(ID_VIEW_NEAREST, ID_TEXTURES_FLATSHADE, OnViewNearest)
+ ON_COMMAND_RANGE(ID_GRID_1, ID_GRID_64, OnGrid1)
+ ON_COMMAND_RANGE(ID_PLUGIN_START, ID_PLUGIN_END, OnPlugIn)
+ ON_REGISTERED_MESSAGE(g_msgBSPDone, OnBSPDone)
+ ON_REGISTERED_MESSAGE(g_msgBSPStatus, OnBSPStatus)
+ ON_MESSAGE(WM_DISPLAYCHANGE, OnDisplayChange)
+
+END_MESSAGE_MAP()
+
+static UINT indicators[] =
+{
+ ID_SEPARATOR, // status line indicator
+ ID_SEPARATOR, // status line indicator
+ ID_SEPARATOR, // status line indicator
+ ID_SEPARATOR, // status line indicator
+ ID_SEPARATOR, // status line indicator
+ ID_SEPARATOR, // status line indicator
+};
+
+LRESULT CMainFrame::OnDisplayChange(UINT wParam, long lParam)
+{
+ int n = wParam;
+ return 0;
+}
+
+
+LRESULT CMainFrame::OnBSPStatus(UINT wParam, long lParam)
+{
+ return 0;
+}
+
+LRESULT CMainFrame::OnBSPDone(UINT wParam, long lParam)
+{
+ DLLBuildDone();
+ return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame construction/destruction
+
+CMainFrame::CMainFrame()
+{
+ m_bDoLoop = false;
+ m_bSplittersOK = false;
+ g_pParentWnd = this;
+ m_pXYWnd = NULL;
+ m_pCamWnd = NULL;
+ m_pTexWnd = NULL;
+ m_pZWnd = NULL;
+ m_pEditWnd = NULL;
+ m_pYZWnd = NULL;
+ m_pXZWnd = NULL;
+ m_pActiveXY = NULL;
+ m_bCamPreview = true;
+}
+
+CMainFrame::~CMainFrame()
+{
+}
+
+void HandlePopup(CWnd* pWindow, unsigned int uId)
+{
+ // Get the current position of the mouse
+ CPoint ptMouse;
+ GetCursorPos(&ptMouse);
+
+ // Load up a menu that has the options we are looking for in it
+ CMenu mnuPopup;
+ VERIFY(mnuPopup.LoadMenu(uId));
+ mnuPopup.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
+ TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y,pWindow);
+ mnuPopup.DestroyMenu();
+
+ // Set focus back to window
+ pWindow->SetFocus();
+}
+
+
+void CMainFrame::OnParentNotify(UINT message, LPARAM lParam)
+{
+}
+
+void CMainFrame::SetButtonMenuStates()
+{
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ {
+ // by default all of these are checked because that's how they're defined in the menu editor
+ if ( !g_qeglobals.d_savedinfo.show_names )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED);
+ if ( !g_qeglobals.d_savedinfo.show_coordinates )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED );
+
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT )
+ pMenu->CheckMenuItem(ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ANGLES )
+ pMenu->CheckMenuItem(ID_VIEW_SHOWANGLES, MF_BYCOMMAND | MF_UNCHECKED );
+
+
+ pMenu->CheckMenuItem(ID_TOGGLE_LOCK, MF_BYCOMMAND | (g_PrefsDlg.m_bTextureLock) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_TOGGLE_ROTATELOCK, MF_BYCOMMAND | (g_PrefsDlg.m_bRotateLock) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_VIEW_CUBICCLIPPING, MF_BYCOMMAND | (g_PrefsDlg.m_bCubicClipping) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem (ID_VIEW_OPENGLLIGHTING, MF_BYCOMMAND | (g_PrefsDlg.m_bGLLighting) ? MF_CHECKED : MF_UNCHECKED );
+ pMenu->CheckMenuItem (ID_SNAPTOGRID, MF_BYCOMMAND | (!g_PrefsDlg.m_bNoClamp) ? MF_CHECKED : MF_UNCHECKED );
+ if (m_wndToolBar.GetSafeHwnd())
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_VIEW_CUBICCLIPPING, (g_PrefsDlg.m_bCubicClipping) ? TRUE : FALSE);
+
+ int n = g_PrefsDlg.m_nTextureScale;
+ int id;
+ switch (n)
+ {
+ case 10 : id = ID_TEXTURES_TEXTUREWINDOWSCALE_10; break;
+ case 25 : id = ID_TEXTURES_TEXTUREWINDOWSCALE_25; break;
+ case 50 : id = ID_TEXTURES_TEXTUREWINDOWSCALE_50; break;
+ case 200 : id = ID_TEXTURES_TEXTUREWINDOWSCALE_200; break;
+ default : id = ID_TEXTURES_TEXTUREWINDOWSCALE_100; break;
+ }
+ CheckTextureScale(id);
+
+
+ }
+ if (g_qeglobals.d_project_entity)
+ {
+ FillTextureMenu(); // redundant but i'll clean it up later.. yeah right..
+ FillBSPMenu();
+ LoadMruInReg(g_qeglobals.d_lpMruMenu,"Software\\id\\QuakeEd4\\MRU");
+ PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,::GetSubMenu(::GetMenu(GetSafeHwnd()),0), ID_FILE_EXIT);
+ }
+}
+
+void CMainFrame::ShowMenuItemKeyBindings(CMenu *pMenu)
+{
+ int i, j;
+ char key[1024], *ptr;
+ MENUITEMINFO MenuItemInfo;
+
+ //return;
+ for (i = 0; i < g_nCommandCount; i++)
+ {
+ memset(&MenuItemInfo, 0, sizeof(MENUITEMINFO));
+ MenuItemInfo.cbSize = sizeof(MENUITEMINFO);
+ MenuItemInfo.fMask = MIIM_TYPE;
+ MenuItemInfo.dwTypeData = key;
+ MenuItemInfo.cch = sizeof(key);
+ if (!pMenu->GetMenuItemInfo(g_Commands[i].m_nCommand, &MenuItemInfo))
+ continue;
+ if (MenuItemInfo.fType != MFT_STRING)
+ continue;
+ ptr = strchr(key, '\t');
+ if (ptr) *ptr = '\0';
+ strcat(key, "\t");
+ if (g_Commands[i].m_nModifiers) // are there modifiers present?
+ {
+ if (g_Commands[i].m_nModifiers & RAD_SHIFT)
+ strcat(key, "Shift-");
+ if (g_Commands[i].m_nModifiers & RAD_ALT)
+ strcat(key, "Alt-");
+ if (g_Commands[i].m_nModifiers & RAD_CONTROL)
+ strcat(key, "Ctrl-");
+ }
+ for (j = 0; j < g_nKeyCount; j++)
+ {
+ if (g_Commands[i].m_nKey == g_Keys[j].m_nVKKey)
+ {
+ strcat(key, g_Keys[j].m_strName);
+ break;
+ }
+ }
+ if (j >= g_nKeyCount)
+ {
+ sprintf(&key[strlen(key)], "%c", g_Commands[i].m_nKey);
+ }
+ memset(&MenuItemInfo, 0, sizeof(MENUITEMINFO));
+ MenuItemInfo.cbSize = sizeof(MENUITEMINFO);
+ MenuItemInfo.fMask = MIIM_TYPE;
+ MenuItemInfo.fType = MFT_STRING;
+ MenuItemInfo.dwTypeData = key;
+ MenuItemInfo.cch = strlen(key);
+ SetMenuItemInfo(pMenu->m_hMenu, g_Commands[i].m_nCommand, FALSE, &MenuItemInfo);
+ }
+}
+
+int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+
+ //Init3Dfx();
+
+ char* pBuffer = g_strAppPath.GetBufferSetLength(_MAX_PATH + 1);
+ int nResult = ::GetModuleFileName(NULL, pBuffer, _MAX_PATH);
+ ASSERT(nResult != 0);
+ pBuffer[g_strAppPath.ReverseFind('\\') + 1] = '\0';
+ g_strAppPath.ReleaseBuffer();
+
+ InitCommonControls ();
+ g_qeglobals.d_hInstance = AfxGetInstanceHandle();
+ MFCCreate(AfxGetInstanceHandle());
+
+ //g_PrefsDlg.LoadPrefs();
+
+ if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ UINT nStyle;
+ UINT nID = (g_PrefsDlg.m_bWideToolbar) ? IDR_TOOLBAR_ADVANCED : IDR_TOOLBAR1;
+
+ if (!m_wndToolBar.Create(this) ||
+ !m_wndToolBar.LoadToolBar(nID))
+ {
+ TRACE0("Failed to create toolbar\n");
+ return -1; // fail to create
+ }
+
+ if (!m_wndStatusBar.Create(this) ||
+ !m_wndStatusBar.SetIndicators(indicators,
+ sizeof(indicators)/sizeof(UINT)))
+ {
+ TRACE0("Failed to create status bar\n");
+ return -1; // fail to create
+ }
+
+#if 0
+ if (!m_wndScaleBar.Create(this) ||
+ !m_wndScaleBar.LoadToolBar(IDR_TOOLBAR_SCALELOCK))
+ {
+ TRACE0("Failed to create scaling toolbar\n");
+ return -1; // fail to create
+ }
+#endif
+
+ // TODO: Remove this if you don't want tool tips or a resizeable toolbar
+ m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
+ CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+
+ // TODO: Delete these three lines if you don't want the toolbar to
+ // be dockable
+ m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
+ EnableDocking(CBRS_ALIGN_ANY);
+ DockControlBar(&m_wndToolBar);
+
+ //m_wndScaleBar.SetBarStyle(m_wndScaleBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+ //m_wndScaleBar.EnableDocking(CBRS_ALIGN_ANY);
+ //m_wndScaleBar.ShowWindow(SW_HIDE);
+
+ int nImage;
+ int nIndex = m_wndToolBar.CommandToIndex(ID_VIEW_CAMERATOGGLE);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(nID);
+ }
+ m_bCamPreview = true;
+
+ nIndex = m_wndToolBar.CommandToIndex(ID_VIEW_CUBICCLIPPING);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_VIEW_ENTITY);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_VIEW_CLIPPER);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_SELECT_MOUSEROTATE);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+
+ nIndex = m_wndToolBar.CommandToIndex(ID_SELECT_MOUSESCALE);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+
+ nIndex = m_wndToolBar.CommandToIndex(ID_SCALELOCKX);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKX, FALSE);
+ }
+
+ nIndex = m_wndToolBar.CommandToIndex(ID_SCALELOCKY);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKY, FALSE);
+ }
+
+ nIndex = m_wndToolBar.CommandToIndex(ID_SCALELOCKZ);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKZ, FALSE);
+ }
+
+#ifdef QUAKE3
+ nIndex = m_wndToolBar.CommandToIndex(ID_DONTSELECTCURVE);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_PATCH_SHOWBOUNDINGBOX);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_SHOWBOUNDINGBOX, TRUE);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_PATCH_WELD);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_WELD, TRUE);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_PATCH_DRILLDOWN);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_DRILLDOWN, TRUE);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_PATCH_BEND);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+ nIndex = m_wndToolBar.CommandToIndex(ID_PATCH_INSDEL);
+ if (nIndex >= 0)
+ {
+ m_wndToolBar.GetButtonInfo(nIndex, nID, nStyle, nImage);
+ m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_CHECKBOX, nImage);
+ }
+#else
+ m_wndToolBar.GetToolBarCtrl().HideButton(ID_DONTSELECTCURVE);
+ m_wndToolBar.GetToolBarCtrl().HideButton(ID_PATCH_SHOWBOUNDINGBOX);
+ m_wndToolBar.GetToolBarCtrl().HideButton(ID_PATCH_WELD);
+ m_wndToolBar.GetToolBarCtrl().HideButton(ID_PATCH_WIREFRAME);
+#endif
+ g_nScaleHow = 0;
+
+
+#ifdef QUAKE3
+ g_pParentWnd->GetMenu()->DestroyMenu();
+ CMenu* pMenu = new CMenu();
+ pMenu->LoadMenu(IDR_MENU_QUAKE3);
+ g_pParentWnd->SetMenu(pMenu);
+#else
+ CMenu* pMenu = GetMenu();
+#endif
+
+ m_wndTextureBar.Create(this, IDD_TEXTUREBAR, CBRS_BOTTOM, 7433);
+ m_wndTextureBar.EnableDocking(CBRS_ALIGN_ANY);
+ DockControlBar(&m_wndTextureBar);
+
+ g_qeglobals.d_lpMruMenu = CreateMruMenuDefault();
+
+ m_bAutoMenuEnable = FALSE;
+
+ LoadCommandMap();
+
+ ShowMenuItemKeyBindings(pMenu);
+
+ CFont* pFont = new CFont();
+ pFont->CreatePointFont(g_PrefsDlg.m_nStatusSize * 10, "Arial");
+ m_wndStatusBar.SetFont(pFont);
+
+ OnPluginsRefresh();
+
+ if (g_PrefsDlg.m_bRunBefore == FALSE)
+ {
+ g_PrefsDlg.m_bRunBefore = TRUE;
+ g_PrefsDlg.SavePrefs();
+/*
+ if (MessageBox("Would you like QERadiant to build and load a default project? If this is the first time you have run QERadiant or you are not familiar with editing QE4 project files directly, this is HIGHLY recommended", "Create a default project?", MB_YESNO) == IDYES)
+ {
+ OnFileNewproject();
+ }
+*/
+ }
+ else
+ {
+ // hack that keeps SGI OpenGL from crashing on texture load with no map
+#if 0
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ vec3_t vMin, vMax;
+ vMin[0] = vMin[1] = vMin[2] = 0;
+ vMax[0] = vMax[1] = vMax[2] = 8;
+ brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
+ Entity_LinkBrush (world_entity, pBrush);
+ Brush_Build(pBrush);
+ Brush_AddToList (pBrush, &active_brushes);
+ Select_Brush(pBrush);
+ Sys_UpdateWindows(W_ALL);
+ PostMessage(WM_COMMAND, ID_SELECTION_DELETE, 0);
+ }
+#endif
+ // load plugins before the first Map_LoadFile
+ // required for model plugins
+ if (g_PrefsDlg.m_bLoadLastMap && g_PrefsDlg.m_strLastMap.GetLength() > 0)
+ Map_LoadFile(g_PrefsDlg.m_strLastMap.GetBuffer(0));
+ }
+
+ SetGridStatus();
+ SetTexValStatus();
+ SetButtonMenuStates();
+ LoadBarState("RadiantToolBars2");
+ if (!g_PrefsDlg.m_bTextureBar)
+ ShowControlBar(&m_wndTextureBar, FALSE, TRUE);
+ else
+ ShowControlBar(&m_wndTextureBar, TRUE, TRUE);
+
+ ShowControlBar(&m_wndToolBar, (m_wndToolBar.GetStyle() & WS_VISIBLE), TRUE);
+
+ SetActiveXY(m_pXYWnd);
+ m_pXYWnd->SetFocus();
+
+ PostMessage(WM_KEYDOWN, 'O', NULL);
+
+ return 0;
+}
+
+void CMainFrame::LoadCommandMap()
+{
+ CString strINI;
+ char* pBuff = new char[1024];
+ if (g_PrefsDlg.m_strUserPath.GetLength() > 0)
+ strINI = g_PrefsDlg.m_strUserPath;
+ else
+ {
+ strINI = g_strAppPath;
+ strINI += "\\radiant.ini";
+ }
+
+ for (int i = 0; i < g_nCommandCount; i++)
+ {
+ int nLen = GetPrivateProfileString("Commands", g_Commands[i].m_strCommand, "", pBuff, 1024, strINI);
+ if (nLen > 0)
+ {
+ CString strBuff = pBuff;
+ strBuff.TrimLeft();
+ strBuff.TrimRight();
+ int nSpecial = strBuff.Find("+alt");
+ g_Commands[i].m_nModifiers = 0;
+ if (nSpecial >= 0)
+ {
+ g_Commands[i].m_nModifiers |= RAD_ALT;
+ FindReplace(strBuff, "+alt", "");
+ }
+ nSpecial = strBuff.Find("+ctrl");
+ if (nSpecial >= 0)
+ {
+ g_Commands[i].m_nModifiers |= RAD_CONTROL;
+ FindReplace(strBuff, "+ctrl", "");
+ }
+ nSpecial = strBuff.Find("+shift");
+ if (nSpecial >= 0)
+ {
+ g_Commands[i].m_nModifiers |= RAD_SHIFT;
+ FindReplace(strBuff, "+shift", "");
+ }
+ strBuff.TrimLeft();
+ strBuff.TrimRight();
+ strBuff.MakeUpper();
+ if (nLen == 1) // most often case.. deal with first
+ {
+ g_Commands[i].m_nKey = __toascii(strBuff.GetAt(0));
+ }
+ else // special key
+ {
+ for (int j = 0; j < g_nKeyCount; j++)
+ {
+ if (strBuff.CompareNoCase(g_Keys[j].m_strName) == 0)
+ {
+ g_Commands[i].m_nKey = g_Keys[j].m_nVKKey;
+ break;
+ }
+ }
+ }
+ }
+ }
+ delete []pBuff;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+ // TODO: Modify the Window class or styles here by modifying
+ // the CREATESTRUCT cs
+ return CFrameWnd::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame diagnostics
+
+#ifdef _DEBUG
+void CMainFrame::AssertValid() const
+{
+ CFrameWnd::AssertValid();
+}
+
+void CMainFrame::Dump(CDumpContext& dc) const
+{
+ CFrameWnd::Dump(dc);
+}
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CMainFrame message handlers
+void CMainFrame::CreateQEChildren()
+{
+ // the project file can be specified on the command line,
+ // or implicitly found in the scripts directory
+ bool bProjectLoaded = false;
+ if (AfxGetApp()->m_lpCmdLine && strlen(AfxGetApp()->m_lpCmdLine))
+ {
+ ParseCommandLine (AfxGetApp()->m_lpCmdLine);
+ bProjectLoaded = QE_LoadProject(argv[1]);
+ }
+ else
+ {
+ if (g_PrefsDlg.m_bLoadLast && g_PrefsDlg.m_strLastProject.GetLength() > 0)
+ {
+ bProjectLoaded = QE_LoadProject(g_PrefsDlg.m_strLastProject.GetBuffer(0));
+ }
+ if (!bProjectLoaded)
+ {
+ CString str = g_strAppPath;
+ AddSlash(str);
+ str += "../baseq3/scripts/quake.qe4";
+ char cWork[1024];
+ char *pFile = NULL;
+ GetFullPathName(str, 1024, cWork, &pFile);
+ bProjectLoaded = QE_LoadProject(cWork);
+ }
+ if (!bProjectLoaded)
+ {
+ bProjectLoaded = QE_LoadProject("scripts/quake.qe4");
+ }
+ }
+
+ if (!bProjectLoaded)
+ {
+#if 0
+ // let's try the default project directory..
+ char* pBuff = new char[1024];
+ ::GetCurrentDirectory(1024, pBuff);
+ CString strDefProj = g_strAppPath;
+ AddSlash(strDefProj);
+ strDefProj += "defproj";
+ if (::SetCurrentDirectory(strDefProj))
+ {
+ bProjectLoaded = QE_LoadProject("scripts/quake.qe4");
+ if (bProjectLoaded)
+ {
+ // setup auto load stuff for the default map
+ g_PrefsDlg.m_bLoadLast = TRUE;
+ AddSlash(strDefProj);
+ strDefProj += "maps\\defproj.map";
+ g_PrefsDlg.m_strLastMap = strDefProj;
+ g_PrefsDlg.SavePrefs();
+ }
+ }
+ else
+ {
+ ::SetCurrentDirectory(pBuff);
+ }
+ delete []pBuff;
+#endif
+
+ if (!bProjectLoaded)
+ {
+ Sys_Printf ("Using default.qe4. You may experience problems. See the readme.txt\n");
+ CString strProj = g_strAppPath;
+ strProj += "\\default.qe4";
+ bProjectLoaded = QE_LoadProject(strProj.GetBuffer(0));
+
+ if (!bProjectLoaded)
+ {
+ CFileDialog dlgFile(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Q3Radiant Project files (*.qe4, *.prj)|*.qe4|*.prj||", this);
+ if (dlgFile.DoModal() == IDOK)
+ bProjectLoaded = QE_LoadProject(dlgFile.GetPathName().GetBuffer(0));
+ }
+ }
+ }
+
+ if (!bProjectLoaded)
+ Error("Unable to load project file. It was unavailable in the scripts path and the default could not be found");
+
+
+ if (g_PrefsDlg.m_bPAK == TRUE)
+ {
+ // FIXME: pay attention to Q3 pref
+ //InitPakFile(ValueForKey(g_qeglobals.d_project_entity, "basepath"), g_PrefsDlg.m_strPAKFile);
+ InitPakFile(ValueForKey(g_qeglobals.d_project_entity, "basepath"), NULL);
+ }
+
+ QE_Init ();
+
+ Sys_Printf ("Entering message loop\n");
+
+ m_bDoLoop = true;
+ SetTimer(QE_TIMER0, 1000, NULL);
+
+}
+
+BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+ return CFrameWnd::OnCommand(wParam, lParam);
+}
+
+LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ RoutineProcessing();
+ return CFrameWnd::DefWindowProc(message, wParam, lParam);
+}
+
+
+void CMainFrame::RoutineProcessing()
+{
+ if (m_bDoLoop)
+ {
+ double time = 0.0;
+ double oldtime = 0.0;
+ double delta= 0.0;
+
+ CheckBspProcess ();
+ time = Sys_DoubleTime ();
+ delta = time - oldtime;
+ oldtime = time;
+ if (delta > 0.2)
+ delta = 0.2;
+
+ // run time dependant behavior
+ if (m_pCamWnd)
+ m_pCamWnd->Cam_MouseControl(delta);
+
+ if (g_PrefsDlg.m_bQE4Painting && g_nUpdateBits)
+ {
+ int nBits = g_nUpdateBits; // this is done to keep this routine from being
+ g_nUpdateBits = 0; // re-entered due to the paint process.. only
+ UpdateWindows(nBits); // happens in rare cases but causes a stack overflow
+ }
+
+ }
+}
+
+LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
+{
+ return CFrameWnd::WindowProc(message, wParam, lParam);
+}
+
+bool MouseDown()
+{
+ if (::GetAsyncKeyState(VK_LBUTTON))
+ return true;
+ if (::GetAsyncKeyState(VK_RBUTTON))
+ return true;
+ if (::GetAsyncKeyState(VK_MBUTTON))
+ return true;
+ return false;
+}
+
+
+void CMainFrame::OnTimer(UINT nIDEvent)
+{
+ if (!MouseDown())
+ {
+ QE_CountBrushesAndUpdateStatusBar();
+ QE_CheckAutoSave();
+ }
+}
+struct SplitInfo
+{
+ int m_nMin;
+ int m_nCur;
+};
+
+bool LoadWindowPlacement(HWND hwnd, const char* pName)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(WINDOWPLACEMENT);
+ LONG lSize = sizeof(wp);
+ if (LoadRegistryInfo(pName, &wp, &lSize))
+ {
+ ::SetWindowPlacement(hwnd, &wp);
+ return true;
+ }
+ return false;
+}
+
+void SaveWindowPlacement(HWND hwnd, const char* pName)
+{
+ WINDOWPLACEMENT wp;
+ wp.length = sizeof(WINDOWPLACEMENT);
+ if (::GetWindowPlacement(hwnd, &wp))
+ {
+ SaveRegistryInfo(pName, &wp, sizeof(wp));
+ }
+}
+
+
+void CMainFrame::OnDestroy()
+{
+ KillTimer(QE_TIMER0);
+
+ SaveBarState("RadiantToolBars2");
+
+ // FIXME
+ // original mru stuff needs replaced with mfc stuff
+ SaveMruInReg(g_qeglobals.d_lpMruMenu,"Software\\id\\QuakeEd4\\MRU");
+
+ DeleteMruMenu(g_qeglobals.d_lpMruMenu);
+
+ SaveWindowPlacement(GetSafeHwnd(), "Radiant::MainWindowPlace");
+ //SaveWindowState(GetSafeHwnd(), "Radiant::MainWindow");
+ //if (m_nCurrentStyle == QR_QE4)
+ //SaveWindowPlacement(g_qeglobals.d_hwndEntity, "EntityWindowPlace");
+
+ if (m_nCurrentStyle == 0 || m_nCurrentStyle == 3)
+ {
+ SaveWindowState(m_wndSplit.GetSafeHwnd(), "Radiant::Split");
+ SaveWindowState(m_wndSplit2.GetSafeHwnd(), "Radiant::Split2");
+ SaveWindowState(m_wndSplit3.GetSafeHwnd(), "Radiant::Split3");
+
+ SplitInfo spinfo;
+ m_wndSplit.GetRowInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split::Row_0", &spinfo, sizeof(spinfo));
+ m_wndSplit.GetRowInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split::Row_1", &spinfo, sizeof(spinfo));
+
+ m_wndSplit2.GetColumnInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split2::Col_0", &spinfo, sizeof(spinfo));
+ m_wndSplit2.GetColumnInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split2::Col_1", &spinfo, sizeof(spinfo));
+ m_wndSplit2.GetColumnInfo(2, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split2::Col_2", &spinfo, sizeof(spinfo));
+
+ m_wndSplit3.GetRowInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split3::Row_0", &spinfo, sizeof(spinfo));
+ m_wndSplit3.GetRowInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ SaveRegistryInfo("Radiant::Split3::Row_1", &spinfo, sizeof(spinfo));
+ }
+ else
+ {
+ SaveWindowPlacement(m_pXYWnd->GetSafeHwnd(), "xywindow");
+ SaveWindowPlacement(m_pXZWnd->GetSafeHwnd(), "xzwindow");
+ SaveWindowPlacement(m_pYZWnd->GetSafeHwnd(), "yzwindow");
+ SaveWindowPlacement(m_pCamWnd->GetSafeHwnd(), "camerawindow");
+ SaveWindowPlacement(m_pZWnd->GetSafeHwnd(), "zwindow");
+ SaveWindowState(m_pTexWnd->GetSafeHwnd(), "texwindow");
+ SaveWindowState(m_pEditWnd->GetSafeHwnd(), "editwindow");
+ }
+
+ if (m_pXYWnd->GetSafeHwnd())
+ m_pXYWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pXYWnd; m_pXYWnd = NULL;
+
+ if (m_pYZWnd->GetSafeHwnd())
+ m_pYZWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pYZWnd; m_pYZWnd = NULL;
+
+ if (m_pXZWnd->GetSafeHwnd())
+ m_pXZWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pXZWnd; m_pXZWnd = NULL;
+
+ if (m_pZWnd->GetSafeHwnd())
+ m_pZWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pZWnd; m_pZWnd = NULL;
+
+ if (m_pTexWnd->GetSafeHwnd())
+ m_pTexWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pTexWnd; m_pTexWnd = NULL;
+
+ if (m_pEditWnd->GetSafeHwnd())
+ m_pEditWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pEditWnd; m_pEditWnd = NULL;
+
+ if (m_pCamWnd->GetSafeHwnd())
+ m_pCamWnd->SendMessage(WM_DESTROY, 0, 0);
+ delete m_pCamWnd;m_pCamWnd = NULL;
+
+ SaveRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, sizeof(g_qeglobals.d_savedinfo));
+
+ if (strcmpi(currentmap, "unnamed.map") != 0)
+ {
+ g_PrefsDlg.m_strLastMap = currentmap;
+ g_PrefsDlg.SavePrefs();
+ }
+ CleanUpEntities();
+
+ while (active_brushes.next != &active_brushes)
+ Brush_Free (active_brushes.next, false);
+ while (selected_brushes.next != &selected_brushes)
+ Brush_Free (selected_brushes.next, false);
+ while (filtered_brushes.next != &filtered_brushes)
+ Brush_Free (filtered_brushes.next, false);
+
+ while (entities.next != &entities)
+ Entity_Free (entities.next);
+
+ epair_t* pEPair = g_qeglobals.d_project_entity->epairs;
+ while (pEPair)
+ {
+ epair_t* pNextEPair = pEPair->next;
+ free (pEPair->key);
+ free (pEPair->value);
+ free (pEPair);
+ pEPair = pNextEPair;
+ }
+
+ entity_t* pEntity = g_qeglobals.d_project_entity->next;
+ while (pEntity != NULL && pEntity != g_qeglobals.d_project_entity)
+ {
+ entity_t* pNextEntity = pEntity->next;
+ Entity_Free(pEntity);
+ pEntity = pNextEntity;
+ }
+
+ Texture_Cleanup();
+
+ if (world_entity)
+ Entity_Free(world_entity);
+
+ if (notexture)
+ {
+ // Timo
+ // Surface properties plugin
+#ifdef _DEBUG
+ if ( !notexture->pData )
+ Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
+#endif
+ if ( notexture->pData )
+ GETPLUGINTEXDEF(notexture)->DecRef();
+
+ free(notexture);
+ }
+
+ //if (current_texture)
+ // free(current_texture);
+ ClosePakFile();
+
+ FreeShaders();
+
+ CFrameWnd::OnDestroy();
+}
+
+void CMainFrame::OnClose()
+{
+ if (ConfirmModified())
+ {
+ CFrameWnd::OnClose();
+ }
+}
+
+void CMainFrame::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ // run through our list to see if we have a handler for nChar
+ //
+ for (int i = 0; i < g_nCommandCount; i++)
+ {
+ if (g_Commands[i].m_nKey == nChar) // find a match?
+ {
+ bool bGo = true;
+ if (g_Commands[i].m_nModifiers & RAD_PRESS)
+ {
+ int nModifiers = g_Commands[i].m_nModifiers & ~RAD_PRESS;
+ if (nModifiers) // are there modifiers present?
+ {
+ if (nModifiers & RAD_ALT)
+ if (!(GetKeyState(VK_MENU) & 0x8000))
+ bGo = false;
+ if (nModifiers & RAD_CONTROL)
+ if (!(GetKeyState(VK_CONTROL) & 0x8000))
+ bGo = false;
+ if (nModifiers & RAD_SHIFT)
+ if (!(GetKeyState(VK_SHIFT) & 0x8000))
+ bGo = false;
+ }
+ else // no modifiers make sure none of those keys are pressed
+ {
+ if (GetKeyState(VK_MENU) & 0x8000)
+ bGo = false;
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ bGo = false;
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ bGo = false;
+ }
+ if (bGo)
+ {
+ SendMessage(WM_COMMAND, g_Commands[i].m_nCommand, 0);
+ break;
+ }
+ }
+ }
+ }
+}
+
+bool CamOK(unsigned int nKey)
+{
+ if (nKey == VK_UP || nKey == VK_LEFT || nKey == VK_RIGHT || nKey == VK_DOWN)
+ {
+ if (::GetAsyncKeyState(nKey))
+ return true;
+ else
+ return false;
+ }
+ return true;
+}
+
+
+void CMainFrame::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ //OnKeyDown(nChar, nRepCnt, nFlags);
+ if (nChar == VK_DOWN)
+ {
+ OnKeyDown(nChar, nRepCnt, nFlags);
+ }
+ CFrameWnd::OnSysKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CMainFrame::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ for (int i = 0; i < g_nCommandCount; i++)
+ {
+ if (g_Commands[i].m_nKey == nChar) // find a match?
+ {
+ // check modifiers
+ unsigned int nState = 0;
+ if (GetKeyState(VK_MENU) & 0x8000)
+ nState |= RAD_ALT;
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ nState |= RAD_CONTROL;
+ if (GetKeyState(VK_SHIFT) & 0x8000)
+ nState |= RAD_SHIFT;
+ if ((g_Commands[i].m_nModifiers & 0x7) == nState)
+ {
+ SendMessage(WM_COMMAND, g_Commands[i].m_nCommand, 0);
+ break;
+ }
+ }
+ }
+ CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
+{
+ g_qeglobals.d_hwndMain = GetSafeHwnd();
+ g_qeglobals.d_hwndStatus = GetMessageBar()->GetSafeHwnd();
+
+/*
+ if (g_PrefsDlg.m_bRunBefore == FALSE)
+ {
+ MessageBox("In the following dialog, please make sure the Quake2 .exe information is correct.\nQERadiant will NOT run correctly without this information");
+ g_PrefsDlg.DoModal();
+ }
+*/
+
+ m_nCurrentStyle = g_PrefsDlg.m_nView;
+
+ CreateEntityWindow(AfxGetInstanceHandle());
+
+ g_pGroupDlg->Create( IDD_DLG_GROUP, this);
+ g_qeglobals.d_hwndGroup = g_pGroupDlg->GetSafeHwnd();
+ ::SetParent(g_qeglobals.d_hwndGroup, g_qeglobals.d_hwndEntity);
+ g_pGroupDlg->ShowWindow(SW_SHOW);
+
+ if (!LoadWindowPlacement(GetSafeHwnd(), "Radiant::MainWindowPlace"))
+ {
+ LoadWindowState(GetSafeHwnd(), "Radiant::MainWindow");
+ }
+
+ //if (m_nCurrentStyle == QR_QE4)
+ // LoadWindowPlacement(g_qeglobals.d_hwndEntity, "EntityWindowPlace");
+
+ CRect rect(5,25, 100, 100);
+ CRect rctParent;
+ GetClientRect(rctParent);
+
+ if (g_PrefsDlg.m_nView == 0 || g_PrefsDlg.m_nView == 3)
+ {
+ m_wndSplit.CreateStatic(this, 2, 1);
+ m_wndSplit2.CreateStatic(&m_wndSplit, 1, 3);
+ m_wndSplit3.CreateStatic(&m_wndSplit2, 2,1);
+
+ m_wndSplit.CreateView(1,0,RUNTIME_CLASS(CEditWnd), CSize(25, 100), pContext);
+ g_pEdit = dynamic_cast<CEdit*>(m_wndSplit.GetPane(1,0));
+ if (g_pEdit)
+ g_qeglobals.d_hwndEdit = g_pEdit->GetSafeHwnd();
+
+ m_wndSplit3.CreateView(0,0,RUNTIME_CLASS(CCamWnd), CSize(25, 100), pContext);
+ m_pCamWnd = dynamic_cast<CCamWnd*>(m_wndSplit3.GetPane(0,0));
+
+ m_wndSplit2.CreateView(0,1,RUNTIME_CLASS(CXYWnd), CSize(25, 100), pContext);
+ m_pXYWnd = dynamic_cast<CXYWnd*>(m_wndSplit2.GetPane(0,1));
+ m_pXYWnd->SetViewType(XY);
+
+ m_pCamWnd->SetXYFriend(m_pXYWnd);
+
+ m_wndSplit2.CreateView(0,2,RUNTIME_CLASS(CZWnd), CSize(25, 100), pContext);
+ m_pZWnd = dynamic_cast<CZWnd*>(m_wndSplit2.GetPane(0,2));
+
+ m_wndSplit3.CreateView(1,0,RUNTIME_CLASS(CTexWnd), CSize(25, 100), pContext);
+ m_pTexWnd = dynamic_cast<CTexWnd*>(m_wndSplit3.GetPane(1,0));
+
+ CreateQEChildren();
+
+ if (g_PrefsDlg.m_nView == 0)
+ {
+ // the following bit switches the left and right views
+ CWnd* pRight = m_wndSplit2.GetPane(0,2);
+ long lRightID = ::GetWindowLong(pRight->GetSafeHwnd(), GWL_ID);
+ long lLeftID = ::GetWindowLong(m_wndSplit3.GetSafeHwnd(), GWL_ID);
+ ::SetWindowLong(pRight->GetSafeHwnd(), GWL_ID, lLeftID);
+ ::SetWindowLong(m_wndSplit3.GetSafeHwnd(), GWL_ID, lRightID);
+ }
+
+ m_wndSplit.SetRowInfo(0, rctParent.Height() * .85, 50);
+ m_wndSplit.SetRowInfo(1, rctParent.Height() * .15, 5);
+
+ float fLeft = (g_PrefsDlg.m_nView == 0) ? .05 : .25;
+ float fRight = (g_PrefsDlg.m_nView == 0) ? .25 : .05;
+ int nMin1 = (g_PrefsDlg.m_nView == 0) ? 10 : 25;
+ int nMin2 = (nMin1 == 10) ? 25 : 10;
+
+ m_wndSplit2.SetColumnInfo(0, rctParent.Width() * fLeft, nMin1);
+ m_wndSplit2.SetColumnInfo(1, rctParent.Width() * .70, 100);
+ m_wndSplit2.SetColumnInfo(2, rctParent.Width() * fRight, nMin2);
+
+ m_wndSplit3.SetRowInfo(1, (rctParent.Height() * .85) * .40, 15);
+ m_wndSplit3.SetRowInfo(0, (rctParent.Height() * .85) * .60, 15);
+
+ LoadWindowState(m_wndSplit.GetSafeHwnd(), "Radiant::Split");
+ LoadWindowState(m_wndSplit2.GetSafeHwnd(), "Radiant::Split2");
+ LoadWindowState(m_wndSplit3.GetSafeHwnd(), "Radiant::Split3");
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+
+ SplitInfo spinfo;
+ long lSize = sizeof(spinfo);
+ if (LoadRegistryInfo("Radiant::Split::Row_0", &spinfo, &lSize))
+ m_wndSplit.SetRowInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ if (LoadRegistryInfo("Radiant::Split::Row_1", &spinfo, &lSize))
+ m_wndSplit.SetRowInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+
+ if (LoadRegistryInfo("Radiant::Split2::Col_0", &spinfo, &lSize))
+ m_wndSplit2.SetColumnInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ if (LoadRegistryInfo("Radiant::Split2::Col_1", &spinfo, &lSize))
+ m_wndSplit2.SetColumnInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ if (LoadRegistryInfo("Radiant::Split2::Col_2", &spinfo, &lSize))
+ m_wndSplit2.SetColumnInfo(2, spinfo.m_nCur, spinfo.m_nMin);
+
+ if (LoadRegistryInfo("Radiant::Split3::Row_0", &spinfo, &lSize))
+ m_wndSplit3.SetRowInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ if (LoadRegistryInfo("Radiant::Split3::Row_1", &spinfo, &lSize))
+ m_wndSplit3.SetRowInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+
+ m_wndSplit.RecalcLayout();
+ m_wndSplit2.RecalcLayout();
+ m_wndSplit3.RecalcLayout();
+ }
+ else if (g_PrefsDlg.m_nView == 1)
+ {
+ m_pCamWnd = new CCamWnd();
+ m_pCamWnd->Create(CAMERA_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1234);
+
+ m_pZWnd = new CZWnd();
+ m_pZWnd->Create(Z_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1238);
+
+ m_pXYWnd = new CXYWnd();
+ m_pXYWnd->Create(XY_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1235);
+ m_pXYWnd->SetViewType(XY);
+
+ m_pXZWnd = new CXYWnd();
+ m_pXZWnd->Create(XY_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1236);
+ m_pXZWnd->SetViewType(XZ);
+
+ m_pYZWnd = new CXYWnd();
+ m_pYZWnd->Create(XY_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1237);
+ m_pYZWnd->SetViewType(YZ);
+
+ m_pCamWnd->SetXYFriend(m_pXYWnd);
+
+ m_pTexWnd = new CTexWnd();
+ m_pTexWnd->Create(TEXTURE_WINDOW_CLASS, "", QE3_SPLITTER_STYLE, rect, this, 1239);
+ ::SetParent(m_pTexWnd->GetSafeHwnd(), g_qeglobals.d_hwndEntity);
+
+ CRect rctWork;
+ // XY and Z windows are 2 pixels off of the height and one down from top so one pixel spacing vertically
+ // Z window takes up 10% of right edge
+ // XY window takes up 60% of middle
+ // TEX and CAM windows take up 30% of left
+#if 0
+ int xTex = 1;
+ int xXY = 1 + xTex + ((float)rctParent.Width()) * .30;
+ int xZ = 1 + xXY + ((float)rctParent.Width()) * .60;
+ int yXY = 1;
+ int yTex = 1 + ((float)rctParent.Height()) * .45;
+ m_pXYWnd->SetWindowPos(NULL, xXY, yXY, ((float)rctParent.Width()) * .60, rctParent.Height() - 2, SWP_SHOWWINDOW);
+ m_pXZWnd->SetWindowPos(NULL, xXY, yXY, ((float)rctParent.Width()) * .60, rctParent.Height() - 2, SWP_SHOWWINDOW);
+ m_pYZWnd->SetWindowPos(NULL, xXY, yXY, ((float)rctParent.Width()) * .60, rctParent.Height() - 2, SWP_SHOWWINDOW);
+ m_pCamWnd->SetWindowPos(NULL, xTex, yXY, ((float)rctParent.Width()) *.30, ((float)rctParent.Height()) * .45, SWP_SHOWWINDOW);
+ m_pTexWnd->SetWindowPos(NULL, xTex, yTex, ((float)rctParent.Width()) *.30, ((float)rctParent.Height()) * .45, SWP_SHOWWINDOW);
+#endif
+
+ LoadWindowPlacement(m_pXYWnd->GetSafeHwnd(), "xywindow");
+ LoadWindowPlacement(m_pXZWnd->GetSafeHwnd(), "xzwindow");
+ LoadWindowPlacement(m_pYZWnd->GetSafeHwnd(), "yzwindow");
+ LoadWindowPlacement(m_pCamWnd->GetSafeHwnd(), "camerawindow");
+ LoadWindowPlacement(m_pZWnd->GetSafeHwnd(), "zwindow");
+
+ if (!g_PrefsDlg.m_bXZVis)
+ m_pXZWnd->ShowWindow(SW_HIDE);
+ if (!g_PrefsDlg.m_bYZVis)
+ m_pYZWnd->ShowWindow(SW_HIDE);
+ if (!g_PrefsDlg.m_bZVis)
+ m_pZWnd->ShowWindow(SW_HIDE);
+
+ CreateQEChildren();
+ }
+ else // 4 way
+ {
+ m_wndSplit.CreateStatic(this, 2, 2);
+
+ m_wndSplit.CreateView(0,0,RUNTIME_CLASS(CCamWnd), CSize(25, 100), pContext);
+ m_pCamWnd = dynamic_cast<CCamWnd*>(m_wndSplit.GetPane(0,0));
+
+ m_wndSplit.CreateView(0,1,RUNTIME_CLASS(CXYWnd), CSize(25, 100), pContext);
+ m_pXYWnd = dynamic_cast<CXYWnd*>(m_wndSplit.GetPane(0,1));
+ m_pXYWnd->SetViewType(XY);
+
+ m_wndSplit.CreateView(1,0,RUNTIME_CLASS(CXYWnd), CSize(25, 100), pContext);
+ m_pYZWnd = dynamic_cast<CXYWnd*>(m_wndSplit.GetPane(1,0));
+ m_pYZWnd->SetViewType(YZ);
+
+ m_wndSplit.CreateView(1,1,RUNTIME_CLASS(CXYWnd), CSize(25, 100), pContext);
+ m_pXZWnd = dynamic_cast<CXYWnd*>(m_wndSplit.GetPane(1,1));
+ m_pXZWnd->SetViewType(XZ);
+
+ m_pCamWnd->SetXYFriend(m_pXYWnd);
+
+ m_pTexWnd = new CTexWnd();
+ m_pTexWnd->Create(TEXTURE_WINDOW_CLASS, "", QE3_SPLITTER_STYLE, rect, this, 1237);
+ ::SetParent(m_pTexWnd->GetSafeHwnd(), g_qeglobals.d_hwndEntity);
+
+ m_pZWnd = new CZWnd();
+ m_pZWnd->Create(Z_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1236);
+ m_pZWnd->ShowWindow(SW_HIDE);
+
+
+ //m_pEditWnd = new CRADEditWnd();
+ //m_pEditWnd->Create(NULL, "Console", QE3_STYLE, rect, this, 1238);
+ //g_pEdit = m_pEditWnd->GetEditWnd();
+ //if (g_pEdit)
+ // g_qeglobals.d_hwndEdit = g_pEdit->GetSafeHwnd();
+
+ LoadWindowState(m_pTexWnd->GetSafeHwnd(), "texwindow");
+ LoadWindowState(m_pEditWnd->GetSafeHwnd(), "editwindow");
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+
+ CreateQEChildren();
+
+ CRect rctParent;
+ GetClientRect(rctParent);
+
+ m_wndSplit.SetRowInfo(0, rctParent.Height() * .5, 50);
+ m_wndSplit.SetRowInfo(1, rctParent.Height() * .5, 50);
+
+ m_wndSplit.SetColumnInfo(0, rctParent.Width() * .5, 50);
+ m_wndSplit.SetColumnInfo(1, rctParent.Width() * .5, 50);
+
+ LoadWindowState(m_wndSplit.GetSafeHwnd(), "Radiant::SplitSPLIT");
+
+ m_wndSplit.RecalcLayout();
+ }
+
+ if (g_pEdit)
+ g_pEdit->SendMessage(WM_SETFONT, (WPARAM)::GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+
+
+ if (m_pXYWnd)
+ m_pXYWnd->SetActive(true);
+ m_bSplittersOK = true;
+ Texture_SetMode(g_qeglobals.d_savedinfo.iTexMenu);
+
+ return TRUE;
+}
+
+CRect g_rctOld(0,0,0,0);
+void CMainFrame::OnSize(UINT nType, int cx, int cy)
+{
+ CFrameWnd::OnSize(nType, cx, cy);
+
+ CRect rctParent;
+ GetClientRect(rctParent);
+
+ UINT nID;
+ UINT nStyle;
+ int nWidth;
+ if (m_wndStatusBar.GetSafeHwnd())
+ {
+ m_wndStatusBar.GetPaneInfo(0, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(0, nID, nStyle, rctParent.Width() * .19);
+ m_wndStatusBar.GetPaneInfo(1, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(1, nID, nStyle, rctParent.Width() * .19);
+ m_wndStatusBar.GetPaneInfo(2, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(2, nID, nStyle, rctParent.Width() * .19);
+ m_wndStatusBar.GetPaneInfo(3, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(3, nID, nStyle, rctParent.Width() * .19);
+ m_wndStatusBar.GetPaneInfo(4, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(4, nID, nStyle, rctParent.Width() * .13);
+ m_wndStatusBar.GetPaneInfo(5, nID, nStyle, nWidth);
+ m_wndStatusBar.SetPaneInfo(5, nID, nStyle, rctParent.Width() * .01);
+ }
+
+ if (nType == SIZE_RESTORED && m_bSplittersOK && g_rctOld.Width() > 0)
+ {
+ if (m_nCurrentStyle == 0 || m_nCurrentStyle == 3)
+ {
+ SplitInfo spinfo;
+ m_wndSplit.GetRowInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc1 = (float)spinfo.m_nCur / g_rctOld.Height();
+ m_wndSplit.GetRowInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc2 = (float)spinfo.m_nCur / g_rctOld.Height();
+ m_wndSplit2.GetColumnInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc3 = (float)spinfo.m_nCur / g_rctOld.Width();
+ m_wndSplit2.GetColumnInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc4 = (float)spinfo.m_nCur / g_rctOld.Width();
+ m_wndSplit2.GetColumnInfo(2, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc5 = (float)spinfo.m_nCur / g_rctOld.Width();
+ m_wndSplit3.GetRowInfo(0, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc6 = (float)spinfo.m_nCur / g_rctOld.Height();
+ m_wndSplit3.GetRowInfo(1, spinfo.m_nCur, spinfo.m_nMin);
+ float fpc7 = (float)spinfo.m_nCur / g_rctOld.Height();
+
+ m_wndSplit.SetRowInfo(0, rctParent.Height() * fpc1, 100);
+ m_wndSplit.SetRowInfo(1, rctParent.Height() * fpc2, 25);
+
+ int nMin1 = (m_nCurrentStyle == 0) ? 10 : 25;
+ int nMin2 = (nMin1 == 10) ? 25 : 10;
+
+ m_wndSplit2.SetColumnInfo(0, rctParent.Width() * fpc3, nMin1);
+ m_wndSplit2.SetColumnInfo(1, rctParent.Width() * fpc4, 100);
+ m_wndSplit2.SetColumnInfo(2, rctParent.Width() * fpc5, nMin2);
+
+ m_wndSplit3.SetRowInfo(0, rctParent.Height() * fpc6, 50);
+ m_wndSplit3.SetRowInfo(1, rctParent.Height() * fpc7, 50);
+
+ m_wndSplit.RecalcLayout();
+ m_wndSplit2.RecalcLayout();
+ m_wndSplit3.RecalcLayout();
+ }
+ }
+
+
+}
+
+
+void OpenDialog (void);
+void SaveAsDialog (bool bRegion);
+void Select_Ungroup (void);
+
+void CMainFrame::ToggleCamera()
+{
+ if (m_bCamPreview)
+ m_bCamPreview = false;
+ else
+ m_bCamPreview = true;
+}
+
+void CMainFrame::OnFileClose()
+{
+
+}
+
+void CMainFrame::OnFileExit()
+{
+ PostMessage (WM_CLOSE, 0, 0L);
+}
+
+void CMainFrame::OnFileLoadproject()
+{
+ if (ConfirmModified())
+ ProjectDialog ();
+}
+
+void CMainFrame::OnFileNew()
+{
+ if (ConfirmModified())
+ Map_New ();
+}
+
+void CMainFrame::OnFileOpen()
+{
+ if (ConfirmModified())
+ OpenDialog ();
+}
+
+void CMainFrame::OnFilePointfile()
+{
+ if (g_qeglobals.d_pointfile_display_list)
+ Pointfile_Clear ();
+ else
+ Pointfile_Check ();
+}
+
+void CMainFrame::OnFilePrint()
+{
+
+}
+
+void CMainFrame::OnFilePrintPreview()
+{
+
+}
+
+void CMainFrame::OnFileSave()
+{
+ if (!strcmp(currentmap, "unnamed.map"))
+ {
+ SaveAsDialog (false);
+ }
+ else
+ {
+ Map_SaveFile (currentmap, false);
+ }
+}
+
+void CMainFrame::OnFileSaveas()
+{
+ SaveAsDialog(false);
+}
+
+void CMainFrame::OnView100()
+{
+ if (m_pXYWnd)
+ m_pXYWnd->SetScale(1);
+ if (m_pXZWnd)
+ m_pXZWnd->SetScale(1);
+ if (m_pYZWnd)
+ m_pYZWnd->SetScale(1);
+ Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
+}
+
+void CMainFrame::OnViewCenter()
+{
+ m_pCamWnd->Camera().angles[ROLL] = m_pCamWnd->Camera().angles[PITCH] = 0;
+ m_pCamWnd->Camera().angles[YAW] = 22.5 *
+ floor( (m_pCamWnd->Camera().angles[YAW]+11)/22.5 );
+ Sys_UpdateWindows (W_CAMERA | W_XY_OVERLAY);
+}
+
+void CMainFrame::OnViewConsole()
+{
+ if (m_nCurrentStyle > 0 && m_nCurrentStyle < 3) // QE4 style
+ {
+ if (inspector_mode == W_CONSOLE && m_nCurrentStyle != QR_QE4) // are we in console mode already?
+ {
+ if (::IsWindowVisible(g_qeglobals.d_hwndEntity))
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+ else
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ }
+ else
+ {
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ SetInspectorMode(W_CONSOLE);
+ }
+ }
+}
+
+void CMainFrame::OnViewDownfloor()
+{
+ m_pCamWnd->Cam_ChangeFloor (false);
+}
+
+void CMainFrame::OnViewEntity()
+{
+ if (m_nCurrentStyle == 0 || m_nCurrentStyle == 3)
+ {
+ if (::IsWindowVisible(g_qeglobals.d_hwndEntity) && inspector_mode == W_ENTITY)
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+ else
+ {
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ SetInspectorMode(W_ENTITY);
+ }
+ }
+ else
+ {
+ if (inspector_mode == W_ENTITY && m_nCurrentStyle != QR_QE4)
+ {
+ if (::IsWindowVisible(g_qeglobals.d_hwndEntity))
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+ else
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ }
+ else
+ {
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ SetInspectorMode(W_ENTITY);
+ }
+ }
+}
+
+void CMainFrame::OnViewFront()
+{
+ if (m_nCurrentStyle != 2)
+ {
+ m_pXYWnd->SetViewType(YZ);
+ m_pXYWnd->PositionView();
+ }
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnMru(unsigned int nID)
+{
+ DoMru(GetSafeHwnd(),nID);
+}
+
+void CMainFrame::OnViewNearest(unsigned int nID)
+{
+ Texture_SetMode(nID);
+}
+
+void CMainFrame::OnTextureWad(unsigned int nID)
+{
+ Sys_BeginWait ();
+ Texture_ShowDirectory (nID);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnBspCommand(unsigned int nID)
+{
+ if (g_PrefsDlg.m_bSnapShots && stricmp(currentmap, "unnamed.map") != 0)
+ Map_Snapshot();
+
+ if (g_qeglobals.bBSPFrontendPlugin)
+ {
+ CString foo = g_BSPFrontendCommands.GetAt(nID-CMD_BSPCOMMAND);
+ g_BSPFrontendTable.m_pfnDispatchBSPCommand( foo.GetBuffer(0) );
+ }
+ else
+ {
+ RunBsp (bsp_commands[LOWORD(nID-CMD_BSPCOMMAND)]);
+ }
+}
+
+
+
+void CMainFrame::OnViewShowblocks()
+{
+ g_qeglobals.show_blocks ^= 1;
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWBLOCKS, MF_BYCOMMAND | (g_qeglobals.show_blocks ? MF_CHECKED : MF_UNCHECKED) );
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnViewShowclip()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_CLIP ) & EXCLUDE_CLIP )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewShowcoordinates()
+{
+ g_qeglobals.d_savedinfo.show_coordinates ^= 1;
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | (g_qeglobals.d_savedinfo.show_coordinates ? MF_CHECKED : MF_UNCHECKED) );
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnViewShowdetail()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_DETAIL ) & EXCLUDE_DETAIL )
+ {
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWDETAIL, MF_BYCOMMAND | MF_UNCHECKED );
+ ::SetWindowText (g_qeglobals.d_hwndCamera, "Camera View (DETAIL EXCLUDED)");
+ }
+ else
+ {
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWDETAIL, MF_BYCOMMAND | MF_CHECKED );
+ ::SetWindowText (g_qeglobals.d_hwndCamera, "Camera View");
+ }
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewShowent()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_ENT ) & EXCLUDE_ENT )
+ CheckMenuItem( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWENT, MF_BYCOMMAND | MF_UNCHECKED);
+ else
+ CheckMenuItem( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWENT, MF_BYCOMMAND | MF_CHECKED);
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewShowlights()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_LIGHTS ) & EXCLUDE_LIGHTS )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewShownames()
+{
+ g_qeglobals.d_savedinfo.show_names = !g_qeglobals.d_savedinfo.show_names;
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWNAMES, MF_BYCOMMAND | (g_qeglobals.d_savedinfo.show_names ? MF_CHECKED : MF_UNCHECKED) );
+ Map_BuildBrushData();
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnViewShowpath()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_PATHS ) & EXCLUDE_PATHS )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewShowwater()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_WATER ) & EXCLUDE_WATER )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewShowworld()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_WORLD ) & EXCLUDE_WORLD )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnViewTexture()
+{
+ if (m_nCurrentStyle > 0 && m_nCurrentStyle < 3) // QE4 style
+ {
+ if (inspector_mode == W_TEXTURE && m_nCurrentStyle != QR_QE4) // are we in console mode already?
+ {
+ if (::IsWindowVisible(g_qeglobals.d_hwndEntity))
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+ else
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_SHOW);
+ }
+ else
+ {
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_SHOW);
+ SetInspectorMode(W_TEXTURE);
+ }
+ }
+}
+
+void CMainFrame::OnViewUpfloor()
+{
+ m_pCamWnd->Cam_ChangeFloor (true);
+}
+
+void CMainFrame::OnViewXy()
+{
+ if (m_nCurrentStyle != 2)
+ {
+ m_pXYWnd->SetViewType(XY);
+ m_pXYWnd->PositionView();
+ }
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnViewZ100()
+{
+ z.scale = 1;
+ Sys_UpdateWindows (W_Z|W_Z_OVERLAY);
+}
+
+void CMainFrame::OnViewZoomin()
+{
+ if (m_pXYWnd && m_pXYWnd->Active())
+ {
+ m_pXYWnd->SetScale(m_pXYWnd->Scale() * 5.0 / 4);
+ if (m_pXYWnd->Scale() > 20)
+ m_pXYWnd->SetScale(20);
+ }
+
+ if (m_pXZWnd && m_pXZWnd->Active())
+ {
+ m_pXZWnd->SetScale(m_pXZWnd->Scale() * 5.0 / 4);
+ if (m_pXZWnd->Scale() > 20)
+ m_pXZWnd->SetScale(20);
+ }
+
+ if (m_pYZWnd && m_pYZWnd->Active())
+ {
+ m_pYZWnd->SetScale(m_pYZWnd->Scale() * 5.0 / 4);
+ if (m_pYZWnd->Scale() > 20)
+ m_pYZWnd->SetScale(20);
+ }
+
+
+ Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
+}
+
+void CMainFrame::OnViewZoomout()
+{
+
+ if (m_pXYWnd && m_pXYWnd->Active())
+ {
+ m_pXYWnd->SetScale(m_pXYWnd->Scale() * 4.0 / 5);
+ if (m_pXYWnd->Scale() < 0.1 / 32)
+ m_pXYWnd->SetScale(0.1 /32);
+ }
+
+ if (m_pXZWnd && m_pXZWnd->Active())
+ {
+ m_pXZWnd->SetScale(m_pXZWnd->Scale() * 4.0 / 5);
+ if (m_pXZWnd->Scale() < 0.1 / 32)
+ m_pXZWnd->SetScale(0.1 / 32);
+ }
+
+ if (m_pYZWnd && m_pYZWnd->Active())
+ {
+ m_pYZWnd->SetScale(m_pYZWnd->Scale() * 4.0 / 5);
+ if (m_pYZWnd->Scale() < 0.1 / 32)
+ m_pYZWnd->SetScale(0.1 / 32);
+ }
+ Sys_UpdateWindows (W_XY|W_XY_OVERLAY);
+}
+
+void CMainFrame::OnViewZzoomin()
+{
+ z.scale *= 5.0/4;
+ if (z.scale > 4)
+ z.scale = 4;
+ Sys_UpdateWindows (W_Z|W_Z_OVERLAY);
+}
+
+void CMainFrame::OnViewZzoomout()
+{
+ z.scale *= 4.0/5;
+ if (z.scale < 0.125)
+ z.scale = 0.125;
+ Sys_UpdateWindows (W_Z|W_Z_OVERLAY);
+}
+
+void CMainFrame::OnViewSide()
+{
+ if (m_nCurrentStyle != 2)
+ {
+ m_pXYWnd->SetViewType(XZ);
+ m_pXYWnd->PositionView();
+ }
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnGrid1(unsigned int nID)
+{
+ HMENU hMenu = ::GetMenu(GetSafeHwnd());
+
+ CheckMenuItem(hMenu, ID_GRID_1, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_2, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_4, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_8, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_16, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_32, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_64, MF_BYCOMMAND | MF_UNCHECKED);
+
+ switch (nID)
+ {
+ case ID_GRID_1: g_qeglobals.d_gridsize = 0; break;
+ case ID_GRID_2: g_qeglobals.d_gridsize = 1; break;
+ case ID_GRID_4: g_qeglobals.d_gridsize = 2; break;
+ case ID_GRID_8: g_qeglobals.d_gridsize = 3; break;
+ case ID_GRID_16: g_qeglobals.d_gridsize = 4; break;
+ case ID_GRID_32: g_qeglobals.d_gridsize = 5; break;
+ case ID_GRID_64: g_qeglobals.d_gridsize = 6; break;
+ }
+ g_qeglobals.d_gridsize = 1 << g_qeglobals.d_gridsize;
+
+ if (g_PrefsDlg.m_bSnapTToGrid)
+ g_qeglobals.d_savedinfo.m_nTextureTweak = g_qeglobals.d_gridsize;
+
+ SetGridStatus();
+ CheckMenuItem(hMenu, nID, MF_BYCOMMAND | MF_CHECKED);
+ Sys_UpdateWindows (W_XY|W_Z);
+
+}
+
+void CMainFrame::OnTexturesShowinuse()
+{
+ Sys_BeginWait ();
+ Texture_ShowInuse ();
+ if (m_pTexWnd)
+ {
+ m_pTexWnd->RedrawWindow();
+ }
+}
+
+//from TexWnd.cpp
+extern qboolean texture_showinuse;
+void CMainFrame::OnUpdateTexturesShowinuse(CCmdUI* pCmdUI)
+{
+ pCmdUI->SetCheck(texture_showinuse);
+}
+
+void CMainFrame::OnTexturesInspector()
+{
+ DoSurface ();
+}
+
+void CMainFrame::OnMiscBenchmark()
+{
+ m_pCamWnd->BenchMark();
+}
+
+void CMainFrame::OnMiscFindbrush()
+{
+ DoFind();
+}
+
+void CMainFrame::OnMiscGamma()
+{
+ float fSave = g_qeglobals.d_savedinfo.fGamma;
+ DoGamma();
+ if (fSave != g_qeglobals.d_savedinfo.fGamma)
+ {
+ MessageBox("You must restart Q3Radiant for Gamma settings to take place");
+ }
+}
+
+void CMainFrame::OnMiscNextleakspot()
+{
+ Pointfile_Next();
+}
+
+void CMainFrame::OnMiscPreviousleakspot()
+{
+ Pointfile_Prev();
+}
+
+void CMainFrame::OnMiscPrintxy()
+{
+ WXY_Print();
+}
+
+void CMainFrame::OnMiscSelectentitycolor()
+{
+ if (edit_entity)
+ {
+ CString strColor = ValueForKey(edit_entity, "_color");
+ if (strColor.GetLength() > 0)
+ {
+ float fR, fG, fB;
+ int n = sscanf(strColor,"%f %f %f", &fR, &fG, &fB);
+ if (n == 3)
+ {
+ g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][0] = fR;
+ g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][1] = fG;
+ g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][2] = fB;
+ }
+ }
+
+ if (inspector_mode == W_ENTITY && (DoColor(COLOR_ENTITY)))
+ {
+ char buffer[100];
+ sprintf(buffer, "%f %f %f", g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][0],
+ g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][1],
+ g_qeglobals.d_savedinfo.colors[COLOR_ENTITY][2]);
+
+ ::SetWindowText( hwndEnt[EntValueField], buffer );
+ ::SetWindowText( hwndEnt[EntKeyField], "_color" );
+ AddProp();
+//DK - SOF change to get color to entity quickly
+ //--::SetWindowText( hwndEnt[EntValueField], buffer );
+//-- ::SetWindowText( hwndEnt[EntKeyField], "color" );
+//-- AddProp();
+ }
+ Sys_UpdateWindows( W_ALL );
+ }
+}
+
+void CMainFrame::OnTexturebk()
+{
+ DoColor(COLOR_TEXTUREBACK);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsMajor()
+{
+ DoColor(COLOR_GRIDMAJOR);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsMinor()
+{
+ DoColor(COLOR_GRIDMINOR);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsXybk()
+{
+ DoColor(COLOR_GRIDBACK);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnBrush3sided()
+{
+ Undo_Start("3 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(3);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrush4sided()
+{
+ Undo_Start("4 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(4);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrush5sided()
+{
+ Undo_Start("5 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(5);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrush6sided()
+{
+ Undo_Start("6 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(6);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrush7sided()
+{
+ Undo_Start("7 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(7);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrush8sided()
+{
+ Undo_Start("8 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(8);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrush9sided()
+{
+ Undo_Start("9 sided");
+ Undo_AddBrushList(&selected_brushes);
+ Brush_MakeSided(9);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushArbitrarysided()
+{
+ Undo_Start("arbitrary sided");
+ Undo_AddBrushList(&selected_brushes);
+ DoSides();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushFlipx()
+{
+ Undo_Start("flip X");
+ Undo_AddBrushList(&selected_brushes);
+
+ Select_FlipAxis (0);
+ for (brush_t *b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ if(b->owner->eclass->fixedsize)
+ {
+ char buf[16];
+ float a = FloatForKey(b->owner, "angle");
+ a = div( ( 180 - a ) , 180 ).rem;
+ SetKeyValue(b->owner, "angle", itoa(a, buf, 10));
+ Brush_Build(b);
+ }
+ }
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushFlipy()
+{
+ Undo_Start("flip Y");
+ Undo_AddBrushList(&selected_brushes);
+
+ Select_FlipAxis (1);
+ for (brush_t *b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ if(b->owner->eclass->fixedsize)
+ {
+ float a = FloatForKey(b->owner, "angle");
+ if (a == 0 || a == 180 || a == 360)
+ continue;
+ if ( a == 90 || a == 270)
+ {
+ a += 180;
+ }
+ else if (a > 270)
+ a += 90;
+ else if (a > 180)
+ a -= 90;
+ else if (a > 90)
+ a += 90;
+ else
+ a -= 90;
+ a = (int)a % 360;
+ char buf[16];
+ SetKeyValue(b->owner, "angle", itoa(a, buf, 10));
+ Brush_Build(b);
+ }
+ }
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushFlipz()
+{
+ Undo_Start("flip Z");
+ Undo_AddBrushList(&selected_brushes);
+ Select_FlipAxis (2);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushRotatex()
+{
+ Undo_Start("rotate X");
+ Undo_AddBrushList(&selected_brushes);
+ Select_RotateAxis (0, 90);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushRotatey()
+{
+ Undo_Start("rotate Y");
+ Undo_AddBrushList(&selected_brushes);
+ Select_RotateAxis (1, 90);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushRotatez()
+{
+ Undo_Start("rotate Z");
+ Undo_AddBrushList(&selected_brushes);
+ Select_RotateAxis (2, 90);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnRegionOff()
+{
+ Map_RegionOff ();
+}
+
+void CMainFrame::OnRegionSetbrush()
+{
+ Map_RegionBrush ();
+}
+
+void CMainFrame::OnRegionSetselection()
+{
+ Map_RegionSelectedBrushes ();
+}
+
+void CMainFrame::OnRegionSettallbrush()
+{
+ Map_RegionTallBrush ();
+}
+
+void CMainFrame::OnRegionSetxy()
+{
+ Map_RegionXY ();
+}
+
+void CMainFrame::OnSelectionArbitraryrotation()
+{
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Undo_Start("arbitrary rotation");
+ Undo_AddBrushList(&selected_brushes);
+
+ CRotateDlg dlg;
+ dlg.DoModal();
+ //DoRotate ();
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionClone()
+{
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Select_Clone();
+}
+
+void CMainFrame::OnSelectionConnect()
+{
+ ConnectEntities();
+}
+
+void CMainFrame::OnSelectionMakehollow()
+{
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Undo_Start("hollow");
+ Undo_AddBrushList(&selected_brushes);
+ CSG_MakeHollow ();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionCsgsubtract()
+{
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Undo_Start("CSG subtract");
+ CSG_Subtract();
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionCsgmerge()
+{
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Undo_Start("CSG merge");
+ Undo_AddBrushList(&selected_brushes);
+ CSG_Merge();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionNoOutline()
+{
+ g_qeglobals.dontDrawSelectedOutlines ^= 1;
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnSelectionDelete()
+{
+ brush_t *brush;
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Undo_Start("delete");
+ Undo_AddBrushList(&selected_brushes);
+ //add all deleted entities to the undo
+ for (brush = selected_brushes.next; brush != &selected_brushes; brush = brush->next)
+ {
+ Undo_AddEntity(brush->owner);
+ }
+ // NOTE: Select_Delete does NOT delete entities
+ Select_Delete();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionDeselect()
+{
+ if (!ByeByeSurfaceDialog())
+ {
+ if (g_bClipMode)
+ OnViewClipper();
+ else if (g_bRotateMode)
+ OnSelectMouserotate();
+ else if (g_bScaleMode)
+ OnSelectMousescale();
+ else if (g_bPathMode)
+ {
+ if (ActiveXY())
+ ActiveXY()->KillPathMode();
+ }
+ else
+ {
+ if (g_qeglobals.d_select_mode == sel_curvepoint && g_qeglobals.d_num_move_points > 0)
+ {
+ g_qeglobals.d_num_move_points = 0;
+ Sys_UpdateWindows(W_ALL);
+ }
+ else if ( g_qeglobals.d_select_mode == sel_terrainpoint && g_qeglobals.d_numterrapoints > 0 )
+ {
+ g_qeglobals.d_numterrapoints = 0;
+ Sys_UpdateWindows( W_ALL );
+ }
+ else
+ {
+ Select_Deselect ();
+ SetStatusText(2, " ");
+ }
+ }
+ }
+}
+
+void CMainFrame::OnSelectionDragedges()
+{
+ if (g_qeglobals.d_select_mode == sel_edge)
+ {
+ clearSelection();
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ {
+ SetupVertexSelection ();
+ if (g_qeglobals.d_numpoints)
+ g_qeglobals.d_select_mode = sel_edge;
+ Sys_UpdateWindows (W_ALL);
+ }
+}
+
+void CMainFrame::OnSelectionDragvertecies()
+{
+ if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_curvepoint ||
+ g_qeglobals.d_select_mode == sel_terrainpoint )
+ {
+ clearSelection();
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ {
+ //--if (QE_SingleBrush() && selected_brushes.next->patchBrush)
+ if ( OnlyTerrainSelected() )
+ {
+ //Terrain_Edit();
+ }
+ else if (OnlyPatchesSelected())
+ {
+ Patch_EditPatch();
+ }
+ else if ( !AnyPatchesSelected() && !AnyTerrainSelected() )
+ {
+ SetupVertexSelection ();
+ if (g_qeglobals.d_numpoints)
+ g_qeglobals.d_select_mode = sel_vertex;
+ }
+ Sys_UpdateWindows (W_ALL);
+ }
+}
+
+void CMainFrame::OnRaiseLowerTerrain()
+{
+ //if ( !OnlyTerrainSelected() || ( g_qeglobals.d_select_mode == sel_terrainpoint ) )
+ //if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) )
+ if ( g_qeglobals.d_select_mode == sel_terrainpoint ) {
+ clearSelection();
+ Sys_UpdateWindows (W_ALL);
+ }
+ else if ( g_qeglobals.d_select_mode == sel_terraintexture ) {
+ clearSelection();
+ g_qeglobals.d_select_mode = sel_terrainpoint;
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ {
+ //g_qeglobals.d_select_mode = sel_terrainpoint;
+ clearSelection();
+ g_qeglobals.d_select_mode = sel_terraintexture;
+ Sys_UpdateWindows (W_ALL);
+// Terrain_Edit();
+ }
+}
+
+void CMainFrame::OnSelectionMakeDetail()
+{
+ Undo_Start("make detail");
+ Undo_AddBrushList(&selected_brushes);
+ Select_MakeDetail ();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionMakeStructural()
+{
+ Undo_Start("make structural");
+ Undo_AddBrushList(&selected_brushes);
+ Select_MakeStructural ();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionSelectcompletetall()
+{
+ if (ActiveXY())
+ ActiveXY()->UndoCopy();
+ Select_CompleteTall ();
+}
+
+void CMainFrame::OnSelectionSelectinside()
+{
+ Select_Inside ();
+}
+
+void CMainFrame::OnSelectionSelectpartialtall()
+{
+ Select_PartialTall();
+}
+
+void CMainFrame::OnSelectionSelecttouching()
+{
+ Select_Touching();
+}
+
+void CMainFrame::OnSelectionUngroupentity()
+{
+ Select_Ungroup();
+}
+
+void CMainFrame::OnTexturesPopup()
+{
+ HandlePopup(this, IDR_POPUP_TEXTURE);
+}
+
+void CMainFrame::OnSplinesPopup()
+{
+ HandlePopup(this, IDR_POPUP_SPLINE);
+}
+
+void CMainFrame::OnPopupSelection()
+{
+ HandlePopup(this, IDR_POPUP_SELECTION);
+}
+
+void CMainFrame::OnViewChange()
+{
+ OnViewNextview();
+ //HandlePopup(this, IDR_POPUP_VIEW);
+}
+
+void CMainFrame::OnViewCameraupdate()
+{
+ Sys_UpdateWindows(W_CAMERA);
+}
+
+void CMainFrame::OnUpdateViewCameraupdate(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(m_bCamPreview == false);
+}
+
+void CMainFrame::OnSizing(UINT fwSide, LPRECT pRect)
+{
+ CFrameWnd::OnSizing(fwSide, pRect);
+ GetClientRect(g_rctOld);
+}
+
+void CMainFrame::OnHelpAbout()
+{
+ DoAbout();
+}
+
+void CMainFrame::OnViewClipper()
+{
+ if (ActiveXY())
+ {
+ if (ActiveXY()->ClipMode())
+ {
+ ActiveXY()->SetClipMode(false);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_VIEW_CLIPPER, FALSE);
+ }
+ else
+ {
+ if (ActiveXY()->RotateMode())
+ OnSelectMouserotate();
+ ActiveXY()->SetClipMode(true);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_VIEW_CLIPPER);
+ }
+ }
+}
+
+void CMainFrame::OnCameraAngledown()
+{
+ m_pCamWnd->Camera().angles[0] -= SPEED_TURN;
+ if (m_pCamWnd->Camera().angles[0] < -85)
+ m_pCamWnd->Camera().angles[0] = -85;
+ Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
+}
+
+void CMainFrame::OnCameraAngleup()
+{
+ m_pCamWnd->Camera().angles[0] += SPEED_TURN;
+ if (m_pCamWnd->Camera().angles[0] > 85)
+ m_pCamWnd->Camera().angles[0] = 85;
+ Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
+}
+
+void CMainFrame::OnCameraBack()
+{
+ VectorMA (m_pCamWnd->Camera().origin, -SPEED_MOVE, m_pCamWnd->Camera().forward, m_pCamWnd->Camera().origin);
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraDown()
+{
+ m_pCamWnd->Camera().origin[2] -= SPEED_MOVE;
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraForward()
+{
+ VectorMA (m_pCamWnd->Camera().origin, SPEED_MOVE, m_pCamWnd->Camera().forward, m_pCamWnd->Camera().origin);
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraLeft()
+{
+ m_pCamWnd->Camera().angles[1] += SPEED_TURN;
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraRight()
+{
+ m_pCamWnd->Camera().angles[1] -= SPEED_TURN;
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraStrafeleft()
+{
+ VectorMA (m_pCamWnd->Camera().origin, -SPEED_MOVE, m_pCamWnd->Camera().right, m_pCamWnd->Camera().origin);
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraStraferight()
+{
+ VectorMA (m_pCamWnd->Camera().origin, SPEED_MOVE, m_pCamWnd->Camera().right, m_pCamWnd->Camera().origin);
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnCameraUp()
+{
+ m_pCamWnd->Camera().origin[2] += SPEED_MOVE;
+ int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
+ Sys_UpdateWindows (nUpdate);
+}
+
+void CMainFrame::OnGridToggle()
+{
+ g_qeglobals.d_showgrid = !g_qeglobals.d_showgrid;
+ Sys_UpdateWindows (W_XY|W_Z);
+}
+
+void CMainFrame::OnPrefs()
+{
+ int nView = g_PrefsDlg.m_nView;
+ BOOL bToolbar = g_PrefsDlg.m_bWideToolbar;
+ BOOL bTextureBar = g_PrefsDlg.m_bTextureBar;
+ BOOL bSGIOpenGL = g_PrefsDlg.m_bSGIOpenGL;
+ BOOL bBuggyICD = g_PrefsDlg.m_bBuggyICD;
+ int nShader = g_PrefsDlg.m_nShader;
+ g_PrefsDlg.LoadPrefs();
+ if (g_PrefsDlg.DoModal() == IDOK)
+ {
+ if (g_PrefsDlg.m_nView != nView || g_PrefsDlg.m_bWideToolbar != bToolbar
+ || g_PrefsDlg.m_bSGIOpenGL != bSGIOpenGL || g_PrefsDlg.m_bBuggyICD != bBuggyICD || nShader != g_PrefsDlg.m_nShader)
+ MessageBox("You need to restart Q3Radiant for the view changes to take place.");
+ if (m_pTexWnd)
+ m_pTexWnd->UpdatePrefs();
+ if (bTextureBar != g_PrefsDlg.m_bTextureBar)
+ {
+ if (bTextureBar) // was turned on
+ ShowControlBar(&m_wndTextureBar, TRUE, TRUE);
+ else // was turned off
+ ShowControlBar(&m_wndTextureBar, FALSE, TRUE);
+ m_wndTextureBar.Invalidate();
+ }
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ pMenu->CheckMenuItem(ID_SNAPTOGRID, MF_BYCOMMAND | (!g_PrefsDlg.m_bNoClamp) ? MF_CHECKED : MF_UNCHECKED);
+ }
+}
+
+// 0 = radiant styel
+// 1 = qe4 style
+void CMainFrame::SetWindowStyle(int nStyle)
+{
+}
+
+void CMainFrame::OnTogglecamera()
+{
+ if (m_nCurrentStyle > 0 && m_nCurrentStyle < 3) // QE4 style
+ {
+ if (m_pCamWnd && m_pCamWnd->GetSafeHwnd())
+ {
+ if (m_pCamWnd->IsWindowVisible())
+ m_pCamWnd->ShowWindow(SW_HIDE);
+ else
+ m_pCamWnd->ShowWindow(SW_SHOW);
+ }
+ }
+}
+
+void CMainFrame::OnToggleconsole()
+{
+ if (m_nCurrentStyle > 0 && m_nCurrentStyle < 3) // QE4 style
+ {
+ if (m_pEditWnd && m_pEditWnd->GetSafeHwnd())
+ {
+ if (m_pEditWnd->IsWindowVisible())
+ m_pEditWnd->ShowWindow(SW_HIDE);
+ else
+ m_pEditWnd->ShowWindow(SW_SHOW);
+ }
+ }
+}
+
+void CMainFrame::OnToggleview()
+{
+ if (m_nCurrentStyle == 1) // QE4 style
+ {
+ if (m_pXYWnd && m_pXYWnd->GetSafeHwnd())
+ {
+ if (m_pXYWnd->IsWindowVisible())
+ m_pXYWnd->ShowWindow(SW_HIDE);
+ else
+ m_pXYWnd->ShowWindow(SW_SHOW);
+ }
+ }
+}
+
+void CMainFrame::OnTogglez()
+{
+ if (m_nCurrentStyle == 1 || m_nCurrentStyle == 2) // QE4 style
+ {
+ if (m_pZWnd && m_pZWnd->GetSafeHwnd())
+ {
+ if (m_pZWnd->IsWindowVisible())
+ m_pZWnd->ShowWindow(SW_HIDE);
+ else
+ m_pZWnd->ShowWindow(SW_SHOW);
+ }
+ }
+ else
+ {
+ Undo_Redo();
+ }
+}
+
+void CMainFrame::OnToggleLock()
+{
+ g_PrefsDlg.m_bTextureLock = !g_PrefsDlg.m_bTextureLock;
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ pMenu->CheckMenuItem(ID_TOGGLE_LOCK, MF_BYCOMMAND | (g_PrefsDlg.m_bTextureLock) ? MF_CHECKED : MF_UNCHECKED);
+ g_PrefsDlg.SavePrefs();
+ SetGridStatus();
+}
+
+void CMainFrame::OnEditMapinfo()
+{
+ CMapInfo dlg;
+ dlg.DoModal();
+}
+
+void CMainFrame::OnEditEntityinfo()
+{
+ CEntityListDlg dlg;
+ dlg.DoModal();
+}
+
+
+
+void CMainFrame::OnBrushScripts()
+{
+ CScriptDlg dlg;
+ dlg.DoModal();
+}
+
+void CMainFrame::OnViewNextview()
+{
+ if (m_nCurrentStyle != 2)
+ {
+ if (m_pXYWnd->GetViewType() == XY)
+ m_pXYWnd->SetViewType(XZ);
+ else
+ if (m_pXYWnd->GetViewType() == XZ)
+ m_pXYWnd->SetViewType(YZ);
+ else
+ m_pXYWnd->SetViewType(XY);
+ m_pXYWnd->PositionView();
+ Sys_UpdateWindows (W_XY);
+ }
+}
+
+void CMainFrame::OnHelpCommandlist()
+{
+ CCommandsDlg dlg;
+ dlg.DoModal();
+#if 0
+ if (g_b3Dfx)
+ {
+ C3DFXCamWnd* pWnd = new C3DFXCamWnd();
+ CRect rect(50,50,400, 400);
+ pWnd->Create(_3DFXCAMERA_WINDOW_CLASS, "", QE3_CHILDSTYLE, rect, this, 1234);
+ pWnd->ShowWindow(SW_SHOW);
+ }
+#endif
+}
+
+void CMainFrame::OnFileNewproject()
+{
+ CNewProjDlg dlg;
+ if (dlg.DoModal() == IDOK && dlg.m_strName.GetLength() > 0)
+ {
+ CString strQ2;
+ CString strQ2File;
+ ExtractPath_and_Filename(g_PrefsDlg.m_strQuake2, strQ2, strQ2File);
+
+
+ AddSlash(strQ2);
+ strQ2 += dlg.m_strName;
+ CString strProjToLoad;
+ CString strMapToLoad;
+ bool bGood = true;
+ if (::CreateDirectory(strQ2, NULL))
+ {
+ CString strDir = strQ2;
+ strDir += "\\maps";
+ if (::CreateDirectory(strDir, NULL))
+ {
+ CString strSource = g_strAppPath;
+ AddSlash(strSource);
+ strSource += "projmap.dat";
+ CString strDest = strDir;
+ AddSlash(strDest);
+ CString strName;
+ strName.Format("%s.map", dlg.m_strName);
+ strDest += strName;
+ strMapToLoad = strDest;
+ if (!::CopyFile(strSource, strDest, FALSE))
+ bGood = false;
+ }
+ else bGood = false;
+
+ strDir = strQ2;
+ strDir += "\\pics";
+ if (::CreateDirectory(strDir, NULL))
+ {
+ CString strSource = g_strAppPath;
+ AddSlash(strSource);
+ strSource += "colormap.pcx";
+ CString strDest = strDir;
+ AddSlash(strDest);
+ strDest += "colormap.pcx";
+ if (!::CopyFile(strSource, strDest, FALSE))
+ bGood = false;
+ }
+ else bGood = false;
+
+ strDir = strQ2;
+ strDir += "\\scripts";
+ if (::CreateDirectory(strDir, NULL))
+ {
+ CString strSource = g_strAppPath;
+ AddSlash(strSource);
+ strSource += "projqe4.dat";
+ CString strDest = strDir;
+ AddSlash(strDest);
+ strDest += "quake.qe4";
+ if (!::CopyFile(strSource, strDest, FALSE))
+ bGood = false;
+ else
+ strProjToLoad = strDest;
+ }
+ else bGood = false;
+ if (bGood && strProjToLoad.GetLength() > 0)
+ {
+ if (QE_LoadProject(strProjToLoad.GetBuffer(0)))
+ {
+ if (strMapToLoad.GetLength() > 0)
+ Map_LoadFile(strMapToLoad.GetBuffer(0));
+ }
+ }
+ }
+ else
+ {
+ CString strMsg;
+ strMsg.Format("Unable to create directory %s", strQ2);
+ MessageBox(strMsg);
+ }
+
+ }
+}
+
+void CMainFrame::UpdateStatusText()
+{
+ for (int n = 0; n < 6; n++)
+ {
+ if (m_strStatus[n].GetLength() >= 0 && m_wndStatusBar.GetSafeHwnd())
+ m_wndStatusBar.SetPaneText(n, m_strStatus[n]);
+ }
+}
+
+void CMainFrame::SetStatusText(int nPane, const char * pText)
+{
+ if (pText && nPane <= 5 && nPane > 0)
+ {
+ m_strStatus[nPane] = pText;
+ UpdateStatusText();
+ }
+}
+
+void CMainFrame::UpdateWindows(int nBits)
+{
+
+ if (!g_bScreenUpdates)
+ return;
+
+ if (nBits & (W_XY | W_XY_OVERLAY))
+ {
+ if (m_pXYWnd)
+ m_pXYWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ if (m_pXZWnd)
+ m_pXZWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ if (m_pYZWnd)
+ m_pYZWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+
+ if (nBits & W_CAMERA || ((nBits & W_CAMERA_IFON) && m_bCamPreview))
+ {
+ if (m_pCamWnd)
+ {
+ m_pCamWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+ }
+
+ if (nBits & (W_Z | W_Z_OVERLAY))
+ {
+ if (m_pZWnd)
+ m_pZWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+
+ if (nBits & W_TEXTURE)
+ {
+ if (m_pTexWnd)
+ m_pTexWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ }
+}
+
+void WINAPI Sys_UpdateWindows (int nBits)
+{
+ if (g_PrefsDlg.m_bQE4Painting)
+ g_nUpdateBits |= nBits;
+ else
+ g_pParentWnd->UpdateWindows(nBits);
+}
+
+
+
+void CMainFrame::OnFlipClip()
+{
+ if (m_pActiveXY)
+ m_pActiveXY->FlipClip();
+}
+
+void CMainFrame::OnClipSelected()
+{
+ if (m_pActiveXY && m_pActiveXY->ClipMode())
+ {
+ Undo_Start("clip selected");
+ Undo_AddBrushList(&selected_brushes);
+ m_pActiveXY->Clip();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+ }
+ else
+ {
+ if (g_bPatchBendMode)
+ Patch_BendHandleENTER();
+ else if (g_bPatchBendMode)
+ Patch_InsDelHandleENTER();
+ }
+}
+
+void CMainFrame::OnSplitSelected()
+{
+ if (m_pActiveXY)
+ {
+ Undo_Start("split selected");
+ Undo_AddBrushList(&selected_brushes);
+ m_pActiveXY->SplitClip();
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+ }
+}
+
+CXYWnd* CMainFrame::ActiveXY()
+{
+ return m_pActiveXY;
+}
+
+
+void CMainFrame::OnToggleviewXz()
+{
+ if (m_nCurrentStyle == 1) // QE4 style
+ {
+ if (m_pXZWnd && m_pXZWnd->GetSafeHwnd())
+ {
+ // get windowplacement doesn't actually save this so we will here
+ g_PrefsDlg.m_bXZVis = m_pXZWnd->IsWindowVisible();
+ if (g_PrefsDlg.m_bXZVis)
+ m_pXZWnd->ShowWindow(SW_HIDE);
+ else
+ m_pXZWnd->ShowWindow(SW_SHOW);
+ g_PrefsDlg.m_bXZVis ^= 1;
+ g_PrefsDlg.SavePrefs();
+ }
+ }
+}
+
+void CMainFrame::OnToggleviewYz()
+{
+ if (m_nCurrentStyle == 1) // QE4 style
+ {
+ if (m_pYZWnd && m_pYZWnd->GetSafeHwnd())
+ {
+ g_PrefsDlg.m_bYZVis = m_pYZWnd->IsWindowVisible();
+ if (g_PrefsDlg.m_bYZVis)
+ m_pYZWnd->ShowWindow(SW_HIDE);
+ else
+ m_pYZWnd->ShowWindow(SW_SHOW);
+ g_PrefsDlg.m_bYZVis ^= 1;
+ g_PrefsDlg.SavePrefs();
+ }
+ }
+}
+
+void CMainFrame::OnColorsBrush()
+{
+ DoColor(COLOR_BRUSHES);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsClipper()
+{
+ DoColor(COLOR_CLIPPER);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsGridtext()
+{
+ DoColor(COLOR_GRIDTEXT);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsSelectedbrush()
+{
+ DoColor(COLOR_SELBRUSHES);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorsGridblock()
+{
+ DoColor(COLOR_GRIDBLOCK);
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+
+void CMainFrame::OnColorsViewname()
+{
+ DoColor(COLOR_VIEWNAME);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorSetoriginal()
+{
+ for (int i=0 ; i<3 ; i++)
+ {
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
+ }
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.75;
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorSetqer()
+{
+ for (int i=0 ; i<3 ; i++)
+ {
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
+ }
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.75;
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnColorSetblack()
+{
+ for (int i=0 ; i<3 ; i++)
+ {
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
+ }
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][0] = 0.3;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][1] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][2] = 0.5;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.7;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.7;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.0;
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnSnaptogrid()
+{
+ g_PrefsDlg.m_bNoClamp ^= 1;
+ g_PrefsDlg.SavePrefs();
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ pMenu->CheckMenuItem(ID_SNAPTOGRID, MF_BYCOMMAND | (!g_PrefsDlg.m_bNoClamp) ? MF_CHECKED : MF_UNCHECKED);
+}
+
+
+void CMainFrame::OnSelectScale()
+{
+ //if (ActiveXY())
+ // ActiveXY()->UndoCopy();
+ Undo_Start("scale");
+ Undo_AddBrushList(&selected_brushes);
+
+ CScaleDialog dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ if (dlg.m_fX > 0 && dlg.m_fY > 0 && dlg.m_fZ > 0)
+ {
+ Select_Scale(dlg.m_fX, dlg.m_fY, dlg.m_fZ);
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ Sys_Printf("Warning.. Tried to scale by a zero value.");
+ }
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectMouserotate()
+{
+ if (ActiveXY())
+ {
+ if (ActiveXY()->ClipMode())
+ OnViewClipper();
+ if (ActiveXY()->RotateMode())
+ {
+ // SetRotateMode(false) always works
+ ActiveXY()->SetRotateMode(false);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SELECT_MOUSEROTATE, FALSE);
+ Map_BuildBrushData();
+ }
+ else
+ {
+ // may not work if no brush selected, see return value
+ if (ActiveXY()->SetRotateMode(true))
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SELECT_MOUSEROTATE, TRUE);
+ else
+ // if MFC called, we need to set back to FALSE ourselves
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SELECT_MOUSEROTATE, FALSE);
+ }
+
+ }
+}
+
+void CMainFrame::OnEditCopybrush()
+{
+ if (ActiveXY())
+ ActiveXY()->Copy();
+}
+
+void CMainFrame::OnEditPastebrush()
+{
+ if (ActiveXY())
+ ActiveXY()->Paste();
+}
+
+void CMainFrame::OnEditUndo()
+{
+// if (ActiveXY())
+// ActiveXY()->Undo();
+ Undo_Undo();
+}
+
+void CMainFrame::OnEditRedo()
+{
+ Undo_Redo();
+}
+
+void CMainFrame::OnUpdateEditUndo(CCmdUI* pCmdUI)
+{
+ /*
+ BOOL bEnable = false;
+ if (ActiveXY())
+ bEnable = ActiveXY()->UndoAvailable();
+ pCmdUI->Enable(bEnable);
+ */
+ pCmdUI->Enable(Undo_UndoAvailable());
+}
+
+void CMainFrame::OnUpdateEditRedo(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(Undo_RedoAvailable());
+}
+
+void CMainFrame::OnSelectionTextureDec()
+{
+ g_qeglobals.d_savedinfo.m_nTextureTweak--;
+ if (g_qeglobals.d_savedinfo.m_nTextureTweak == 0)
+ g_qeglobals.d_savedinfo.m_nTextureTweak--;
+ SetTexValStatus();
+}
+
+void CMainFrame::OnSelectionTextureFit()
+{
+ // TODO: Add your command handler code here
+
+}
+
+void CMainFrame::OnSelectionTextureInc()
+{
+ g_qeglobals.d_savedinfo.m_nTextureTweak++;
+ if (g_qeglobals.d_savedinfo.m_nTextureTweak == 0)
+ g_qeglobals.d_savedinfo.m_nTextureTweak++;
+ SetTexValStatus();
+}
+
+void CMainFrame::OnSelectionTextureRotateclock()
+{
+ Select_RotateTexture(abs(g_PrefsDlg.m_nRotation));
+}
+
+void CMainFrame::OnSelectionTextureRotatecounter()
+{
+ Select_RotateTexture(-abs(g_PrefsDlg.m_nRotation));
+}
+
+void CMainFrame::OnSelectionTextureScaledown()
+{
+ Select_ScaleTexture(0, -abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+}
+
+void CMainFrame::OnSelectionTextureScaleup()
+{
+ Select_ScaleTexture(0, abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+}
+
+void CMainFrame::OnSelectionTextureScaleLeft()
+{
+ Select_ScaleTexture(-abs(g_qeglobals.d_savedinfo.m_nTextureTweak),0);
+}
+
+void CMainFrame::OnSelectionTextureScaleRight()
+{
+ Select_ScaleTexture(abs(g_qeglobals.d_savedinfo.m_nTextureTweak),0);
+}
+
+void CMainFrame::OnSelectionTextureShiftdown()
+{
+ Select_ShiftTexture(0, -abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+}
+
+void CMainFrame::OnSelectionTextureShiftleft()
+{
+ Select_ShiftTexture(-abs(g_qeglobals.d_savedinfo.m_nTextureTweak), 0);
+}
+
+void CMainFrame::OnSelectionTextureShiftright()
+{
+ Select_ShiftTexture(abs(g_qeglobals.d_savedinfo.m_nTextureTweak), 0);
+}
+
+void CMainFrame::OnSelectionTextureShiftup()
+{
+ Select_ShiftTexture(0, abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+}
+
+void CMainFrame::OnGridNext()
+{
+ if (g_qeglobals.d_gridsize < 64)
+ {
+ g_qeglobals.d_gridsize = g_qeglobals.d_gridsize << 1;
+ Sys_UpdateWindows(W_XY | W_Z);
+ SetGridStatus();
+
+ HMENU hMenu = ::GetMenu(GetSafeHwnd());
+ CheckMenuItem(hMenu, ID_GRID_1, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_2, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_4, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_8, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_16, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_32, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_64, MF_BYCOMMAND | MF_UNCHECKED);
+
+ int nID;
+ switch (g_qeglobals.d_gridsize)
+ {
+ case 1: nID = ID_GRID_1; break;
+ case 2: nID = ID_GRID_2; break;
+ case 4: nID = ID_GRID_4; break;
+ case 8: nID = ID_GRID_8; break;
+ case 16: nID = ID_GRID_16; break;
+ case 32: nID = ID_GRID_32; break;
+ case 64: nID = ID_GRID_64; break;
+ }
+ CheckMenuItem(hMenu, nID, MF_BYCOMMAND | MF_CHECKED);
+ }
+}
+
+void CMainFrame::OnGridPrev()
+{
+ if (g_qeglobals.d_gridsize > 1)
+ {
+ g_qeglobals.d_gridsize = g_qeglobals.d_gridsize >> 1;
+ Sys_UpdateWindows(W_XY | W_Z);
+ SetGridStatus();
+ HMENU hMenu = ::GetMenu(GetSafeHwnd());
+ CheckMenuItem(hMenu, ID_GRID_1, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_2, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_4, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_8, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_16, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_32, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_GRID_64, MF_BYCOMMAND | MF_UNCHECKED);
+
+ int nID;
+ switch (g_qeglobals.d_gridsize)
+ {
+ case 1: nID = ID_GRID_1; break;
+ case 2: nID = ID_GRID_2; break;
+ case 4: nID = ID_GRID_4; break;
+ case 8: nID = ID_GRID_8; break;
+ case 16: nID = ID_GRID_16; break;
+ case 32: nID = ID_GRID_32; break;
+ case 64: nID = ID_GRID_64; break;
+ }
+ CheckMenuItem(hMenu, nID, MF_BYCOMMAND | MF_CHECKED);
+ }
+}
+
+void CMainFrame::SetGridStatus()
+{
+ CString strStatus;
+ char c1;
+ char c2;
+ c1 = (g_PrefsDlg.m_bTextureLock) ? 'M' : ' ';
+ c2 = (g_PrefsDlg.m_bRotateLock) ? 'R' : ' ';
+ strStatus.Format("G:%i T:%i R:%i C:%i L:%c%c", g_qeglobals.d_gridsize, g_qeglobals.d_savedinfo.m_nTextureTweak, g_PrefsDlg.m_nRotation, g_PrefsDlg.m_nCubicScale, c1, c2);
+ SetStatusText(4, strStatus);
+}
+
+void CMainFrame::SetTexValStatus()
+{
+ //CString strStatus;
+ //strStatus.Format("T: %i C: %i", g_nTextureTweak, g_nCubicScale);
+ //SetStatusText(5, strStatus.GetBuffer(0));
+ SetGridStatus();
+}
+
+void CMainFrame::OnTextureReplaceall()
+{
+ CFindTextureDlg::show();
+}
+
+
+void CMainFrame::OnScalelockx()
+{
+ if (g_nScaleHow & SCALE_X)
+ {
+ g_nScaleHow ^= SCALE_X;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKX, FALSE);
+ }
+ else
+ {
+ g_nScaleHow |= SCALE_X;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKX);
+ }
+}
+
+void CMainFrame::OnScalelocky()
+{
+ if (g_nScaleHow & SCALE_Y)
+ {
+ g_nScaleHow ^= SCALE_Y;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKY, FALSE);
+ }
+ else
+ {
+ g_nScaleHow |= SCALE_Y;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKY);
+ }
+}
+
+void CMainFrame::OnScalelockz()
+{
+ if (g_nScaleHow & SCALE_Z)
+ {
+ g_nScaleHow ^= SCALE_Z;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKZ, FALSE);
+ }
+ else
+ {
+ g_nScaleHow |= SCALE_Z;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SCALELOCKZ);
+ }
+}
+
+void CMainFrame::OnSelectMousescale()
+{
+ if (ActiveXY())
+ {
+ if (ActiveXY()->ClipMode())
+ OnViewClipper();
+ if (ActiveXY()->RotateMode())
+ {
+ // SetRotateMode(false) always works
+ ActiveXY()->SetRotateMode(false);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SELECT_MOUSESCALE, FALSE);
+ }
+ if (ActiveXY()->ScaleMode())
+ {
+ ActiveXY()->SetScaleMode(false);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SELECT_MOUSESCALE, FALSE);
+ }
+ else
+ {
+ ActiveXY()->SetScaleMode(true);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_SELECT_MOUSESCALE);
+ }
+ }
+}
+
+void CMainFrame::OnFileImport()
+{
+}
+
+void CMainFrame::OnFileProjectsettings()
+{
+ DoProjectSettings();
+}
+
+void CMainFrame::OnUpdateFileImport(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(FALSE);
+}
+
+void CMainFrame::OnViewCubein()
+{
+ g_PrefsDlg.m_nCubicScale--;
+ if (g_PrefsDlg.m_nCubicScale < 1)
+ g_PrefsDlg.m_nCubicScale = 1;
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows(W_CAMERA);
+ SetTexValStatus();
+}
+
+void CMainFrame::OnViewCubeout()
+{
+ g_PrefsDlg.m_nCubicScale++;
+ if (g_PrefsDlg.m_nCubicScale > 22)
+ g_PrefsDlg.m_nCubicScale = 22;
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows(W_CAMERA);
+ SetTexValStatus();
+}
+
+void CMainFrame::OnViewCubicclipping()
+{
+ g_PrefsDlg.m_bCubicClipping ^= 1;
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ pMenu->CheckMenuItem(ID_VIEW_CUBICCLIPPING, MF_BYCOMMAND | (g_PrefsDlg.m_bCubicClipping) ? MF_CHECKED : MF_UNCHECKED);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_VIEW_CUBICCLIPPING, (g_PrefsDlg.m_bCubicClipping) ? TRUE : FALSE);
+ g_PrefsDlg.SavePrefs();
+ Map_BuildBrushData ();
+ Sys_UpdateWindows(W_CAMERA);
+}
+
+
+void CMainFrame::OnFileSaveregion()
+{
+ SaveAsDialog (true);
+}
+
+void CMainFrame::OnUpdateFileSaveregion(CCmdUI* pCmdUI)
+{
+ pCmdUI->Enable(static_cast<BOOL>(region_active));
+}
+
+void CMainFrame::OnSelectionMovedown()
+{
+ Undo_Start("move up");
+ Undo_AddBrushList(&selected_brushes);
+
+ vec3_t vAmt;
+ vAmt[0] = vAmt[1] = 0.0;
+ vAmt[2] = -g_qeglobals.d_gridsize;
+ Select_Move (vAmt);
+ Sys_UpdateWindows(W_CAMERA | W_XY | W_Z);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnSelectionMoveup()
+{
+ vec3_t vAmt;
+ vAmt[0] = vAmt[1] = 0.0;
+ vAmt[2] = g_qeglobals.d_gridsize;
+ Select_Move (vAmt);
+ Sys_UpdateWindows(W_CAMERA | W_XY | W_Z);
+}
+
+void CMainFrame::OnToolbarMain()
+{
+
+}
+
+void CMainFrame::OnToolbarTexture()
+{
+
+}
+
+void CMainFrame::OnSelectionPrint()
+{
+ for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ Brush_Print(b);
+}
+
+void CMainFrame::UpdateTextureBar()
+{
+ if (m_wndTextureBar.GetSafeHwnd())
+ m_wndTextureBar.GetSurfaceAttributes();
+}
+
+bool g_bTABDown = false;
+bool g_bOriginalFlag;
+void CMainFrame::OnSelectionTogglesizepaint()
+{
+ if (::GetAsyncKeyState('Q'))
+ {
+ if (!g_bTABDown)
+ {
+ g_bTABDown = true;
+ g_bOriginalFlag = g_PrefsDlg.m_bSizePaint;
+ g_PrefsDlg.m_bSizePaint = !g_bOriginalFlag;
+ Sys_UpdateWindows(W_XY);
+ return;
+ }
+ }
+ else
+ {
+ g_bTABDown = false;
+ g_PrefsDlg.m_bSizePaint = g_bOriginalFlag;
+ Sys_UpdateWindows(W_XY);
+ return;
+ }
+}
+
+void CMainFrame::OnBrushMakecone()
+{
+ Undo_Start("make cone");
+ Undo_AddBrushList(&selected_brushes);
+ DoSides(true);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+
+void CMainFrame::OnTexturesLoad()
+{
+ BROWSEINFO bi;
+ CString strPath;
+ char* p = strPath.GetBuffer(MAX_PATH+1);
+ bi.hwndOwner = GetSafeHwnd();
+ bi.pidlRoot = NULL;
+ bi.pszDisplayName = p;
+ bi.lpszTitle = "Load textures from path";
+ bi.ulFlags = 0;
+ bi.lpfn = NULL;
+ bi.lParam = NULL;
+ bi.iImage = 0;
+ LPITEMIDLIST pidlBrowse;
+ pidlBrowse = SHBrowseForFolder(&bi);
+ if (pidlBrowse)
+ {
+ SHGetPathFromIDList(pidlBrowse, p);
+ strPath.ReleaseBuffer();
+ AddSlash(strPath);
+ Texture_ShowDirectory(strPath.GetBuffer(0));
+ }
+}
+
+void CMainFrame::OnToggleRotatelock()
+{
+ g_PrefsDlg.m_bRotateLock ^= 1;
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ pMenu->CheckMenuItem(ID_TOGGLE_ROTATELOCK, MF_BYCOMMAND | (g_PrefsDlg.m_bRotateLock) ? MF_CHECKED : MF_UNCHECKED);
+ g_PrefsDlg.SavePrefs();
+ SetGridStatus();
+}
+
+
+void CMainFrame::OnCurveBevel()
+{
+ //Curve_MakeCurvedBrush (false, false, false, false, false, true, true);
+}
+
+void CMainFrame::OnCurveCylinder()
+{
+ //Curve_MakeCurvedBrush (false, false, false, true, true, true, true);
+}
+
+void CMainFrame::OnCurveEighthsphere()
+{
+ //Curve_MakeCurvedBrush (false, true, false, true, true, false, false);
+}
+
+void CMainFrame::OnCurveEndcap()
+{
+ //Curve_MakeCurvedBrush (false, false, false, false, true, true, true);
+}
+
+void CMainFrame::OnCurveHemisphere()
+{
+ //Curve_MakeCurvedBrush (false, true, false, true, true, true, true);
+}
+
+void CMainFrame::OnCurveInvertcurve()
+{
+ //Curve_Invert ();
+}
+
+void CMainFrame::OnCurveQuarter()
+{
+ //Curve_MakeCurvedBrush (false, true, false, true, true, true, false);
+}
+
+void CMainFrame::OnCurveSphere()
+{
+ //Curve_MakeCurvedBrush (false, true, true, true, true, true, true);
+}
+
+void CMainFrame::OnFileImportmap()
+{
+ CFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Map files (*.map)|*.map||", this);
+ if (dlgFile.DoModal() == IDOK)
+ {
+ Map_ImportFile(dlgFile.GetPathName().GetBuffer(0));
+ }
+}
+
+void CMainFrame::OnFileExportmap()
+{
+ CFileDialog dlgFile(FALSE, "map", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Map files (*.map)|*.map||", this);
+ if (dlgFile.DoModal() == IDOK)
+ {
+ Map_SaveSelected(dlgFile.GetPathName().GetBuffer(0));
+ }
+}
+
+void CMainFrame::OnViewShowcurves()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_CURVES ) & EXCLUDE_CURVES )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCURVES, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCURVES, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnSelectionSelectNudgedown()
+{
+ NudgeSelection(3, g_qeglobals.d_savedinfo.m_nTextureTweak);
+}
+
+void CMainFrame::OnSelectionSelectNudgeleft()
+{
+ NudgeSelection(0, g_qeglobals.d_savedinfo.m_nTextureTweak);
+}
+
+void CMainFrame::OnSelectionSelectNudgeright()
+{
+ NudgeSelection(2, g_qeglobals.d_savedinfo.m_nTextureTweak);
+}
+
+void CMainFrame::OnSelectionSelectNudgeup()
+{
+ NudgeSelection(1, g_qeglobals.d_savedinfo.m_nTextureTweak);
+}
+
+void CMainFrame::NudgeSelection(int nDirection, int nAmount)
+{
+ if (ActiveXY()->RotateMode())
+ {
+ int nAxis = 0;
+ if (ActiveXY()->GetViewType() == XY)
+ {
+ nAxis = 2;
+ }
+ else
+ if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)
+ {
+ nAxis = 1;
+ nAmount = -nAmount;
+ }
+
+ if (nDirection == 2 || nDirection == 3)
+ {
+ nAmount = -nAmount;
+ }
+
+ float fDeg = -nAmount;
+ float fAdj = nAmount;
+
+ g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;
+ CString strStatus;
+ strStatus.Format("Rotation x:: %.1f y:: %.1f z:: %.1f", g_pParentWnd->ActiveXY()->Rotation()[0], g_pParentWnd->ActiveXY()->Rotation()[1], g_pParentWnd->ActiveXY()->Rotation()[2]);
+ g_pParentWnd->SetStatusText(2, strStatus);
+ Select_RotateAxis(nAxis, fDeg, false, true);
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ if (ActiveXY()->ScaleMode())
+ {
+ if (nDirection == 0 || nDirection == 3)
+ {
+ nAmount = -nAmount;
+ }
+ vec3_t v;
+ v[0] = v[1] = v[2] = 1.0;
+ if (nAmount > 0)
+ {
+ v[0] = 1.1;
+ v[1] = 1.1;
+ v[2] = 1.1;
+ }
+ else
+ {
+ v[0] = 0.9;
+ v[1] = 0.9;
+ v[2] = 0.9;
+ }
+
+ Select_Scale((g_nScaleHow & SCALE_X) ? v[0] : 1.0,
+ (g_nScaleHow & SCALE_Y) ? v[1] : 1.0,
+ (g_nScaleHow & SCALE_Z) ? v[2] : 1.0);
+ Sys_UpdateWindows (W_ALL);
+ }
+ else
+ {
+ // 0 - left, 1 - up, 2 - right, 3 - down
+ int nDim;
+ if (nDirection == 0)
+ {
+ nDim = ActiveXY()->GetViewType() == YZ ? 1 : 0;
+ nAmount = -nAmount;
+ }
+ else if (nDirection == 1)
+ {
+ nDim = ActiveXY()->GetViewType() == XY ? 1 : 2;
+ }
+ else if (nDirection == 2)
+ {
+ nDim = ActiveXY()->GetViewType() == YZ ? 1 : 0;
+ }
+ else
+ {
+ nDim = ActiveXY()->GetViewType() == XY ? 1 : 2;
+ nAmount = -nAmount;
+ }
+ Nudge(nDim, nAmount);
+ }
+}
+
+
+BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
+{
+ return CFrameWnd::PreTranslateMessage(pMsg);
+}
+
+void CMainFrame::Nudge(int nDim, float fNudge)
+{
+ vec3_t vMove;
+ vMove[0] = vMove[1] = vMove[2] = 0;
+ vMove[nDim] = fNudge;
+ Select_Move(vMove, true);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnTexturesLoadlist()
+{
+ CDialogTextures dlg;
+ if (dlg.DoModal() == IDOK && dlg.m_nSelection >= 0)
+ {
+ Texture_ShowDirectory(dlg.m_nSelection + CMD_TEXTUREWAD);
+ }
+}
+
+void CMainFrame::OnDontselectcurve()
+{
+ g_PrefsDlg.m_bSelectCurves ^= 1;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_DONTSELECTCURVE, (g_PrefsDlg.m_bSelectCurves) ? FALSE : TRUE);
+}
+
+void CMainFrame::OnConvertcurves()
+{
+#if 0
+ Select_Deselect();
+ for (brush_t* pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+ {
+ if (pb->curveBrush)
+ {
+ for (face_t* f = pb->brush_faces ; f ; f=f->next)
+ {
+ if (f->texdef.contents & CONTENTS_LADDER)
+ {
+ f->texdef.contents &= ~CONTENTS_LADDER;
+ f->texdef.contents |= CONTENTS_NEGATIVE_CURVE;
+ }
+ }
+ }
+ }
+ Map_BuildBrushData();
+#endif
+
+}
+
+void CMainFrame::OnDynamicLighting()
+{
+ CCamWnd* pCam = new CCamWnd();
+ CRect rect(100, 100, 300, 300);
+ pCam->Create(CAMERA_WINDOW_CLASS, "", WS_OVERLAPPEDWINDOW, rect, GetDesktopWindow(), 12345);
+ pCam->ShowWindow(SW_SHOW);
+}
+
+
+void CMainFrame::OnCurveSimplepatchmesh()
+{
+ Undo_Start("make simpe patch mesh");
+ Undo_AddBrushList(&selected_brushes);
+
+ CPatchDensityDlg dlg;
+ dlg.DoModal();
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+
+void CMainFrame::OnPatchToggleBox()
+{
+ g_bPatchShowBounds ^= 1;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_SHOWBOUNDINGBOX, (g_bPatchShowBounds) ? TRUE : FALSE);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnPatchWireframe()
+{
+ g_bPatchWireFrame ^= 1;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_WIREFRAME, (g_bPatchWireFrame) ? TRUE : FALSE);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurvePatchcone()
+{
+ Undo_Start("make curve cone");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_BrushToMesh(true);
+ Sys_UpdateWindows (W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurvePatchtube()
+{
+ Undo_Start("make curve cylinder");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_BrushToMesh(false);
+ Sys_UpdateWindows (W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnPatchWeld()
+{
+ g_bPatchWeld ^= 1;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_WELD, (g_bPatchWeld) ? TRUE : FALSE);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurvePatchbevel()
+{
+ Undo_Start("make bevel");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_BrushToMesh(false, true, false);
+ Sys_UpdateWindows (W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurvePatchendcap()
+{
+ Undo_Start("make end cap");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_BrushToMesh(false, false, true);
+ Sys_UpdateWindows (W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurvePatchinvertedbevel()
+{
+ //Patch_BrushToMesh(false, true, false, true);
+ //Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnCurvePatchinvertedendcap()
+{
+ //Patch_BrushToMesh(false, false, true, true);
+ //Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnPatchDrilldown()
+{
+ g_bPatchDrillDown ^= 1;
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_DRILLDOWN, (g_bPatchDrillDown) ? TRUE : FALSE);
+ Sys_UpdateWindows(W_ALL);
+}
+
+
+void CMainFrame::OnCurveInsertcolumn()
+{
+ Undo_Start("insert colum");
+ Undo_AddBrushList(&selected_brushes);
+ //Patch_AdjustSelectedRowCols(0, 2);
+ Patch_AdjustSelected(true, true, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveInsertrow()
+{
+ Undo_Start("insert row");
+ Undo_AddBrushList(&selected_brushes);
+ //Patch_AdjustSelectedRowCols(2, 0);
+ Patch_AdjustSelected(true, false, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveDeletecolumn()
+{
+ Undo_Start("delete column");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(false, true, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveDeleterow()
+{
+ Undo_Start("delete row");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(false, false, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveInsertAddcolumn()
+{
+ Undo_Start("add (2) columns");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(true, true, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveInsertAddrow()
+{
+ Undo_Start("add (2) rows");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(true, false, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveInsertInsertcolumn()
+{
+ Undo_Start("insert (2) columns");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(true, true, false);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveInsertInsertrow()
+{
+ Undo_Start("insert (2) rows");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(true, false, false);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveNegative()
+{
+ Patch_ToggleInverted();
+ //Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurveNegativeTextureX()
+{
+ Patch_InvertTexture(false);
+ //Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurveNegativeTextureY()
+{
+ Patch_InvertTexture(true);
+ //Sys_UpdateWindows(W_ALL);
+}
+
+
+void CMainFrame::OnCurveDeleteFirstcolumn()
+{
+ Undo_Start("delete first (2) columns");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(false, true, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveDeleteFirstrow()
+{
+ Undo_Start("delete first (2) rows");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(false, false, true);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveDeleteLastcolumn()
+{
+ Undo_Start("delete last (2) columns");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(false, true, false);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveDeleteLastrow()
+{
+ Undo_Start("delete last (2) rows");
+ Undo_AddBrushList(&selected_brushes);
+ Patch_AdjustSelected(false, false, false);
+ Sys_UpdateWindows(W_ALL);
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnPatchBend()
+{
+ Patch_BendToggle();
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_BEND, (g_bPatchBendMode) ? TRUE : FALSE);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnPatchInsdel()
+{
+ Patch_InsDelToggle();
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_INSDEL, (g_bPatchInsertMode) ? TRUE : FALSE);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnPatchEnter()
+{
+
+}
+
+void CMainFrame::OnPatchTab()
+{
+ if (g_bPatchBendMode)
+ Patch_BendHandleTAB();
+ else if (g_bPatchInsertMode)
+ Patch_InsDelHandleTAB();
+ else
+ {
+ // check to see if the selected brush is part of a func group
+ // if it is, deselect everything and reselect the next brush
+ // in the group
+ brush_t *b = selected_brushes.next;
+ entity_t * e;
+ if (b != &selected_brushes)
+ {
+ if (strcmpi(b->owner->eclass->name, "worldspawn") != 0)
+ {
+ e = b->owner;
+ Select_Deselect();
+ for (brush_t * b2 = e->brushes.onext ; b2 != &e->brushes ; b2 = b2->onext)
+ {
+ if (b == b2)
+ {
+ b2 = b2->onext;
+ break;
+ }
+ }
+ if (b2 == &e->brushes)
+ b2 = b2->onext;
+
+ Select_Brush(b2, false);
+ Sys_UpdateWindows(W_ALL);
+ }
+ }
+ }
+}
+
+void CMainFrame::UpdatePatchToolbarButtons()
+{
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_BEND, (g_bPatchBendMode) ? TRUE : FALSE);
+ m_wndToolBar.GetToolBarCtrl().CheckButton(ID_PATCH_INSDEL, (g_bPatchInsertMode) ? TRUE : FALSE);
+}
+
+void CMainFrame::OnCurvePatchdensetube()
+{
+ Undo_Start("dense cylinder");
+ Undo_AddBrushList(&selected_brushes);
+
+ Patch_BrushToMesh(false);
+ OnCurveInsertAddrow();
+ OnCurveInsertInsertrow();
+ Sys_UpdateWindows (W_ALL);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurvePatchverydensetube()
+{
+ Undo_Start("very dense cylinder");
+ Undo_AddBrushList(&selected_brushes);
+
+ Patch_BrushToMesh(false);
+ OnCurveInsertAddrow();
+ OnCurveInsertInsertrow();
+ OnCurveInsertAddrow();
+ OnCurveInsertInsertrow();
+ Sys_UpdateWindows (W_ALL);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveCap()
+{
+ Patch_CapCurrent();
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+void CMainFrame::OnCurveCapInvertedbevel()
+{
+ Patch_CapCurrent(true);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnCurveCapInvertedendcap()
+{
+ Patch_CapCurrent(false, true);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnCurveRedisperseCols()
+{
+ Patch_DisperseColumns();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnCurveRedisperseRows()
+{
+ Patch_DisperseRows();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnPatchNaturalize()
+{
+ Patch_NaturalizeSelected();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnSnapToGrid()
+{
+ Select_SnapToGrid();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnCurvePatchsquare()
+{
+ Undo_Start("square cylinder");
+ Undo_AddBrushList(&selected_brushes);
+
+ Patch_BrushToMesh(false, false, false, true);
+ Sys_UpdateWindows (W_ALL);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnTerrainCreateFromBrush()
+{
+ Terrain_BrushToMesh();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::CheckTextureScale(int id)
+{
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ {
+ pMenu->CheckMenuItem(ID_TEXTURES_TEXTUREWINDOWSCALE_10, MF_BYCOMMAND | MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_TEXTURES_TEXTUREWINDOWSCALE_25, MF_BYCOMMAND | MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_TEXTURES_TEXTUREWINDOWSCALE_50, MF_BYCOMMAND | MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_TEXTURES_TEXTUREWINDOWSCALE_100, MF_BYCOMMAND | MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_TEXTURES_TEXTUREWINDOWSCALE_200, MF_BYCOMMAND | MF_UNCHECKED);
+ pMenu->CheckMenuItem(id, MF_BYCOMMAND | MF_CHECKED);
+ }
+ g_PrefsDlg.SavePrefs();
+ Texture_ResetPosition();
+ Sys_UpdateWindows(W_TEXTURE);
+}
+
+void CMainFrame::OnTexturesTexturewindowscale10()
+{
+ g_PrefsDlg.m_nTextureScale = 10;
+ CheckTextureScale(ID_TEXTURES_TEXTUREWINDOWSCALE_10);
+}
+
+void CMainFrame::OnTexturesTexturewindowscale100()
+{
+ g_PrefsDlg.m_nTextureScale = 100;
+ CheckTextureScale(ID_TEXTURES_TEXTUREWINDOWSCALE_100);
+}
+
+void CMainFrame::OnTexturesTexturewindowscale200()
+{
+ g_PrefsDlg.m_nTextureScale = 200;
+ CheckTextureScale(ID_TEXTURES_TEXTUREWINDOWSCALE_200);
+}
+
+void CMainFrame::OnTexturesTexturewindowscale25()
+{
+ g_PrefsDlg.m_nTextureScale = 25;
+ CheckTextureScale(ID_TEXTURES_TEXTUREWINDOWSCALE_25);
+}
+
+void CMainFrame::OnTexturesTexturewindowscale50()
+{
+ g_PrefsDlg.m_nTextureScale = 50;
+ CheckTextureScale(ID_TEXTURES_TEXTUREWINDOWSCALE_50);
+}
+
+
+
+void CMainFrame::OnTexturesFlush()
+{
+ Texture_Flush();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurveOverlayClear()
+{
+ Patch_ClearOverlays();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurveOverlaySet()
+{
+ Patch_SetOverlays();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnCurveThicken()
+{
+ Undo_Start("curve thicken");
+ Undo_AddBrushList(&selected_brushes);
+
+ CDialogThick dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ Patch_Thicken(dlg.m_nAmount, dlg.m_bSeams);
+ Sys_UpdateWindows(W_ALL);
+ }
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveCyclecap()
+{
+ Patch_NaturalizeSelected(true, true);
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnCurveMatrixTranspose()
+{
+ Patch_Transpose();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnTexturesReloadshaders()
+{
+ CWaitCursor wait;
+ ReloadShaders();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::SetEntityCheck()
+{
+ CMenu* pMenu = GetMenu();
+ if (pMenu)
+ {
+ pMenu->CheckMenuItem(ID_VIEW_ENTITIESAS_BOUNDINGBOX, MF_BYCOMMAND | (g_PrefsDlg.m_nEntityShowState == ENTITY_BOX) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_VIEW_ENTITIESAS_WIREFRAME, MF_BYCOMMAND | (g_PrefsDlg.m_nEntityShowState == ENTITY_WIRE) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME, MF_BYCOMMAND | (g_PrefsDlg.m_nEntityShowState == ENTITY_SELECTED) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_VIEW_ENTITIESAS_SELECTEDSKINNED, MF_BYCOMMAND | (g_PrefsDlg.m_nEntityShowState == ENTITY_SELECTED_SKIN) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_VIEW_ENTITIESAS_SKINNED, MF_BYCOMMAND | (g_PrefsDlg.m_nEntityShowState == ENTITY_SKINNED) ? MF_CHECKED : MF_UNCHECKED);
+ pMenu->CheckMenuItem(ID_VIEW_ENTITIESAS_SKINNEDANDBOXED, MF_BYCOMMAND | (g_PrefsDlg.m_nEntityShowState == ENTITY_SKINNED_BOXED) ? MF_CHECKED : MF_UNCHECKED);
+ }
+}
+
+
+void CMainFrame::OnShowEntities()
+{
+ HandlePopup(this, IDR_POPUP_ENTITY);
+}
+
+void CMainFrame::OnViewEntitiesasBoundingbox()
+{
+ g_PrefsDlg.m_nEntityShowState = ENTITY_BOX;
+ SetEntityCheck();
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnViewEntitiesasSelectedskinned()
+{
+ g_PrefsDlg.m_nEntityShowState = ENTITY_SELECTED_SKIN;
+ SetEntityCheck();
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnViewEntitiesasSelectedwireframe()
+{
+ g_PrefsDlg.m_nEntityShowState = ENTITY_SELECTED;
+ SetEntityCheck();
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnViewEntitiesasSkinned()
+{
+ g_PrefsDlg.m_nEntityShowState = ENTITY_SKINNED;
+ SetEntityCheck();
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnViewEntitiesasSkinnedandboxed()
+{
+ g_PrefsDlg.m_nEntityShowState = ENTITY_SKINNED_BOXED;
+ SetEntityCheck();
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnViewEntitiesasWireframe()
+{
+ g_PrefsDlg.m_nEntityShowState = ENTITY_WIRE;
+ SetEntityCheck();
+ g_PrefsDlg.SavePrefs();
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+
+
+
+
+
+void CMainFrame::OnPluginsRefresh()
+{
+ CleanPlugInMenu();
+ CString str(g_strAppPath);
+ AddSlash(str);
+ str += "plugins\\";
+ m_PlugInMgr.Init(str);
+}
+
+void CMainFrame::CleanPlugInMenu()
+{
+ m_nNextPlugInID = ID_PLUGIN_START;
+ CMenu* pMenu = GetMenu();
+ //--pMenu->RemoveMenu(MENU_PLUGIN, MF_BYPOSITION);
+ //--pMenu->InsertMenu(MENU_PLUGIN, MF_BYPOSITION, 0, "Plugins");
+ //--DrawMenuBar();
+ CMenu* pSub = pMenu->GetSubMenu(MENU_PLUGIN);
+ if (pSub)
+ {
+ int n = pSub->GetMenuItemCount();
+ for (int i = n; i > 1 ; i--)
+ {
+ pSub->RemoveMenu(i, MF_BYPOSITION);
+ }
+ }
+}
+
+void CMainFrame::AddPlugInMenuItem(CPlugIn* pPlugIn)
+{
+ const char *menuText; //PGM
+ CMenu* pMenu = GetMenu();
+ CMenu* pSub = pMenu->GetSubMenu(MENU_PLUGIN);
+ if (pSub)
+ {
+ CMenu* pChild = new CMenu();
+ pChild->CreateMenu();
+ int nCount = pPlugIn->getCommandCount();
+ if (nCount > 0)
+ {
+ while (nCount > 0)
+ {
+ menuText = pPlugIn->getCommand(--nCount);
+ if (menuText != NULL && strlen(menuText) > 0)
+ {
+ if(!strcmp(menuText, "-"))
+ pChild->AppendMenu(MF_SEPARATOR, NULL);
+ else
+ pChild->AppendMenu(MF_STRING, m_nNextPlugInID, menuText);
+ pPlugIn->addMenuID(m_nNextPlugInID++);
+ }
+ }
+ pSub->AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), pPlugIn->getMenuName());
+ }
+ }
+}
+
+void CMainFrame::OnPlugIn(unsigned int nID)
+{
+ CMenu* pMenu = GetMenu();
+ CString str;
+ pMenu->GetMenuString(nID, str, MF_BYCOMMAND);
+ m_PlugInMgr.Dispatch(nID, str);
+}
+
+void CMainFrame::OnViewShowhint()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_HINT ) & EXCLUDE_HINT )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnTexturesShowall()
+{
+ Texture_ShowAll();
+}
+
+void CMainFrame::OnPatchInspector()
+{
+ DoPatchInspector();
+}
+
+void CMainFrame::OnViewOpengllighting()
+{
+ g_PrefsDlg.m_bGLLighting ^= 1;
+ g_PrefsDlg.SavePrefs();
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_OPENGLLIGHTING, MF_BYCOMMAND | (g_PrefsDlg.m_bGLLighting) ? MF_CHECKED : MF_UNCHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnSelectAll()
+{
+ Select_AllOfType();
+}
+
+void CMainFrame::OnViewShowcaulk()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_CAULK ) & EXCLUDE_CAULK )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+
+}
+
+void CMainFrame::OnCurveFreeze()
+{
+ Patch_Freeze();
+}
+
+void CMainFrame::OnCurveUnFreeze()
+{
+ Patch_UnFreeze(false);
+}
+
+void CMainFrame::OnCurveUnFreezeAll()
+{
+ Patch_UnFreeze(true);
+}
+
+void CMainFrame::OnSelectReselect()
+{
+ Select_Reselect();
+}
+
+void CMainFrame::OnViewShowangles()
+{
+ if ( ( g_qeglobals.d_savedinfo.exclude ^= EXCLUDE_ANGLES ) & EXCLUDE_ANGLES )
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWANGLES, MF_BYCOMMAND | MF_UNCHECKED );
+ else
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_VIEW_SHOWANGLES, MF_BYCOMMAND | MF_CHECKED );
+ Sys_UpdateWindows (W_XY|W_CAMERA);
+}
+
+void CMainFrame::OnEditSaveprefab()
+{
+ CFileDialog dlgFile(FALSE, "pfb", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Prefab files (*.pfb)|*.pfb||", this);
+ char CurPath[1024];
+ if (g_PrefsDlg.m_strPrefabPath.GetLength() > 0)
+ {
+ strcpy(CurPath, g_PrefsDlg.m_strPrefabPath);
+ }
+ else
+ {
+ ::GetCurrentDirectory(1024, CurPath);
+ }
+ dlgFile.m_ofn.lpstrInitialDir = CurPath;
+ if (dlgFile.DoModal() == IDOK)
+ {
+ Map_SaveSelected(dlgFile.GetPathName().GetBuffer(0));
+ }
+}
+
+
+void CMainFrame::OnEditLoadprefab()
+{
+ CFileDialog dlgFile(TRUE, "pfb", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Prefab files (*.pfb)|*.pfb||", this);
+ char CurPath[1024];
+ if (g_PrefsDlg.m_strPrefabPath.GetLength() > 0)
+ {
+ strcpy(CurPath, g_PrefsDlg.m_strPrefabPath);
+ }
+ else
+ {
+ ::GetCurrentDirectory(1024, CurPath);
+ }
+ dlgFile.m_ofn.lpstrInitialDir = CurPath;
+ if (dlgFile.DoModal() == IDOK)
+ {
+ Map_ImportFile(dlgFile.GetPathName().GetBuffer(0));
+ }
+}
+
+void CMainFrame::OnCurveMoreendcapsbevelsSquarebevel()
+{
+ Undo_Start("square bevel");
+ Undo_AddBrushList(&selected_brushes);
+
+ Patch_BrushToMesh(false, true, false, true);
+ Sys_UpdateWindows (W_ALL);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnCurveMoreendcapsbevelsSquareendcap()
+{
+ Undo_Start("square endcap");
+ Undo_AddBrushList(&selected_brushes);
+
+ Patch_BrushToMesh(false, false, true, true);
+ Sys_UpdateWindows (W_ALL);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+void CMainFrame::OnBrushPrimitivesSphere()
+{
+ Undo_Start("make sphere");
+ Undo_AddBrushList(&selected_brushes);
+
+ DoSides(false, true);
+
+ Undo_EndBrushList(&selected_brushes);
+ Undo_End();
+}
+
+extern bool g_bCrossHairs;
+void CMainFrame::OnViewCrosshair()
+{
+ g_bCrossHairs ^= 1;
+ Sys_UpdateWindows (W_XY);
+}
+
+void CMainFrame::OnViewHideshowHideselected()
+{
+ Select_Hide();
+ Select_Deselect();
+}
+
+void CMainFrame::OnViewHideshowShowhidden()
+{
+ Select_ShowAllHidden();
+}
+
+void CMainFrame::OnTexturesShadersShow()
+{
+ g_PrefsDlg.m_bShowShaders ^= 1;
+ CheckMenuItem ( ::GetMenu(g_qeglobals.d_hwndMain), ID_TEXTURES_SHADERS_SHOW, MF_BYCOMMAND | ((g_PrefsDlg.m_bShowShaders) ? MF_CHECKED : MF_UNCHECKED ));
+ Sys_UpdateWindows(W_TEXTURE);
+
+}
+
+void CMainFrame::OnTexturesFlushUnused()
+{
+ Texture_FlushUnused();
+ Sys_UpdateWindows(W_TEXTURE);
+}
+
+void CMainFrame::OnSelectionInvert()
+{
+ Select_Invert();
+ Sys_UpdateWindows(W_XY | W_Z | W_CAMERA);
+}
+
+
+void CMainFrame::OnViewGroups()
+{
+ if (m_nCurrentStyle == 0 || m_nCurrentStyle == 3)
+ {
+ if (::IsWindowVisible(g_qeglobals.d_hwndEntity) && inspector_mode == W_GROUP)
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+ else
+ {
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ SetInspectorMode(W_GROUP);
+ }
+ }
+ else
+ {
+ if (inspector_mode == W_GROUP && m_nCurrentStyle != QR_QE4)
+ {
+ if (::IsWindowVisible(g_qeglobals.d_hwndEntity))
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_HIDE);
+ else
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ }
+ else
+ {
+ ::ShowWindow(g_qeglobals.d_hwndEntity, SW_NORMAL);
+ SetInspectorMode(W_GROUP);
+ }
+ }
+}
+
+void CMainFrame::OnDropGroupAddtoWorld()
+{
+ Select_AddToGroup("World");
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnDropGroupName()
+{
+ CNameDlg dlg("Name Selection", this);
+ if (dlg.DoModal() == IDOK)
+ {
+ Select_Name(dlg.m_strName);
+ Sys_UpdateWindows (W_ALL);
+ }
+}
+
+void CMainFrame::OnDropGroupNewgroup()
+{
+
+}
+
+void CMainFrame::OnDropGroupRemove()
+{
+ Select_AddToGroup("World");
+ Sys_UpdateWindows (W_ALL);
+}
+
+void CMainFrame::OnSplinesMode()
+{
+ g_qeglobals.d_select_mode = sel_addpoint;
+ g_qeglobals.selectObject = g_splineList->getPositionObj();
+ g_splineList->clear();
+ g_splineList->startEdit(true);
+ showCameraInspector();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CMainFrame::OnSplinesLoad()
+{
+ g_splineList->load("maps/test.camera");
+ g_splineList->buildCamera();
+}
+
+void CMainFrame::OnSplinesSave()
+{
+ g_splineList->save("maps/test.camera");
+}
+
+void CMainFrame::OnSplinesEdit()
+{
+ showCameraInspector();
+ Sys_UpdateWindows(W_ALL);
+}
+
+extern void testCamSpeed();
+void CMainFrame::OnSplineTest()
+{
+ long start = GetTickCount();
+ g_splineList->startCamera(start);
+ float cycle = g_splineList->getTotalTime();
+ long msecs = cycle * 1000;
+ long current = start;
+ vec3_t lookat;
+ VectorClear(lookat);
+ vec3_t dir;
+ while (current < start + msecs) {
+ float fov;
+ g_splineList->getCameraInfo(current, &g_pParentWnd->GetCamera()->Camera().origin[0], &dir[0], &fov);
+ g_pParentWnd->GetCamera()->Camera().angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
+ g_pParentWnd->GetCamera()->Camera().angles[0] = asin (dir[2])*180/3.14159;
+ g_pParentWnd->UpdateWindows(W_XY | W_CAMERA);
+ current = GetTickCount();
+ }
+ g_splineList->setRunning(false);
+}
+
+void CMainFrame::OnSplinesTarget()
+{
+}
+
+void CMainFrame::OnSplinesTargetPoints()
+{
+}
+
+void CMainFrame::OnSplinesCameraPoints()
+{
+}
+
+void CMainFrame::OnPopupNewcameraInterpolated()
+{
+ g_qeglobals.d_select_mode = sel_addpoint;
+ g_qeglobals.selectObject = g_splineList->startNewCamera(idCameraPosition::INTERPOLATED);
+ OnSplinesEdit();
+}
+
+void CMainFrame::OnPopupNewcameraSpline()
+{
+ g_qeglobals.d_select_mode = sel_addpoint;
+ g_qeglobals.selectObject = g_splineList->startNewCamera(idCameraPosition::SPLINE);
+ OnSplinesEdit();
+}
+
+void CMainFrame::OnPopupNewcameraFixed()
+{
+ g_qeglobals.d_select_mode = sel_addpoint;
+ g_qeglobals.selectObject = g_splineList->startNewCamera(idCameraPosition::FIXED);
+ OnSplinesEdit();
+}
diff --git a/q3radiant/MainFrm.h b/q3radiant/MainFrm.h
new file mode 100755
index 0000000..35e46a8
--- /dev/null
+++ b/q3radiant/MainFrm.h
@@ -0,0 +1,504 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// MainFrm.h : interface of the CMainFrame class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_MAINFRM_H__330BBF0A_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+#define AFX_MAINFRM_H__330BBF0A_731C_11D1_B539_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "LstToolBar.h"
+#include "XYWnd.h"
+#include "TexWnd.h"
+#include "ZWnd.h"
+#include "CamWnd.h"
+#include "RADEditWnd.h"
+#include "TextureBar.h"
+#include "PlugInManager.h"
+#include "PlugIn.h"
+#include "groupdlg.h"
+
+
+const int RAD_SHIFT = 0x01;
+const int RAD_ALT = 0x02;
+const int RAD_CONTROL = 0x04;
+const int RAD_PRESS = 0x08;
+
+struct SCommandInfo
+{
+ char* m_strCommand;
+ unsigned int m_nKey;
+ unsigned int m_nModifiers;
+ unsigned int m_nCommand;
+};
+
+struct SKeyInfo
+{
+ char* m_strName;
+ unsigned int m_nVKKey;
+};
+
+
+
+
+class CMainFrame : public CFrameWnd
+{
+ DECLARE_DYNAMIC(CMainFrame)
+public:
+ CMainFrame();
+ void HandleKey(UINT nChar, UINT nRepCnt, UINT nFlags, bool bDown = true)
+ {
+ if (bDown)
+ OnKeyDown(nChar, nRepCnt, nFlags);
+ else
+ OnKeyUp(nChar, nRepCnt, nFlags);
+ };
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CMainFrame)
+ public:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ protected:
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
+ virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ void UpdatePatchToolbarButtons();
+ void NudgeSelection(int nDirection, int nAmount);
+ void UpdateTextureBar();
+ void SetButtonMenuStates();
+ void SetTexValStatus();
+ void SetGridStatus();
+ void RoutineProcessing();
+ CXYWnd* ActiveXY();
+ void UpdateWindows(int nBits);
+ void SetStatusText(int nPane, const char* pText);
+ void UpdateStatusText();
+ void SetWindowStyle(int nStyle);
+ virtual ~CMainFrame();
+ CXYWnd* GetXYWnd() {return m_pXYWnd;};
+ CXYWnd* GetXZWnd() {return m_pXZWnd;};
+ CXYWnd* GetYZWnd() {return m_pYZWnd;};
+ CCamWnd* GetCamera() {return m_pCamWnd;};
+ CTexWnd* GetTexWnd() {return m_pTexWnd;};
+ void SetActiveXY(CXYWnd* p)
+ {
+ if (m_pActiveXY)
+ m_pActiveXY->SetActive(false);
+
+ m_pActiveXY = p;
+
+ if (m_pActiveXY)
+ m_pActiveXY->SetActive(true);
+
+ };
+ int CurrentStyle() { return m_nCurrentStyle; };
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected: // control bar embedded members
+ CStatusBar m_wndStatusBar;
+ CLstToolBar m_wndToolBar;
+ CLstToolBar m_wndScaleBar;
+ CDialogBar m_wndHelpBar;
+ CTextureBar m_wndTextureBar;
+ CSplitterWnd m_wndSplit;
+ CSplitterWnd m_wndSplit2;
+ CSplitterWnd m_wndSplit3;
+ CXYWnd* m_pXYWnd;
+ CXYWnd* m_pYZWnd;
+ CXYWnd* m_pXZWnd;
+ CCamWnd* m_pCamWnd;
+ CTexWnd* m_pTexWnd;
+ CZWnd* m_pZWnd;
+ CRADEditWnd* m_pEditWnd;
+ int m_nCurrentStyle;
+ CString m_strStatus[15];
+ CXYWnd* m_pActiveXY;
+ bool m_bCamPreview;
+ CPlugInManager m_PlugInMgr;
+ int m_nNextPlugInID;
+
+// Generated message map functions
+protected:
+ bool m_bDoLoop;
+ bool m_bSplittersOK;
+ void CreateQEChildren();
+ void LoadCommandMap();
+ void ShowMenuItemKeyBindings(CMenu *pMenu);
+ void SetEntityCheck();
+ afx_msg LRESULT OnBSPStatus(UINT wParam, long lParam);
+ afx_msg LRESULT OnBSPDone(UINT wParam, long lParam);
+public:
+ void Nudge(int nDim, float fNudge);
+
+ CPlugInManager &GetPlugInMgr() {return m_PlugInMgr;};
+ void AddPlugInMenuItem(CPlugIn* pPlugIn);
+ void CleanPlugInMenu();
+
+ // these are public so i can easily reflect messages
+ // from child windows..
+ //{{AFX_MSG(CMainFrame)
+ afx_msg void OnParentNotify(UINT message, LPARAM lParam);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnDestroy();
+ afx_msg void OnClose();
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void ToggleCamera();
+ afx_msg void OnFileClose();
+ afx_msg void OnFileExit();
+ afx_msg void OnFileLoadproject();
+ afx_msg void OnFileNew();
+ afx_msg void OnFileOpen();
+ afx_msg void OnFilePointfile();
+ afx_msg void OnFilePrint();
+ afx_msg void OnFilePrintPreview();
+ afx_msg void OnFileSave();
+ afx_msg void OnFileSaveas();
+ afx_msg void OnView100();
+ afx_msg void OnViewCenter();
+ afx_msg void OnViewConsole();
+ afx_msg void OnViewDownfloor();
+ afx_msg void OnViewEntity();
+ afx_msg void OnViewFront();
+ afx_msg void OnViewShowblocks();
+ afx_msg void OnViewShowclip();
+ afx_msg void OnViewShowcoordinates();
+ afx_msg void OnViewShowdetail();
+ afx_msg void OnViewShowent();
+ afx_msg void OnViewShowlights();
+ afx_msg void OnViewShownames();
+ afx_msg void OnViewShowpath();
+ afx_msg void OnViewShowwater();
+ afx_msg void OnViewShowworld();
+ afx_msg void OnViewTexture();
+ afx_msg void OnViewUpfloor();
+ afx_msg void OnViewXy();
+ afx_msg void OnViewZ100();
+ afx_msg void OnViewZoomin();
+ afx_msg void OnViewZoomout();
+ afx_msg void OnViewZzoomin();
+ afx_msg void OnViewZzoomout();
+ afx_msg void OnViewSide();
+ afx_msg void OnTexturesShowinuse();
+ afx_msg void OnTexturesInspector();
+ afx_msg void OnMiscBenchmark();
+ afx_msg void OnMiscFindbrush();
+ afx_msg void OnMiscGamma();
+ afx_msg void OnMiscNextleakspot();
+ afx_msg void OnMiscPreviousleakspot();
+ afx_msg void OnMiscPrintxy();
+ afx_msg void OnMiscSelectentitycolor();
+ afx_msg void OnTexturebk();
+ afx_msg void OnColorsMajor();
+ afx_msg void OnColorsMinor();
+ afx_msg void OnColorsXybk();
+ afx_msg void OnBrush3sided();
+ afx_msg void OnBrush4sided();
+ afx_msg void OnBrush5sided();
+ afx_msg void OnBrush6sided();
+ afx_msg void OnBrush7sided();
+ afx_msg void OnBrush8sided();
+ afx_msg void OnBrush9sided();
+ afx_msg void OnBrushArbitrarysided();
+ afx_msg void OnBrushFlipx();
+ afx_msg void OnBrushFlipy();
+ afx_msg void OnBrushFlipz();
+ afx_msg void OnBrushRotatex();
+ afx_msg void OnBrushRotatey();
+ afx_msg void OnBrushRotatez();
+ afx_msg void OnRegionOff();
+ afx_msg void OnRegionSetbrush();
+ afx_msg void OnRegionSetselection();
+ afx_msg void OnRegionSettallbrush();
+ afx_msg void OnRegionSetxy();
+ afx_msg void OnSelectionArbitraryrotation();
+ afx_msg void OnSelectionClone();
+ afx_msg void OnSelectionConnect();
+ afx_msg void OnSelectionCsgsubtract();
+ afx_msg void OnSelectionCsgmerge();
+ afx_msg void OnSelectionNoOutline();
+ afx_msg void OnSelectionDelete();
+ afx_msg void OnSelectionDeselect();
+ afx_msg void OnSelectionDragedges();
+ afx_msg void OnSelectionDragvertecies();
+ afx_msg void OnRaiseLowerTerrain();
+ afx_msg void OnSelectionMakeDetail();
+ afx_msg void OnSelectionMakeStructural();
+ afx_msg void OnSelectionMakehollow();
+ afx_msg void OnSelectionSelectcompletetall();
+ afx_msg void OnSelectionSelectinside();
+ afx_msg void OnSelectionSelectpartialtall();
+ afx_msg void OnSelectionSelecttouching();
+ afx_msg void OnSelectionUngroupentity();
+ afx_msg void OnTexturesPopup();
+ afx_msg void OnSplinesPopup();
+ afx_msg void OnPopupSelection();
+ afx_msg void OnViewChange();
+ afx_msg void OnViewCameraupdate();
+ afx_msg void OnUpdateViewCameraupdate(CCmdUI* pCmdUI);
+ afx_msg void OnSizing(UINT fwSide, LPRECT pRect);
+ afx_msg void OnHelpAbout();
+ afx_msg void OnViewClipper();
+ afx_msg void OnCameraAngledown();
+ afx_msg void OnCameraAngleup();
+ afx_msg void OnCameraBack();
+ afx_msg void OnCameraDown();
+ afx_msg void OnCameraForward();
+ afx_msg void OnCameraLeft();
+ afx_msg void OnCameraRight();
+ afx_msg void OnCameraStrafeleft();
+ afx_msg void OnCameraStraferight();
+ afx_msg void OnCameraUp();
+ afx_msg void OnGridToggle();
+ afx_msg void OnPrefs();
+ afx_msg void OnTogglecamera();
+ afx_msg void OnToggleconsole();
+ afx_msg void OnToggleview();
+ afx_msg void OnTogglez();
+ afx_msg void OnToggleLock();
+ afx_msg void OnEditMapinfo();
+ afx_msg void OnEditEntityinfo();
+ afx_msg void OnBrushScripts();
+ afx_msg void OnViewNextview();
+ afx_msg void OnHelpCommandlist();
+ afx_msg void OnFileNewproject();
+ afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnFlipClip();
+ afx_msg void OnClipSelected();
+ afx_msg void OnSplitSelected();
+ afx_msg void OnToggleviewXz();
+ afx_msg void OnToggleviewYz();
+ afx_msg void OnColorsBrush();
+ afx_msg void OnColorsClipper();
+ afx_msg void OnColorsGridtext();
+ afx_msg void OnColorsSelectedbrush();
+ afx_msg void OnColorsGridblock();
+ afx_msg void OnColorsViewname();
+ afx_msg void OnColorSetoriginal();
+ afx_msg void OnColorSetqer();
+ afx_msg void OnColorSetblack();
+ afx_msg void OnSnaptogrid();
+ afx_msg void OnSelectScale();
+ afx_msg void OnSelectMouserotate();
+ afx_msg void OnEditCopybrush();
+ afx_msg void OnEditPastebrush();
+ afx_msg void OnEditUndo();
+ afx_msg void OnEditRedo();
+ afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI);
+ afx_msg void OnUpdateEditRedo(CCmdUI* pCmdUI);
+ afx_msg void OnSelectionInvert();
+ afx_msg void OnSelectionTextureDec();
+ afx_msg void OnSelectionTextureFit();
+ afx_msg void OnSelectionTextureInc();
+ afx_msg void OnSelectionTextureRotateclock();
+ afx_msg void OnSelectionTextureRotatecounter();
+ afx_msg void OnSelectionTextureScaledown();
+ afx_msg void OnSelectionTextureScaleup();
+ afx_msg void OnSelectionTextureShiftdown();
+ afx_msg void OnSelectionTextureShiftleft();
+ afx_msg void OnSelectionTextureShiftright();
+ afx_msg void OnSelectionTextureShiftup();
+ afx_msg void OnGridNext();
+ afx_msg void OnGridPrev();
+ afx_msg void OnSelectionTextureScaleLeft();
+ afx_msg void OnSelectionTextureScaleRight();
+ afx_msg void OnTextureReplaceall();
+ afx_msg void OnScalelockx();
+ afx_msg void OnScalelocky();
+ afx_msg void OnScalelockz();
+ afx_msg void OnSelectMousescale();
+ afx_msg void OnViewCubicclipping();
+ afx_msg void OnFileImport();
+ afx_msg void OnFileProjectsettings();
+ afx_msg void OnUpdateFileImport(CCmdUI* pCmdUI);
+ afx_msg void OnViewCubein();
+ afx_msg void OnViewCubeout();
+ afx_msg void OnFileSaveregion();
+ afx_msg void OnUpdateFileSaveregion(CCmdUI* pCmdUI);
+ afx_msg void OnSelectionMovedown();
+ afx_msg void OnSelectionMoveup();
+ afx_msg void OnToolbarMain();
+ afx_msg void OnToolbarTexture();
+ afx_msg void OnSelectionPrint();
+ afx_msg void OnSelectionTogglesizepaint();
+ afx_msg void OnBrushMakecone();
+ afx_msg void OnTexturesLoad();
+ afx_msg void OnToggleRotatelock();
+ afx_msg void OnCurveBevel();
+ afx_msg void OnCurveCylinder();
+ afx_msg void OnCurveEighthsphere();
+ afx_msg void OnCurveEndcap();
+ afx_msg void OnCurveHemisphere();
+ afx_msg void OnCurveInvertcurve();
+ afx_msg void OnCurveQuarter();
+ afx_msg void OnCurveSphere();
+ afx_msg void OnFileImportmap();
+ afx_msg void OnFileExportmap();
+ afx_msg void OnEditLoadprefab();
+ afx_msg void OnViewShowcurves();
+ afx_msg void OnSelectionSelectNudgedown();
+ afx_msg void OnSelectionSelectNudgeleft();
+ afx_msg void OnSelectionSelectNudgeright();
+ afx_msg void OnSelectionSelectNudgeup();
+ afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnTexturesLoadlist();
+ afx_msg void OnDontselectcurve();
+ afx_msg void OnConvertcurves();
+ afx_msg void OnDynamicLighting();
+ afx_msg void OnCurveSimplepatchmesh();
+ afx_msg void OnPatchToggleBox();
+ afx_msg void OnPatchWireframe();
+ afx_msg void OnCurvePatchcone();
+ afx_msg void OnCurvePatchtube();
+ afx_msg void OnPatchWeld();
+ afx_msg void OnCurvePatchbevel();
+ afx_msg void OnCurvePatchendcap();
+ afx_msg void OnCurvePatchinvertedbevel();
+ afx_msg void OnCurvePatchinvertedendcap();
+ afx_msg void OnPatchDrilldown();
+ afx_msg void OnCurveInsertcolumn();
+ afx_msg void OnCurveInsertrow();
+ afx_msg void OnCurveDeletecolumn();
+ afx_msg void OnCurveDeleterow();
+ afx_msg void OnCurveInsertAddcolumn();
+ afx_msg void OnCurveInsertAddrow();
+ afx_msg void OnCurveInsertInsertcolumn();
+ afx_msg void OnCurveInsertInsertrow();
+ afx_msg void OnCurveNegative();
+ afx_msg void OnCurveNegativeTextureX();
+ afx_msg void OnCurveNegativeTextureY();
+ afx_msg void OnCurveDeleteFirstcolumn();
+ afx_msg void OnCurveDeleteFirstrow();
+ afx_msg void OnCurveDeleteLastcolumn();
+ afx_msg void OnCurveDeleteLastrow();
+ afx_msg void OnPatchBend();
+ afx_msg void OnPatchInsdel();
+ afx_msg void OnPatchEnter();
+ afx_msg void OnPatchTab();
+ afx_msg void OnCurvePatchdensetube();
+ afx_msg void OnCurvePatchverydensetube();
+ afx_msg void OnCurveCap();
+ afx_msg void OnCurveCapInvertedbevel();
+ afx_msg void OnCurveCapInvertedendcap();
+ afx_msg void OnCurveRedisperseCols();
+ afx_msg void OnCurveRedisperseRows();
+ afx_msg void OnPatchNaturalize();
+ afx_msg void OnSnapToGrid();
+ afx_msg void OnCurvePatchsquare();
+ afx_msg void OnTerrainCreateFromBrush();
+ afx_msg void OnTexturesTexturewindowscale10();
+ afx_msg void OnTexturesTexturewindowscale100();
+ afx_msg void OnTexturesTexturewindowscale200();
+ afx_msg void OnTexturesTexturewindowscale25();
+ afx_msg void OnTexturesTexturewindowscale50();
+ afx_msg void OnTexturesFlush();
+ afx_msg void OnCurveOverlayClear();
+ afx_msg void OnCurveOverlaySet();
+ afx_msg void OnCurveThicken();
+ afx_msg void OnCurveCyclecap();
+ afx_msg void OnCurveMatrixTranspose();
+ afx_msg void OnTexturesReloadshaders();
+ afx_msg void OnShowEntities();
+ afx_msg void OnViewEntitiesasBoundingbox();
+ afx_msg void OnViewEntitiesasSelectedskinned();
+ afx_msg void OnViewEntitiesasSelectedwireframe();
+ afx_msg void OnViewEntitiesasSkinned();
+ afx_msg void OnViewEntitiesasSkinnedandboxed();
+ afx_msg void OnViewEntitiesasWireframe();
+ afx_msg void OnPluginsRefresh();
+ afx_msg void OnViewShowhint();
+ afx_msg void OnUpdateTexturesShowinuse(CCmdUI* pCmdUI);
+ afx_msg void OnTexturesShowall();
+ afx_msg void OnPatchInspector();
+ afx_msg void OnViewOpengllighting();
+ afx_msg void OnSelectAll();
+ afx_msg void OnViewShowcaulk();
+ afx_msg void OnCurveFreeze();
+ afx_msg void OnCurveUnFreeze();
+ afx_msg void OnCurveUnFreezeAll();
+ afx_msg void OnSelectReselect();
+ afx_msg void OnViewShowangles();
+ afx_msg void OnEditSaveprefab();
+ afx_msg void OnCurveMoreendcapsbevelsSquarebevel();
+ afx_msg void OnCurveMoreendcapsbevelsSquareendcap();
+ afx_msg void OnBrushPrimitivesSphere();
+ afx_msg void OnViewCrosshair();
+ afx_msg void OnViewHideshowHideselected();
+ afx_msg void OnViewHideshowShowhidden();
+ afx_msg void OnTexturesShadersShow();
+ afx_msg void OnTexturesFlushUnused();
+ afx_msg void OnViewGroups();
+ afx_msg void OnDropGroupAddtoWorld();
+ afx_msg void OnDropGroupName();
+ afx_msg void OnDropGroupNewgroup();
+ afx_msg void OnDropGroupRemove();
+ afx_msg void OnSplinesMode();
+ afx_msg void OnSplinesLoad();
+ afx_msg void OnSplinesSave();
+ afx_msg void OnSplinesEdit();
+ afx_msg void OnSplineTest();
+ afx_msg void OnSplinesTarget();
+ afx_msg void OnSplinesTargetPoints();
+ afx_msg void OnSplinesCameraPoints();
+ afx_msg void OnPopupNewcameraInterpolated();
+ afx_msg void OnPopupNewcameraSpline();
+ afx_msg void OnPopupNewcameraFixed();
+ //}}AFX_MSG
+ afx_msg void OnMru(unsigned int nID);
+ afx_msg void OnViewNearest(unsigned int nID);
+ afx_msg void OnTextureWad(unsigned int nID);
+ afx_msg void OnBspCommand(unsigned int nID);
+ afx_msg void OnGrid1(unsigned int nID);
+ afx_msg LRESULT OnDisplayChange(WPARAM wp, LPARAM lp);
+ void CheckTextureScale(int id);
+ afx_msg void OnPlugIn(unsigned int nID);
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAINFRM_H__330BBF0A_731C_11D1_B539_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/MapInfo.cpp b/q3radiant/MapInfo.cpp
new file mode 100755
index 0000000..8373b7b
--- /dev/null
+++ b/q3radiant/MapInfo.cpp
@@ -0,0 +1,114 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// MapInfo.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "MapInfo.h"
+#include "qe3.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CMapInfo dialog
+
+
+CMapInfo::CMapInfo(CWnd* pParent /*=NULL*/)
+ : CDialog(CMapInfo::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CMapInfo)
+ m_nNet = 0;
+ m_nTotalBrushes = 0;
+ m_nTotalEntities = 0;
+ //}}AFX_DATA_INIT
+}
+
+
+void CMapInfo::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CMapInfo)
+ DDX_Control(pDX, IDC_LIST_ENTITIES, m_lstEntity);
+ DDX_Text(pDX, IDC_EDIT_NET, m_nNet);
+ DDX_Text(pDX, IDC_EDIT_TOTALBRUSHES, m_nTotalBrushes);
+ DDX_Text(pDX, IDC_EDIT_TOTALENTITIES, m_nTotalEntities);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CMapInfo, CDialog)
+ //{{AFX_MSG_MAP(CMapInfo)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CMapInfo message handlers
+
+BOOL CMapInfo::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_nTotalBrushes = 0;
+ m_nTotalEntities = 0;
+ m_nNet = 0;
+ for (brush_t* pBrush=active_brushes.next ; pBrush != &active_brushes ; pBrush=pBrush->next)
+ {
+ m_nTotalBrushes++;
+ if (pBrush->owner == world_entity)
+ m_nNet++;
+ }
+
+
+ CMapStringToPtr mapEntity;
+
+ int nValue = 0;
+ for (entity_t* pEntity=entities.next ; pEntity != &entities ; pEntity=pEntity->next)
+ {
+ m_nTotalEntities++;
+ nValue = 0;
+ mapEntity.Lookup(pEntity->eclass->name, reinterpret_cast<void*&>(nValue));
+ nValue++ ;
+ mapEntity.SetAt(pEntity->eclass->name, reinterpret_cast<void*>(nValue));
+ }
+
+ m_lstEntity.ResetContent();
+ m_lstEntity.SetTabStops(96);
+ CString strKey;
+ POSITION pos = mapEntity.GetStartPosition();
+ while (pos)
+ {
+ mapEntity.GetNextAssoc(pos, strKey, reinterpret_cast<void*&>(nValue));
+ CString strList;
+ strList.Format("%s\t%i", strKey, nValue);
+ m_lstEntity.AddString(strList);
+ }
+
+ UpdateData(FALSE);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/MapInfo.h b/q3radiant/MapInfo.h
new file mode 100755
index 0000000..28db33a
--- /dev/null
+++ b/q3radiant/MapInfo.h
@@ -0,0 +1,70 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_MAPINFO_H__C241B9A2_819F_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_MAPINFO_H__C241B9A2_819F_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// MapInfo.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CMapInfo dialog
+
+class CMapInfo : public CDialog
+{
+// Construction
+public:
+ CMapInfo(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CMapInfo)
+ enum { IDD = IDD_DLG_MAPINFO };
+ CListBox m_lstEntity;
+ int m_nNet;
+ int m_nTotalBrushes;
+ int m_nTotalEntities;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CMapInfo)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CMapInfo)
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_MAPINFO_H__C241B9A2_819F_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/Messaging.cpp b/q3radiant/Messaging.cpp
new file mode 100755
index 0000000..e744b84
--- /dev/null
+++ b/q3radiant/Messaging.cpp
@@ -0,0 +1,137 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.2.1 $
+// $Author: ttimo $
+// $Date: 2000/02/04 22:59:34 $
+// $Log: Messaging.cpp,v $
+// Revision 1.1.2.1 2000/02/04 22:59:34 ttimo
+// messaging API preview
+//
+//
+// DESCRIPTION:
+// implementation of IMessaging specific interface
+//
+
+#include "stdafx.h"
+
+CPtrArray l_Listeners[RADIANT_MSGCOUNT];
+CPtrArray l_WindowListeners;
+CXYWndWrapper l_XYWndWrapper;
+
+void WINAPI QERApp_HookWindow(IWindowListener* pListen)
+{
+ l_WindowListeners.Add( pListen );
+ pListen->IncRef();
+}
+
+void WINAPI QERApp_UnHookWindow(IWindowListener* pListen)
+{
+ for ( int i = 0; i < l_WindowListeners.GetSize(); i++ )
+ {
+ if (l_WindowListeners.GetAt(i) == pListen)
+ {
+ l_WindowListeners.RemoveAt(i);
+ pListen->DecRef();
+ return;
+ }
+ }
+#ifdef _DEBUG
+ Sys_Printf("WARNING: IWindowListener not found in QERApp_UnHookWindow\n");
+#endif
+}
+
+void DispatchOnMouseMove(UINT nFlags, int x, int y)
+{
+ for( int i = 0; i < l_WindowListeners.GetSize(); i++ )
+ static_cast<IWindowListener*>(l_WindowListeners.GetAt(i))->OnMouseMove( nFlags, x, y );
+}
+
+bool DispatchOnLButtonDown(UINT nFlags, int x, int y)
+{
+ for( int i = 0; i < l_WindowListeners.GetSize(); i++ )
+ if (static_cast<IWindowListener*>(l_WindowListeners.GetAt(i))->OnLButtonDown( nFlags, x, y ))
+ return true;
+ return false;
+}
+
+bool DispatchOnLButtonUp(UINT nFlags, int x, int y)
+{
+ for( int i = 0; i < l_WindowListeners.GetSize(); i++ )
+ if (static_cast<IWindowListener*>(l_WindowListeners.GetAt(i))->OnLButtonUp( nFlags, x, y ))
+ return true;
+ return false;
+}
+
+void WINAPI QERApp_HookListener(IListener* pListen, int Msg)
+{
+#ifdef _DEBUG
+ if (Msg >= RADIANT_MSGCOUNT)
+ {
+ Sys_Printf("ERROR: bad index in QERApp_HookListener\n");
+ return;
+ }
+#endif
+ l_Listeners[Msg].Add( pListen );
+ pListen->IncRef();
+}
+
+int WINAPI QERApp_UnHookListener(IListener* pListen)
+{
+ int count = 0;
+ for( int i = 0; i<RADIANT_MSGCOUNT; i++ )
+ for( int j = 0; j<l_Listeners[i].GetSize(); j++ )
+ if (l_Listeners[i].GetAt(j) == pListen)
+ {
+ l_Listeners[i].RemoveAt(j);
+ pListen->DecRef();
+ count++;
+ }
+ return count;
+}
+
+void DispatchRadiantMsg( int Msg )
+{
+#ifdef _DEBUG
+ if (Msg >= RADIANT_MSGCOUNT)
+ {
+ Sys_Printf("ERROR: bad index in DispatchRadiantMsg\n");
+ return;
+ }
+#endif
+ for(int i = 0; i<l_Listeners[Msg].GetSize(); i++)
+ static_cast<IListener *>(l_Listeners[Msg].GetAt(i))->DispatchRadiantMsg(Msg);
+}
+
+void CXYWndWrapper::SnapToGrid( int x1, int y1, vec3_t pt )
+{
+ CRect rctZ;
+ g_pParentWnd->ActiveXY()->GetClientRect( rctZ );
+ g_pParentWnd->ActiveXY()->SnapToPoint( x1, rctZ.Height() - 1 - y1, pt );
+}
+
+IXYWndWrapper* WINAPI QERApp_GetXYWndWrapper()
+{
+ return &l_XYWndWrapper;
+}
diff --git a/q3radiant/Messaging.h b/q3radiant/Messaging.h
new file mode 100755
index 0000000..dfea880
--- /dev/null
+++ b/q3radiant/Messaging.h
@@ -0,0 +1,46 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.2.1 $
+// $Author: ttimo $
+// $Date: 2000/02/04 22:59:34 $
+// $Log: Messaging.h,v $
+// Revision 1.1.2.1 2000/02/04 22:59:34 ttimo
+// messaging API preview
+//
+//
+// DESCRIPTION:
+// headers for internal classes used in Messaging.cpp
+//
+
+#ifndef __MESSAGING_H_
+#define __MESSAGING_H_
+
+class CXYWndWrapper : public IXYWndWrapper
+{
+public:
+ void SnapToGrid( int x1, int y1, vec3_t pt );
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/NameDlg.cpp b/q3radiant/NameDlg.cpp
new file mode 100755
index 0000000..14027c5
--- /dev/null
+++ b/q3radiant/NameDlg.cpp
@@ -0,0 +1,79 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// NameDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "NameDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CNameDlg dialog
+
+
+CNameDlg::CNameDlg(const char *pName, CWnd* pParent /*=NULL*/)
+ : CDialog(CNameDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CNameDlg)
+ m_strName = _T("");
+ //}}AFX_DATA_INIT
+ m_strCaption = pName;
+}
+
+
+void CNameDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CNameDlg)
+ DDX_Text(pDX, IDC_EDIT_NAME, m_strName);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CNameDlg, CDialog)
+ //{{AFX_MSG_MAP(CNameDlg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CNameDlg message handlers
+
+void CNameDlg::OnOK()
+{
+ CDialog::OnOK();
+}
+
+BOOL CNameDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ SetWindowText(m_strCaption);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/NameDlg.h b/q3radiant/NameDlg.h
new file mode 100755
index 0000000..6dd75ba
--- /dev/null
+++ b/q3radiant/NameDlg.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_NAMEDLG_H__624F3290_976A_48A9_AE89_50CD1E6E2F9A__INCLUDED_)
+#define AFX_NAMEDLG_H__624F3290_976A_48A9_AE89_50CD1E6E2F9A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// NameDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CNameDlg dialog
+
+class CNameDlg : public CDialog
+{
+ CString m_strCaption;
+// Construction
+public:
+ CNameDlg(const char *pName, CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CNameDlg)
+ enum { IDD = IDD_NEWNAME };
+ CString m_strName;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CNameDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CNameDlg)
+ virtual void OnOK();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_NAMEDLG_H__624F3290_976A_48A9_AE89_50CD1E6E2F9A__INCLUDED_)
diff --git a/q3radiant/NewProjDlg.cpp b/q3radiant/NewProjDlg.cpp
new file mode 100755
index 0000000..4a9c1b5
--- /dev/null
+++ b/q3radiant/NewProjDlg.cpp
@@ -0,0 +1,64 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// NewProjDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "NewProjDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CNewProjDlg dialog
+
+
+CNewProjDlg::CNewProjDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CNewProjDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CNewProjDlg)
+ m_strName = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CNewProjDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CNewProjDlg)
+ DDX_Text(pDX, IDC_EDIT_NAME, m_strName);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CNewProjDlg, CDialog)
+ //{{AFX_MSG_MAP(CNewProjDlg)
+ // NOTE: the ClassWizard will add message map macros here
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CNewProjDlg message handlers
diff --git a/q3radiant/NewProjDlg.h b/q3radiant/NewProjDlg.h
new file mode 100755
index 0000000..6d6c302
--- /dev/null
+++ b/q3radiant/NewProjDlg.h
@@ -0,0 +1,67 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_NEWPROJDLG_H__1E2527A2_8447_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_NEWPROJDLG_H__1E2527A2_8447_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// NewProjDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CNewProjDlg dialog
+
+class CNewProjDlg : public CDialog
+{
+// Construction
+public:
+ CNewProjDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CNewProjDlg)
+ enum { IDD = IDD_DLG_NEWPROJECT };
+ CString m_strName;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CNewProjDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CNewProjDlg)
+ // NOTE: the ClassWizard will add member functions here
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_NEWPROJDLG_H__1E2527A2_8447_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/PARSE.CPP b/q3radiant/PARSE.CPP
new file mode 100755
index 0000000..6a2b340
--- /dev/null
+++ b/q3radiant/PARSE.CPP
@@ -0,0 +1,148 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+
+char token[MAXTOKEN];
+qboolean unget;
+char *script_p;
+int scriptline;
+
+void StartTokenParsing (char *data)
+{
+ scriptline = 1;
+ script_p = data;
+ unget = false;
+}
+
+qboolean WINAPI GetToken (qboolean crossline)
+{
+ char *token_p;
+
+ if (unget) // is a token allready waiting?
+ {
+ unget = false;
+ return true;
+ }
+
+//
+// skip space
+//
+skipspace:
+ while (*script_p <= 32)
+ {
+ if (!*script_p)
+ {
+ if (!crossline)
+ Sys_Printf("Warning: Line %i is incomplete [01]\n",scriptline);
+ return false;
+ }
+ if (*script_p++ == '\n')
+ {
+ if (!crossline)
+ Sys_Printf("Warning: Line %i is incomplete [02]\n",scriptline);
+ scriptline++;
+ }
+ }
+
+ if (script_p[0] == '/' && script_p[1] == '/') // comment field
+ {
+ if (!crossline)
+ Sys_Printf("Warning: Line %i is incomplete [03]\n",scriptline);
+ while (*script_p++ != '\n')
+ if (!*script_p)
+ {
+ if (!crossline)
+ Sys_Printf("Warning: Line %i is incomplete [04]\n",scriptline);
+ return false;
+ }
+ goto skipspace;
+ }
+
+//
+// copy token
+//
+ token_p = token;
+
+ if (*script_p == '"')
+ {
+ script_p++;
+ //if (*script_p == '"') // handle double quotes i suspect they are put in by other editors cccasionally
+ // script_p++;
+ while ( *script_p != '"' )
+ {
+ if (!*script_p)
+ Error ("EOF inside quoted token");
+ *token_p++ = *script_p++;
+ if (token_p == &token[MAXTOKEN])
+ Error ("Token too large on line %i",scriptline);
+ }
+ script_p++;
+ //if (*script_p == '"') // handle double quotes i suspect they are put in by other editors cccasionally
+ // script_p++;
+ }
+ else while ( *script_p > 32 )
+ {
+ *token_p++ = *script_p++;
+ if (token_p == &token[MAXTOKEN])
+ Error ("Token too large on line %i",scriptline);
+ }
+
+ *token_p = 0;
+
+ return true;
+}
+
+void WINAPI UngetToken (void)
+{
+ unget = true;
+}
+
+
+/*
+==============
+TokenAvailable
+
+Returns true if there is another token on the line
+==============
+*/
+qboolean TokenAvailable (void)
+{
+ char *search_p;
+
+ search_p = script_p;
+
+ while ( *search_p <= 32)
+ {
+ if (*search_p == '\n')
+ return false;
+ if (*search_p == 0)
+ return false;
+ search_p++;
+ }
+
+ if (*search_p == ';')
+ return false;
+
+ return true;
+}
+
diff --git a/q3radiant/PARSE.H b/q3radiant/PARSE.H
new file mode 100755
index 0000000..60e1c7b
--- /dev/null
+++ b/q3radiant/PARSE.H
@@ -0,0 +1,34 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// parse.h -- text file parsing routines
+
+#define MAXTOKEN 1024
+
+extern char token[MAXTOKEN];
+extern int scriptline;
+
+// NOTE: added WINAPI call syntax to export these for plugins in _QERScripLibTable
+void StartTokenParsing (char *data);
+qboolean WINAPI GetToken (qboolean crossline);
+void WINAPI UngetToken (void);
+qboolean TokenAvailable (void);
+
diff --git a/q3radiant/PMESH.CPP b/q3radiant/PMESH.CPP
new file mode 100755
index 0000000..3f69152
--- /dev/null
+++ b/q3radiant/PMESH.CPP
@@ -0,0 +1,5136 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//
+// Preliminary patch stuff
+//
+//
+
+#include "stdafx.h"
+#include "qe3.h"
+#include "DialogInfo.h"
+#include "CapDialog.h"
+
+// externs
+extern void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...);
+extern face_t *Face_Alloc( void );
+void _Write3DMatrix (FILE *f, int y, int x, int z, float *m);
+void _Write3DMatrix (CMemFile *f, int y, int x, int z, float *m);
+
+
+
+#define CBLOCK_SUBDIVISIONS 6
+
+
+patchMesh_t* MakeNewPatch()
+{
+ patchMesh_t *pm = reinterpret_cast<patchMesh_t*>(qmalloc(sizeof(patchMesh_t)));
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ pm->pData = static_cast<void *>( g_SurfaceTable.m_pfnPatchAlloc( pm ) );
+ }
+ return pm;
+}
+
+// FIXME: this needs to be dynamic
+//#define MAX_PATCH_MESHES 4096
+//patchMesh_t patchMeshes[MAX_PATCH_MESHES];
+//int numPatchMeshes = 0;
+
+// used for a save spot
+patchMesh_t patchSave;
+
+// Tracks the selected patch for point manipulation/update. FIXME: Need to revert back to a generalized
+// brush approach
+//--int g_nSelectedPatch = -1;
+
+// HACK: for tracking which view generated the click
+// as we dont want to deselect a point on a same point
+// click if it is from a different view
+int g_nPatchClickedView = -1;
+bool g_bSameView = false;
+
+
+// globals
+bool g_bPatchShowBounds = true;
+bool g_bPatchWireFrame = false;
+bool g_bPatchWeld = true;
+bool g_bPatchDrillDown = true;
+bool g_bPatchInsertMode = false;
+bool g_bPatchBendMode = false;
+int g_nPatchBendState = -1;
+int g_nPatchInsertState = -1;
+int g_nBendOriginIndex = 0;
+vec3_t g_vBendOrigin;
+
+bool g_bPatchAxisOnRow = true;
+int g_nPatchAxisIndex = 0;
+bool g_bPatchLowerEdge = true;
+
+// BEND states
+enum
+{
+ BEND_SELECT_ROTATION = 0,
+ BEND_SELECT_ORIGIN,
+ BEND_SELECT_EDGE,
+ BEND_BENDIT,
+ BEND_STATE_COUNT
+};
+
+const char *g_pBendStateMsg[] =
+{
+ "Use TAB to cycle through available bend axis. Press ENTER when the desired one is highlighted.",
+ "Use TAB to cycle through available rotation axis. This will LOCK around that point. You may also use Shift + Middle Click to select an arbitrary point. Press ENTER when the desired one is highlighted",
+ "Use TAB to choose which side to bend. Press ENTER when the desired one is highlighted.",
+ "Use the MOUSE to bend the patch. It uses the same ui rules as Free Rotation. Press ENTER to accept the bend, press ESC to abandon it and exit Bend mode",
+ ""
+};
+
+// INSERT states
+enum
+{
+ INSERT_SELECT_EDGE = 0,
+ INSERT_STATE_COUNT
+};
+
+const char* g_pInsertStateMsg[] =
+{
+ "Use TAB to cycle through available rows/columns for insertion/deletion. Press INS to insert at the highlight, DEL to remove the pair"
+};
+
+
+float *g_InversePoints[1024];
+
+const float fFullBright = 1.0;
+const float fLowerLimit = .50;
+const float fDec = .05;
+void _SetColor(face_t* f, float fColor[3])
+{
+ return;
+ fColor[0] = f->d_color[0];
+ fColor[1] = f->d_color[1];
+ fColor[2] = f->d_color[2];
+ qglColor3fv(fColor);
+}
+
+
+void _DecColor(float fColor[3])
+{
+ return;
+ fColor[0] -= fDec;
+ fColor[1] -= fDec ;
+ fColor[2] -= fDec;
+ for (int i = 0; i < 3; i++)
+ {
+ if (fColor[i] <= fLowerLimit)
+ {
+ fColor[0] = fFullBright;
+ fColor[1] = fFullBright;
+ fColor[2] = fFullBright;
+ break;
+ }
+ }
+ qglColor3fv(fColor);
+}
+
+vec_t __VectorNormalize (vec3_t in, vec3_t out)
+{
+ vec_t length, ilength;
+
+ length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
+ if (length == 0)
+ {
+ VectorClear (out);
+ return 0;
+ }
+
+ ilength = 1.0/length;
+ out[0] = in[0]*ilength;
+ out[1] = in[1]*ilength;
+ out[2] = in[2]*ilength;
+
+ return length;
+}
+
+
+void Patch_SetType(patchMesh_t *p, int nType)
+{
+ p->type = (p->type & PATCH_STYLEMASK) | nType;
+}
+
+void Patch_SetStyle(patchMesh_t *p, int nStyle)
+{
+ p->type = (p->type & PATCH_TYPEMASK) | nStyle;
+}
+
+/*
+==================
+Patch_MemorySize
+==================
+*/
+int Patch_MemorySize(patchMesh_t *p)
+{
+ return _msize(p);
+}
+
+
+
+/*
+===============
+InterpolateInteriorPoints
+===============
+*/
+void InterpolateInteriorPoints( patchMesh_t *p )
+{
+ int i, j, k;
+ int next, prev;
+
+ for ( i = 0 ; i < p->width ; i += 2 )
+ {
+
+ next = ( i == p->width - 1 ) ? 1 : ( i + 1 ) % p->width;
+ prev = ( i == 0 ) ? p->width - 2 : i - 1;
+
+#if 0
+ if ( i == 0 )
+ {
+ next = ( i + 1 ) % p->width;
+ prev = p->width - 2; // joined wrap case
+ }
+ else if ( i == p->width - 1 )
+ {
+ next = 1;
+ prev = i - 1;
+ }
+ else
+ {
+ next = ( i + 1 ) % p->width;
+ prev = i - 1;
+ }
+#endif
+
+ for ( j = 0 ; j < p->height ; j++ )
+ {
+ for ( k = 0 ; k < 3 ; k++ )
+ {
+ p->ctrl[i][j].xyz[k] = ( p->ctrl[next][j].xyz[k] + p->ctrl[prev][j].xyz[k] ) * 0.5;
+ }
+ }
+ }
+}
+
+/*
+=================
+MakeMeshNormals
+
+=================
+*/
+int neighbors[8][2] = {
+ {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
+};
+
+void Patch_MeshNormals(patchMesh_t *in )
+{
+ int i, j, k, dist;
+ vec3_t normal;
+ vec3_t sum;
+ int count;
+ vec3_t base;
+ vec3_t delta;
+ int x, y;
+ drawVert_t *dv;
+ vec3_t around[8], temp;
+ qboolean good[8];
+ qboolean wrapWidth, wrapHeight;
+ float len;
+
+ wrapWidth = false;
+ for ( i = 0 ; i < in->height ; i++ )
+ {
+
+ VectorSubtract( in->ctrl[0][i].xyz,
+ in->ctrl[in->width-1][i].xyz, delta );
+ len = VectorLength( delta );
+ if ( len > 1.0 )
+ {
+ break;
+ }
+ }
+ if ( i == in->height )
+ {
+ wrapWidth = true;
+ }
+
+ wrapHeight = false;
+ for ( i = 0 ; i < in->width ; i++ )
+ {
+ VectorSubtract( in->ctrl[i][0].xyz,
+ in->ctrl[i][in->height-1].xyz, delta );
+ len = VectorLength( delta );
+ if ( len > 1.0 )
+ {
+ break;
+ }
+ }
+ if ( i == in->width)
+ {
+ wrapHeight = true;
+ }
+
+
+ for ( i = 0 ; i < in->width ; i++ )
+ {
+ for ( j = 0 ; j < in->height ; j++ )
+ {
+ count = 0;
+ //--dv = reinterpret_cast<drawVert_t*>(in.ctrl[j*in.width+i]);
+ dv = &in->ctrl[i][j];
+ VectorCopy( dv->xyz, base );
+ for ( k = 0 ; k < 8 ; k++ )
+ {
+ VectorClear( around[k] );
+ good[k] = false;
+
+ for ( dist = 1 ; dist <= 3 ; dist++ )
+ {
+ x = i + neighbors[k][0] * dist;
+ y = j + neighbors[k][1] * dist;
+ if ( wrapWidth )
+ {
+ if ( x < 0 )
+ {
+ x = in->width - 1 + x;
+ }
+ else if ( x >= in->width )
+ {
+ x = 1 + x - in->width;
+ }
+ }
+ if ( wrapHeight )
+ {
+ if ( y < 0 )
+ {
+ y = in->height - 1 + y;
+ }
+ else if ( y >= in->height )
+ {
+ y = 1 + y - in->height;
+ }
+ }
+
+ if ( x < 0 || x >= in->width || y < 0 || y >= in->height )
+ {
+ break; // edge of patch
+ }
+ //--VectorSubtract( in.ctrl[y*in.width+x]->xyz, base, temp );
+ VectorSubtract( in->ctrl[x][y].xyz, base, temp );
+ if ( __VectorNormalize( temp, temp ) == 0 )
+ {
+ continue; // degenerate edge, get more dist
+ }
+ else
+ {
+ good[k] = true;
+ VectorCopy( temp, around[k] );
+ break; // good edge
+ }
+ }
+ }
+
+ VectorClear( sum );
+ for ( k = 0 ; k < 8 ; k++ )
+ {
+ if ( !good[k] || !good[(k+1)&7] )
+ {
+ continue; // didn't get two points
+ }
+ CrossProduct( around[(k+1)&7], around[k], normal );
+ if ( __VectorNormalize( normal, normal ) == 0 )
+ {
+ continue;
+ }
+ VectorAdd( normal, sum, sum );
+ count++;
+ }
+ if ( count == 0 )
+ {
+ //printf("bad normal\n");
+ count = 1;
+ //continue;
+ }
+ __VectorNormalize( sum, dv->normal );
+ }
+ }
+}
+
+
+
+
+/*
+==================
+Patch_CalcBounds
+==================
+*/
+void Patch_CalcBounds(patchMesh_t *p, vec3_t& vMin, vec3_t& vMax)
+{
+ vMin[0] = vMin[1] = vMin[2] = 99999;
+ vMax[0] = vMax[1] = vMax[2] = -99999;
+
+ p->bDirty = true;
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ float f = p->ctrl[w][h].xyz[j];
+ if (f < vMin[j])
+ vMin[j] = f;
+ if (f > vMax[j])
+ vMax[j] = f;
+ }
+ }
+ }
+}
+
+/*
+==================
+Brush_RebuildBrush
+==================
+*/
+void Brush_RebuildBrush(brush_t *b, vec3_t vMins, vec3_t vMaxs)
+{
+ //
+ // Total hack job
+ // Rebuilds a brush
+ int i, j;
+ face_t *f, *next;
+ vec3_t pts[4][2];
+ texdef_t texdef;
+ // free faces
+
+ for (j = 0; j < 3; j++)
+ {
+ if ((int)vMins[j] == (int)vMaxs[j])
+ {
+ vMins[j] -= 4;
+ vMaxs[j] += 4;
+ }
+ }
+
+
+ for (f=b->brush_faces ; f ; f=next)
+ {
+ next = f->next;
+ if (f)
+ texdef = f->texdef;
+ Face_Free( f );
+ }
+
+ b->brush_faces = NULL;
+
+ // left the last face so we can use its texdef
+
+ for (i=0 ; i<3 ; i++)
+ if (vMaxs[i] < vMins[i])
+ Error ("Brush_RebuildBrush: backwards");
+
+ pts[0][0][0] = vMins[0];
+ pts[0][0][1] = vMins[1];
+
+ pts[1][0][0] = vMins[0];
+ pts[1][0][1] = vMaxs[1];
+
+ pts[2][0][0] = vMaxs[0];
+ pts[2][0][1] = vMaxs[1];
+
+ pts[3][0][0] = vMaxs[0];
+ pts[3][0][1] = vMins[1];
+
+ for (i=0 ; i<4 ; i++)
+ {
+ pts[i][0][2] = vMins[2];
+ pts[i][1][0] = pts[i][0][0];
+ pts[i][1][1] = pts[i][0][1];
+ pts[i][1][2] = vMaxs[2];
+ }
+
+ for (i=0 ; i<4 ; i++)
+ {
+ f = Face_Alloc();
+ f->texdef = texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ if ( b->patchBrush )
+ {
+ f->texdef.flags |= SURF_PATCH;
+ }
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+ j = (i+1)%4;
+
+ VectorCopy (pts[j][1], f->planepts[0]);
+ VectorCopy (pts[i][1], f->planepts[1]);
+ VectorCopy (pts[i][0], f->planepts[2]);
+ }
+
+ f = Face_Alloc();
+ f->texdef = texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ if ( b->patchBrush )
+ {
+ f->texdef.flags |= SURF_PATCH;
+ }
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorCopy (pts[0][1], f->planepts[0]);
+ VectorCopy (pts[1][1], f->planepts[1]);
+ VectorCopy (pts[2][1], f->planepts[2]);
+
+ f = Face_Alloc();
+ f->texdef = texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ if ( b->patchBrush )
+ {
+ f->texdef.flags |= SURF_PATCH;
+ }
+ f->next = b->brush_faces;
+ b->brush_faces = f;
+
+ VectorCopy (pts[2][0], f->planepts[0]);
+ VectorCopy (pts[1][0], f->planepts[1]);
+ VectorCopy (pts[0][0], f->planepts[2]);
+
+ Brush_Build(b);
+}
+
+void WINAPI Patch_Rebuild(patchMesh_t *p)
+{
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ p->bDirty = true;
+}
+
+/*
+==================
+AddBrushForPatch
+==================
+ adds a patch brush and ties it to this patch id
+*/
+brush_t* AddBrushForPatch(patchMesh_t *pm, bool bLinkToWorld )
+{
+ // find the farthest points in x,y,z
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(pm, vMin, vMax);
+
+ for (int j = 0; j < 3; j++)
+ {
+ if (vMin[j] == vMax[j])
+ {
+ vMin[j] -= 4;
+ vMax[j] += 4;
+ }
+ }
+
+ brush_t *b = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
+ face_t *f;
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ f->texdef.flags |= SURF_PATCH;
+ }
+
+ // FIXME: this entire type of linkage needs to be fixed
+ b->pPatch = pm;
+ pm->pSymbiot = b;
+ pm->bSelected = false;
+ pm->bOverlay = false;
+ pm->bDirty = true;
+ pm->nListID = -1;
+
+ if (bLinkToWorld)
+ {
+ Brush_AddToList (b, &active_brushes);
+ Entity_LinkBrush (world_entity, b);
+ Brush_Build(b);
+ }
+
+ return b;
+}
+
+void Patch_SetPointIntensities(int n)
+{
+#if 0
+ patchMesh_t *p = patchMeshes[n];
+ for (int i = 0; i < p->width; i++)
+ {
+ for (int j = 0; j < p->height; j++)
+ {
+
+ }
+ }
+#endif
+}
+
+// very approximate widths and heights
+
+/*
+==================
+Patch_Width
+==================
+*/
+float Patch_Width(patchMesh_t *p)
+{
+ float f = 0;
+ for (int i = 0; i < p->width-1; i++)
+ {
+ vec3_t vTemp;
+ VectorSubtract(p->ctrl[i][0].xyz, p->ctrl[i+1][0].xyz, vTemp);
+ f += VectorLength(vTemp);
+ }
+ return f;
+}
+
+float Patch_WidthDistanceTo(patchMesh_t *p, int j)
+{
+ float f = 0;
+ for (int i = 0; i < j; i++)
+ {
+ vec3_t vTemp;
+ VectorSubtract(p->ctrl[i][0].xyz, p->ctrl[i+1][0].xyz, vTemp);
+ f += VectorLength(vTemp);
+ }
+ return f;
+}
+
+
+
+/*
+==================
+Patch_Height
+==================
+*/
+float Patch_Height(patchMesh_t *p)
+{
+ float f = 0;
+ for (int i = 0; i < p->height-1; i++)
+ {
+ vec3_t vTemp;
+ VectorSubtract(p->ctrl[0][i].xyz, p->ctrl[0][i+1].xyz, vTemp);
+ f += VectorLength(vTemp);
+ }
+ return f;
+}
+
+float Patch_HeightDistanceTo(patchMesh_t *p, int j)
+{
+ float f = 0;
+ for (int i = 0; i < j; i++)
+ {
+ vec3_t vTemp;
+ VectorSubtract(p->ctrl[0][i].xyz, p->ctrl[0][i+1].xyz, vTemp);
+ f += VectorLength(vTemp);
+ }
+ return f;
+}
+
+
+
+/*
+==================
+Patch_Naturalize
+==================
+texture = TotalTexture * LengthToThisControlPoint / TotalControlPointLength
+
+dist( this control point to first control point ) / dist ( last control pt to first)
+*/
+void Patch_Naturalize(patchMesh_t *p)
+{
+ int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? p->d_texture->width * 0.5 : p->d_texture->width;
+ int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? p->d_texture->height * 0.5 : p->d_texture->height;
+ float fPWidth = Patch_Width(p);
+ float fPHeight = Patch_Height(p);
+ float xAccum = 0;
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ float yAccum = 0;
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ p->ctrl[i][j].st[0] = (fPWidth / nWidth) * xAccum / fPWidth;
+ p->ctrl[i][j].st[1] = (fPHeight / nHeight) * yAccum / fPHeight;
+ yAccum = Patch_HeightDistanceTo(p,j+1);
+ //p->ctrl[i][j][3] = (fPWidth / nWidth) * (float)i / (p->width - 1);
+ //p->ctrl[i][j][4] = (fPHeight/ nHeight) * (float)j / (p->height - 1);
+ }
+ xAccum = Patch_WidthDistanceTo(p,i+1);
+ }
+ p->bDirty = true;
+}
+
+/*
+ if (bIBevel)
+ {
+ VectorCopy(p->ctrl[1][0], p->ctrl[1][1]);
+ }
+
+ if (bIEndcap)
+ {
+ VectorCopy(p->ctrl[3][0], p->ctrl[4][1]);
+ VectorCopy(p->ctrl[2][0], p->ctrl[3][1]);
+ VectorCopy(p->ctrl[2][0], p->ctrl[2][1]);
+ VectorCopy(p->ctrl[2][0], p->ctrl[1][1]);
+ VectorCopy(p->ctrl[1][0], p->ctrl[0][1]);
+ VectorCopy(p->ctrl[1][0], p->ctrl[0][2]);
+ VectorCopy(p->ctrl[1][0], p->ctrl[1][2]);
+ VectorCopy(p->ctrl[2][0], p->ctrl[2][2]);
+ VectorCopy(p->ctrl[3][0], p->ctrl[3][2]);
+ VectorCopy(p->ctrl[3][0], p->ctrl[4][2]);
+ }
+*/
+
+int Index3By[][2] =
+{
+ {0,0},
+ {1,0},
+ {2,0},
+ {2,1},
+ {2,2},
+ {1,2},
+ {0,2},
+ {0,1},
+ {0,0},
+ {0,0},
+ {0,0},
+ {0,0},
+ {0,0},
+ {0,0},
+ {0,0}
+};
+
+int Index5By[][2] =
+{
+ {0,0},
+ {1,0},
+ {2,0},
+ {3,0},
+ {4,0},
+ {4,1},
+ {4,2},
+ {4,3},
+ {4,4},
+ {3,4},
+ {2,4},
+ {1,4},
+ {0,4},
+ {0,3},
+ {0,2},
+ {0,1}
+};
+
+
+
+int Interior3By[][2] =
+{
+ {1,1}
+};
+
+int Interior5By[][2] =
+{
+ {1,1},
+ {2,1},
+ {3,1},
+ {1,2},
+ {2,2},
+ {3,2},
+ {1,3},
+ {2,3},
+ {3,3}
+};
+
+int Interior3ByCount = sizeof(Interior3By) / sizeof(int[2]);
+int Interior5ByCount = sizeof(Interior5By) / sizeof(int[2]);
+
+face_t* Patch_GetAxisFace(patchMesh_t *p)
+{
+ face_t *f = NULL;
+ vec3_t vTemp;
+ brush_t *b = p->pSymbiot;
+
+ for (f = b->brush_faces ; f ; f = f->next)
+ {
+ VectorSubtract(f->face_winding->points[1], f->face_winding->points[0], vTemp);
+ int nScore = 0;
+
+ // default edge faces on caps are 8 high so
+ // as soon as we hit one that is bigger it should be on the right axis
+ for (int j = 0; j < 3; j++)
+ {
+ if (vTemp[j] > 8)
+ nScore++;
+ }
+
+ if (nScore > 0)
+ break;
+ }
+
+ if (f == NULL)
+ f = b->brush_faces;
+ return f;
+}
+
+int g_nFaceCycle = 0;
+
+face_t* nextFace(patchMesh_t *p)
+{
+ brush_t *b = p->pSymbiot;
+ face_t *f = NULL;
+ int n = 0;
+ for (f = b->brush_faces ; f && n <= g_nFaceCycle; f = f->next)
+ {
+ n++;
+ }
+ g_nFaceCycle++;
+ if (g_nFaceCycle > 5)
+ {
+ g_nFaceCycle =0;
+ f = b->brush_faces;
+ }
+
+ return f;
+}
+
+
+extern void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f);
+void Patch_CapTexture(patchMesh_t *p, bool bFaceCycle = false)
+{
+ Patch_MeshNormals(p);
+ face_t *f = (bFaceCycle) ? nextFace(p) : Patch_GetAxisFace(p);
+ vec3_t vSave;
+ VectorCopy(f->plane.normal, vSave);
+
+ float fRotate = f->texdef.rotate;
+ f->texdef.rotate = 0;
+ float fScale[2];
+ fScale[0] = f->texdef.scale[0];
+ fScale[1] = f->texdef.scale[1];
+ f->texdef.scale[0] = 0.5;
+ f->texdef.scale[1] = 0.5;
+ float fShift[2];
+ fShift[0] = f->texdef.shift[0];
+ fShift[1] = f->texdef.shift[1];
+ f->texdef.shift[0] = 0;
+ f->texdef.shift[1] = 0;
+
+ for (int i = 0; i < p->width; i++)
+ {
+ for (int j = 0; j < p->height; j++)
+ {
+ if (!bFaceCycle)
+ {
+ VectorCopy(p->ctrl[i][j].normal, f->plane.normal);
+ }
+ EmitTextureCoordinates( p->ctrl[i][j].xyz, f->d_texture, f);
+ }
+ }
+ VectorCopy(vSave, f->plane.normal);
+ f->texdef.rotate = fRotate;
+ f->texdef.scale[0] = fScale[0];
+ f->texdef.scale[1] = fScale[1];
+ f->texdef.shift[0] = fShift[0];
+ f->texdef.shift[1] = fShift[1];
+ p->bDirty = true;
+}
+
+void FillPatch(patchMesh_t *p, vec3_t v)
+{
+ for (int i = 0; i < p->width; i++)
+ {
+ for (int j = 0; j < p->height; j++)
+ {
+ VectorCopy(v, p->ctrl[i][j].xyz);
+ }
+ }
+}
+
+brush_t* Cap(patchMesh_t *pParent, bool bByColumn, bool bFirst)
+{
+ brush_t *b;
+ patchMesh_t *p;
+ vec3_t vMin, vMax;
+ int i, j;
+
+ bool bSmall = true;
+ // make a generic patch
+ if (pParent->width <= 9)
+ {
+ b = Patch_GenericMesh(3, 3, 2, false);
+ }
+ else
+ {
+ b = Patch_GenericMesh(5, 5, 2, false);
+ bSmall = false;
+ }
+
+ if (!b)
+ {
+ Sys_Printf("Unable to cap. You may need to ungroup the patch.\n");
+ return NULL;
+ }
+
+ p = b->pPatch;
+ p->type |= PATCH_CAP;
+
+ vMin[0] = vMin[1] = vMin[2] = 9999;
+ vMax[0] = vMax[1] = vMax[2] = -9999;
+
+ // we seam the column edge, FIXME: this might need to be able to seem either edge
+ //
+ int nSize = (bByColumn) ? pParent->width : pParent->height;
+ int nIndex = (bFirst) ? 0 : (bByColumn) ? pParent->height-1 : pParent->width-1;
+
+ FillPatch(p, pParent->ctrl[0][nIndex].xyz);
+
+ for (i = 0; i < nSize; i++)
+ {
+ if (bByColumn)
+ {
+ if (bSmall)
+ {
+ VectorCopy(pParent->ctrl[i][nIndex].xyz, p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz);
+ }
+ else
+ {
+ VectorCopy(pParent->ctrl[i][nIndex].xyz, p->ctrl[Index5By[i][0]][Index5By[i][1]].xyz);
+ }
+ }
+ else
+ {
+ if (bSmall)
+ {
+ VectorCopy(pParent->ctrl[nIndex][i].xyz, p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz);
+ }
+ else
+ {
+ VectorCopy(pParent->ctrl[nIndex][i].xyz, p->ctrl[Index5By[i][0]][Index5By[i][1]].xyz);
+ }
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ float f = (bSmall) ? p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz[j] : p->ctrl[Index5By[i][0]][Index5By[i][1]].xyz[j];
+ if (f < vMin[j])
+ vMin[j] = f;
+ if (f > vMax[j])
+ vMax[j] = f;
+ }
+ }
+
+ vec3_t vTemp;
+ for (j = 0; j < 3; j++)
+ {
+ vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
+ }
+
+ int nCount = (bSmall) ? Interior3ByCount : Interior5ByCount;
+ for (j = 0; j < nCount; j++)
+ {
+ if (bSmall)
+ {
+ VectorCopy(vTemp, p->ctrl[Interior3By[j][0]][Interior3By[j][1]].xyz);
+ }
+ else
+ {
+ VectorCopy(vTemp, p->ctrl[Interior5By[j][0]][Interior5By[j][1]].xyz);
+ }
+ }
+
+ if (bFirst)
+ {
+ drawVert_t vertTemp;
+ for (i = 0; i < p->width; i++)
+ {
+ for (j = 0; j < p->height / 2; j++)
+ {
+ memcpy(&vertTemp, &p->ctrl[i][p->height - 1- j], sizeof (drawVert_t));
+ memcpy(&p->ctrl[i][p->height - 1 - j], &p->ctrl[i][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[i][j], &vertTemp, sizeof(drawVert_t));
+ }
+ }
+ }
+
+ Patch_Rebuild(p);
+ Patch_CapTexture(p);
+ return p->pSymbiot;
+}
+
+brush_t* CapSpecial(patchMesh_t *pParent, int nType, bool bFirst)
+{
+ brush_t *b;
+ patchMesh_t *p;
+ vec3_t vMin, vMax, vTemp;
+ int i, j;
+
+ if (nType == CCapDialog::IENDCAP)
+ b = Patch_GenericMesh(5, 3, 2, false);
+ else
+ b = Patch_GenericMesh(3, 3, 2, false);
+
+ if (!b)
+ {
+ Sys_Printf("Unable to cap. Make sure you ungroup before re-capping.");
+ return NULL;
+ }
+
+ p = b->pPatch;
+ p->type |= PATCH_CAP;
+
+ vMin[0] = vMin[1] = vMin[2] = 9999;
+ vMax[0] = vMax[1] = vMax[2] = -9999;
+
+ int nSize = pParent->width;
+ int nIndex = (bFirst) ? 0 : pParent->height-1;
+
+ // parent bounds are used for some things
+ Patch_CalcBounds(pParent, vMin, vMax);
+
+ for (j = 0; j < 3; j++)
+ {
+ vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
+ }
+
+ if (nType == CCapDialog::IBEVEL)
+ {
+ VectorCopy(pParent->ctrl[0][nIndex].xyz, p->ctrl[0][0].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[0][2].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][1].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[2][2].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][0].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][1].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][2].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[2][0].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[2][1].xyz);
+ }
+ else if (nType == CCapDialog::BEVEL)
+ {
+ vec3_t p1, p2, p3, p4, temp, dir;
+
+ VectorCopy(pParent->ctrl[0][nIndex].xyz, p3);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p1);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p2);
+
+ VectorSubtract(p3, p2, dir);
+ VectorNormalize(dir);
+ VectorSubtract(p1, p2, temp);
+ vec_t dist = _DotProduct(temp, dir);
+
+ VectorScale(dir, dist, temp);
+
+ VectorAdd(p2, temp, temp);
+
+ VectorSubtract(temp, p1, temp);
+ VectorScale(temp, 2, temp);
+ VectorAdd(p1, temp, p4);
+
+ VectorCopy(p4, p->ctrl[0][0].xyz);
+ VectorCopy(p4, p->ctrl[1][0].xyz);
+ VectorCopy(p4, p->ctrl[0][1].xyz);
+ VectorCopy(p4, p->ctrl[1][1].xyz);
+ VectorCopy(p4, p->ctrl[0][2].xyz);
+ VectorCopy(p4, p->ctrl[1][2].xyz);
+ VectorCopy(p3, p->ctrl[2][0].xyz);
+ VectorCopy(p1, p->ctrl[2][1].xyz);
+ VectorCopy(p2, p->ctrl[2][2].xyz);
+
+ }
+ else if (nType == CCapDialog::ENDCAP)
+ {
+ VectorAdd(pParent->ctrl[4][nIndex].xyz, pParent->ctrl[0][nIndex].xyz, vTemp);
+ VectorScale(vTemp, 0.5, vTemp);
+ VectorCopy(pParent->ctrl[0][nIndex].xyz, p->ctrl[0][0].xyz);
+ VectorCopy(vTemp, p->ctrl[1][0].xyz);
+ VectorCopy(pParent->ctrl[4][nIndex].xyz, p->ctrl[2][0].xyz);
+
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[0][2].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[1][2].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][2].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[1][1].xyz);
+
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][1].xyz);
+ VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[2][1].xyz);
+ }
+ else
+ {
+ VectorCopy(pParent->ctrl[0][nIndex].xyz, p->ctrl[0][0].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][0].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][0].xyz);
+ VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[3][0].xyz);
+ VectorCopy(pParent->ctrl[4][nIndex].xyz, p->ctrl[4][0].xyz);
+
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][1].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][1].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][1].xyz);
+ VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[3][1].xyz);
+ VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[4][1].xyz);
+
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[0][2].xyz);
+ VectorCopy(pParent->ctrl[1][nIndex].xyz, p->ctrl[1][2].xyz);
+ VectorCopy(pParent->ctrl[2][nIndex].xyz, p->ctrl[2][2].xyz);
+ VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[3][2].xyz);
+ VectorCopy(pParent->ctrl[3][nIndex].xyz, p->ctrl[4][2].xyz);
+ }
+
+
+ bool bEndCap = (nType == CCapDialog::ENDCAP || nType == CCapDialog::IENDCAP);
+ if ((!bFirst && !bEndCap) || (bFirst && bEndCap))
+ {
+ drawVert_t vertTemp;
+ for (i = 0; i < p->width; i++)
+ {
+ for (j = 0; j < p->height / 2; j++)
+ {
+ memcpy(&vertTemp, &p->ctrl[i][p->height - 1- j], sizeof (drawVert_t));
+ memcpy(&p->ctrl[i][p->height - 1 - j], &p->ctrl[i][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[i][j], &vertTemp, sizeof(drawVert_t));
+ }
+ }
+ }
+
+ //--Patch_CalcBounds(p, vMin, vMax);
+ //--Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ Patch_Rebuild(p);
+ Patch_CapTexture(p);
+ return p->pSymbiot;
+}
+
+
+void Patch_CapCurrent(bool bInvertedBevel, bool bInvertedEndcap)
+{
+ patchMesh_t *pParent = NULL;
+ brush_t *b[4];
+ brush_t *pCap = NULL;
+ b[0] = b[1] = b[2] = b[3] = NULL;
+ int nIndex = 0;
+
+ if (!QE_SingleBrush())
+ {
+ Sys_Printf("Cannot cap multiple selection. Please select a single patch.\n");
+ return;
+ }
+
+
+ for (brush_t *pb = selected_brushes.next ; pb != NULL && pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ pParent = pb->pPatch;
+ // decide which if any ends we are going to cap
+ // if any of these compares hit, it is a closed patch and as such
+ // the generic capping will work.. if we do not find a closed edge
+ // then we need to ask which kind of cap to add
+ if (VectorCompare(pParent->ctrl[0][0].xyz, pParent->ctrl[pParent->width-1][0].xyz))
+ {
+ pCap = Cap(pParent, true, false);
+ if (pCap != NULL)
+ {
+ b[nIndex++] = pCap;
+ }
+ }
+ if (VectorCompare(pParent->ctrl[0][pParent->height-1].xyz, pParent->ctrl[pParent->width-1][pParent->height-1].xyz))
+ {
+ pCap = Cap(pParent, true, true);
+ if (pCap != NULL)
+ {
+ b[nIndex++] = pCap;
+ }
+ }
+ if (VectorCompare(pParent->ctrl[0][0].xyz, pParent->ctrl[0][pParent->height-1].xyz))
+ {
+ pCap = Cap(pParent, false, false);
+ if (pCap != NULL)
+ {
+ b[nIndex++] = pCap;
+ }
+ }
+ if (VectorCompare(pParent->ctrl[pParent->width-1][0].xyz, pParent->ctrl[pParent->width-1][pParent->height-1].xyz))
+ {
+ pCap = Cap(pParent, false, true);
+ if (pCap != NULL)
+ {
+ b[nIndex++] = pCap;
+ }
+ }
+ }
+ }
+
+ if (pParent)
+ {
+ // if we did not cap anything with the above tests
+ if (nIndex == 0)
+ {
+ CCapDialog dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ b[nIndex++] = CapSpecial(pParent, dlg.getCapType(), false);
+ b[nIndex++] = CapSpecial(pParent, dlg.getCapType(), true);
+ }
+ }
+
+ if (nIndex > 0)
+ {
+ while (nIndex > 0)
+ {
+ nIndex--;
+ if (b[nIndex])
+ {
+ Select_Brush(b[nIndex]);
+ }
+ }
+ eclass_t *pecNew = Eclass_ForName("func_group", false);
+ if (pecNew)
+ {
+ entity_t *e = Entity_Create(pecNew);
+ SetKeyValue(e, "type", "patchCapped");
+ }
+ }
+ }
+}
+
+
+//FIXME: Table drive all this crap
+//
+void GenerateEndCaps(brush_t *brushParent, bool bBevel, bool bEndcap, bool bInverted)
+{
+ brush_t *b, *b2;
+ patchMesh_t *p, *p2, *pParent;
+ vec3_t vTemp, vMin, vMax;
+ int i, j;
+
+ pParent = brushParent->pPatch;
+
+ Patch_CalcBounds(pParent, vMin, vMax);
+ // basically generate two endcaps, place them, and link the three brushes with a func_group
+
+ if (pParent->width > 9)
+ b = Patch_GenericMesh(5, 3, 2, false);
+ else
+ b = Patch_GenericMesh(3, 3, 2, false);
+ p = b->pPatch;
+
+ vMin[0] = vMin[1] = vMin[2] = 9999;
+ vMax[0] = vMax[1] = vMax[2] = -9999;
+
+ for (i = 0; i < pParent->width; i++)
+ {
+ VectorCopy(pParent->ctrl[i][0].xyz, p->ctrl[Index3By[i][0]][Index3By[i][1]].xyz);
+ for (j = 0; j < 3; j++)
+ {
+ if (pParent->ctrl[i][0].xyz[j] < vMin[j])
+ vMin[j] = pParent->ctrl[i][0].xyz[j];
+ if (pParent->ctrl[i][0].xyz[j] > vMax[j])
+ vMax[j] = pParent->ctrl[i][0].xyz[j];
+ }
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ vTemp[j] = vMin[j] + abs((vMax[j] - vMin[j]) * 0.5);
+ }
+
+ for (i = 0; i < Interior3ByCount; i++)
+ {
+ VectorCopy(vTemp, p->ctrl[Interior3By[i][0]][Interior3By[i][1]].xyz);
+ }
+
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ Select_Brush(p->pSymbiot);
+ return;
+
+ bool bCreated = false;
+
+ if (bInverted)
+ {
+ if (bBevel)
+ {
+ b = Patch_GenericMesh(3, 3, 2, false);
+ p = b->pPatch;
+ VectorCopy(p->ctrl[2][2].xyz, p->ctrl[1][2].xyz);
+ VectorCopy(p->ctrl[2][2].xyz, p->ctrl[2][1].xyz);
+ VectorCopy(p->ctrl[2][2].xyz, p->ctrl[0][1].xyz);
+ VectorCopy(p->ctrl[2][2].xyz, p->ctrl[1][0].xyz);
+ VectorCopy(p->ctrl[2][2].xyz, p->ctrl[1][1].xyz);
+ VectorCopy(p->ctrl[2][0].xyz, p->ctrl[0][0].xyz);
+
+ b2 = Patch_GenericMesh(3, 3, 2, false);
+ p2 = b2->pPatch;
+ VectorCopy(p2->ctrl[2][2].xyz, p2->ctrl[1][2].xyz);
+ VectorCopy(p2->ctrl[2][2].xyz, p2->ctrl[2][1].xyz);
+ VectorCopy(p2->ctrl[2][2].xyz, p2->ctrl[0][1].xyz);
+ VectorCopy(p2->ctrl[2][2].xyz, p2->ctrl[1][0].xyz);
+ VectorCopy(p2->ctrl[2][2].xyz, p2->ctrl[1][1].xyz);
+ VectorCopy(p2->ctrl[2][0].xyz, p2->ctrl[0][0].xyz);
+
+
+ bCreated = true;
+
+ }
+ else if (bEndcap)
+ {
+ b = Patch_GenericMesh(5, 5, 2, false);
+ p = b->pPatch;
+ VectorCopy(p->ctrl[4][4].xyz, p->ctrl[4][3].xyz);
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[1][4].xyz);
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[2][4].xyz);
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[3][4].xyz);
+
+ VectorCopy(p->ctrl[4][0].xyz, p->ctrl[4][1].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[1][0].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[2][0].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[3][0].xyz);
+
+ for (i = 1; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ VectorCopy(p->ctrl[4][i].xyz, p->ctrl[j][i].xyz);
+ }
+ }
+
+
+ b2 = Patch_GenericMesh(5, 5, 2, false);
+ p2 = b2->pPatch;
+ VectorCopy(p2->ctrl[4][4].xyz, p2->ctrl[4][3].xyz);
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[1][4].xyz);
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[2][4].xyz);
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[3][4].xyz);
+
+ VectorCopy(p2->ctrl[4][0].xyz, p2->ctrl[4][1].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[1][0].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[2][0].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[3][0].xyz);
+
+ for (i = 1; i < 4; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ VectorCopy(p2->ctrl[4][i].xyz, p2->ctrl[j][i].xyz);
+ }
+ }
+
+
+ bCreated = true;
+ }
+ }
+ else
+ {
+ if (bBevel)
+ {
+ b = Patch_GenericMesh(3, 3, 2, false);
+ p = b->pPatch;
+ VectorCopy(p->ctrl[2][0].xyz, p->ctrl[2][1].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[1][0].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[2][0].xyz);
+
+ b2 = Patch_GenericMesh(3, 3, 2, false);
+ p2 = b2->pPatch;
+ VectorCopy(p2->ctrl[2][0].xyz, p2->ctrl[2][1].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[1][0].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[2][0].xyz);
+ bCreated = true;
+ }
+ else if (bEndcap)
+ {
+ b = Patch_GenericMesh(5, 5, 2, false);
+ p = b->pPatch;
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[1][0].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[2][0].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[3][0].xyz);
+ VectorCopy(p->ctrl[4][0].xyz, p->ctrl[4][1].xyz);
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[4][0].xyz);
+
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[1][4].xyz);
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[2][4].xyz);
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[3][4].xyz);
+ VectorCopy(p->ctrl[4][4].xyz, p->ctrl[4][3].xyz);
+ VectorCopy(p->ctrl[0][4].xyz, p->ctrl[4][4].xyz);
+
+ b2 = Patch_GenericMesh(5, 5, 2, false);
+ p2 = b2->pPatch;
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[1][0].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[2][0].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[3][0].xyz);
+ VectorCopy(p2->ctrl[4][0].xyz, p2->ctrl[4][1].xyz);
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[4][0].xyz);
+
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[1][4].xyz);
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[2][4].xyz);
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[3][4].xyz);
+ VectorCopy(p2->ctrl[4][4].xyz, p2->ctrl[4][3].xyz);
+ VectorCopy(p2->ctrl[0][4].xyz, p2->ctrl[4][4].xyz);
+ bCreated = true;
+ }
+ else
+ {
+ b = Patch_GenericMesh(3, 3, 2, false);
+ p = b->pPatch;
+
+ VectorCopy(p->ctrl[0][1].xyz, vTemp);
+ VectorCopy(p->ctrl[0][2].xyz, p->ctrl[0][1].xyz)
+ VectorCopy(p->ctrl[1][2].xyz, p->ctrl[0][2].xyz)
+ VectorCopy(p->ctrl[2][2].xyz, p->ctrl[1][2].xyz)
+ VectorCopy(p->ctrl[2][1].xyz, p->ctrl[2][2].xyz)
+ VectorCopy(p->ctrl[2][0].xyz, p->ctrl[2][1].xyz)
+ VectorCopy(p->ctrl[1][0].xyz, p->ctrl[2][0].xyz)
+ VectorCopy(p->ctrl[0][0].xyz, p->ctrl[1][0].xyz)
+ VectorCopy(vTemp, p->ctrl[0][0].xyz)
+
+ b2 = Patch_GenericMesh(3, 3, 2, false);
+ p2 = b2->pPatch;
+ VectorCopy(p2->ctrl[0][1].xyz, vTemp);
+ VectorCopy(p2->ctrl[0][2].xyz, p2->ctrl[0][1].xyz)
+ VectorCopy(p2->ctrl[1][2].xyz, p2->ctrl[0][2].xyz)
+ VectorCopy(p2->ctrl[2][2].xyz, p2->ctrl[1][2].xyz)
+ VectorCopy(p2->ctrl[2][1].xyz, p2->ctrl[2][2].xyz)
+ VectorCopy(p2->ctrl[2][0].xyz, p2->ctrl[2][1].xyz)
+ VectorCopy(p2->ctrl[1][0].xyz, p2->ctrl[2][0].xyz)
+ VectorCopy(p2->ctrl[0][0].xyz, p2->ctrl[1][0].xyz)
+ VectorCopy(vTemp, p2->ctrl[0][0].xyz)
+ bCreated = true;
+ }
+ }
+
+ if (bCreated)
+ {
+ drawVert_t vertTemp;
+ for (i = 0; i < p->width; i++)
+ {
+ for (j = 0; j < p->height; j++)
+ {
+ p->ctrl[i][j].xyz[2] = vMin[2];
+ p2->ctrl[i][j].xyz[2] = vMax[2];
+ }
+
+ for (j = 0; j < p->height / 2; j++)
+ {
+ memcpy(&vertTemp, &p->ctrl[i][p->height - 1- j], sizeof (drawVert_t));
+ memcpy(&p->ctrl[i][p->height - 1 - j], &p->ctrl[i][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[i][j], &vertTemp, sizeof(drawVert_t));
+ }
+
+ }
+ //Select_Delete();
+
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ Patch_CalcBounds(p2, vMin, vMax);
+ Brush_RebuildBrush(p2->pSymbiot, vMin, vMax);
+ Select_Brush(p->pSymbiot);
+ Select_Brush(p2->pSymbiot);
+ }
+ else
+ {
+ Select_Delete();
+ }
+ //Select_Brush(brushParent);
+
+}
+
+
+/*
+===============
+BrushToPatchMesh
+===============
+*/
+void Patch_BrushToMesh(bool bCone, bool bBevel, bool bEndcap, bool bSquare, int nHeight)
+{
+ brush_t *b;
+ patchMesh_t *p;
+ int i,j;
+
+ if (!QE_SingleBrush())
+ return;
+
+ b = selected_brushes.next;
+
+ p = MakeNewPatch();
+
+ p->d_texture = b->brush_faces->d_texture;
+
+ p->height = nHeight;
+
+ p->type = PATCH_CYLINDER;
+ if (bBevel & !bSquare)
+ {
+ p->type = PATCH_BEVEL;
+ p->width = 3;
+ int nStep = (b->maxs[2] - b->mins[2]) / (p->height-1);
+ int nStart = b->mins[2];
+ for (i = 0; i < p->height; i++)
+ {
+ p->ctrl[0][i].xyz[0] = b->mins[0];
+ p->ctrl[0][i].xyz[1] = b->mins[1];
+ p->ctrl[0][i].xyz[2] = nStart;
+
+ p->ctrl[1][i].xyz[0] = b->maxs[0];
+ p->ctrl[1][i].xyz[1] = b->mins[1];
+ p->ctrl[1][i].xyz[2] = nStart;
+
+ p->ctrl[2][i].xyz[0] = b->maxs[0];
+ p->ctrl[2][i].xyz[1] = b->maxs[1];
+ p->ctrl[2][i].xyz[2] = nStart;
+ nStart += nStep;
+ }
+ }
+ else if (bEndcap & !bSquare)
+ {
+ p->type = PATCH_ENDCAP;
+ p->width = 5;
+ int nStep = (b->maxs[2] - b->mins[2]) / (p->height-1);
+ int nStart = b->mins[2];
+ for (i = 0; i < p->height; i++)
+ {
+ p->ctrl[0][i].xyz[0] = b->mins[0];
+ p->ctrl[0][i].xyz[1] = b->mins[1];
+ p->ctrl[0][i].xyz[2] = nStart;
+
+ p->ctrl[1][i].xyz[0] = b->mins[0];
+ p->ctrl[1][i].xyz[1] = b->maxs[1];
+ p->ctrl[1][i].xyz[2] = nStart;
+
+ p->ctrl[2][i].xyz[0] = b->mins[0] + ((b->maxs[0] - b->mins[0]) * 0.5);
+ p->ctrl[2][i].xyz[1] = b->maxs[1];
+ p->ctrl[2][i].xyz[2] = nStart;
+
+ p->ctrl[3][i].xyz[0] = b->maxs[0];
+ p->ctrl[3][i].xyz[1] = b->maxs[1];
+ p->ctrl[3][i].xyz[2] = nStart;
+
+ p->ctrl[4][i].xyz[0] = b->maxs[0];
+ p->ctrl[4][i].xyz[1] = b->mins[1];
+ p->ctrl[4][i].xyz[2] = nStart;
+ nStart += nStep;
+ }
+ }
+ else
+ {
+ p->width = 9;
+ p->ctrl[1][0].xyz[0] = b->mins[0];
+ p->ctrl[1][0].xyz[1] = b->mins[1];
+
+ p->ctrl[3][0].xyz[0] = b->maxs[0];
+ p->ctrl[3][0].xyz[1] = b->mins[1];
+
+ p->ctrl[5][0].xyz[0] = b->maxs[0];
+ p->ctrl[5][0].xyz[1] = b->maxs[1];
+
+ p->ctrl[7][0].xyz[0] = b->mins[0];
+ p->ctrl[7][0].xyz[1] = b->maxs[1];
+
+ for ( i = 1 ; i < p->width - 1 ; i += 2 )
+ {
+
+ p->ctrl[i][0].xyz[2] = b->mins[2];
+
+ VectorCopy( p->ctrl[i][0].xyz, p->ctrl[i][2].xyz );
+
+ p->ctrl[i][2].xyz[2] = b->maxs[2];
+
+ p->ctrl[i][1].xyz[0] = ( p->ctrl[i][0].xyz[0] + p->ctrl[i][2].xyz[0] ) * 0.5;
+ p->ctrl[i][1].xyz[1] = ( p->ctrl[i][0].xyz[1] + p->ctrl[i][2].xyz[1] ) * 0.5;
+ p->ctrl[i][1].xyz[2] = ( p->ctrl[i][0].xyz[2] + p->ctrl[i][2].xyz[2] ) * 0.5;
+ }
+ InterpolateInteriorPoints( p );
+
+ if (bSquare)
+ {
+ if (bBevel || bEndcap)
+ {
+ if (bBevel)
+ {
+ for (i = 0; i < p->height; i++)
+ {
+ VectorCopy(p->ctrl[1][i].xyz, p->ctrl[2][i].xyz);
+ VectorCopy(p->ctrl[7][i].xyz, p->ctrl[6][i].xyz);
+ }
+ }
+ else
+ {
+ for (i = 0; i < p->height; i++)
+ {
+ VectorCopy(p->ctrl[5][i].xyz, p->ctrl[4][i].xyz);
+ VectorCopy(p->ctrl[1][i].xyz, p->ctrl[2][i].xyz);
+ VectorCopy(p->ctrl[7][i].xyz, p->ctrl[6][i].xyz);
+ VectorCopy(p->ctrl[8][i].xyz, p->ctrl[7][i].xyz);
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < p->width-1; i ++)
+ {
+ for (j = 0; j < p->height; j++)
+ {
+ VectorCopy(p->ctrl[i+1][j].xyz, p->ctrl[i][j].xyz);
+ }
+ }
+ for (j = 0; j < p->height; j++)
+ {
+ VectorCopy(p->ctrl[0][j].xyz, p->ctrl[8][j].xyz);
+ }
+ }
+ }
+ }
+
+
+ Patch_Naturalize(p);
+
+ if (bCone)
+ {
+ p->type = PATCH_CONE;
+ float xc = (b->maxs[0] + b->mins[0]) * 0.5;
+ float yc = (b->maxs[1] + b->mins[1]) * 0.5;
+
+ for ( i = 0 ; i < p->width ; i ++)
+ {
+ p->ctrl[i][2].xyz[0] = xc;
+ p->ctrl[i][2].xyz[1] = yc;
+ }
+ }
+/*
+ if (bEndcap || bBevel)
+ {
+ if (bInverted)
+ {
+ for ( i = 0 ; i < p->height ; i ++)
+ {
+ if (bBevel)
+ {
+ VectorCopy(p->ctrl[7][i], p->ctrl[0][i]);
+ VectorCopy(p->ctrl[7][i], p->ctrl[8][i]);
+ VectorCopy(p->ctrl[3][i], p->ctrl[2][i]);
+ VectorCopy(p->ctrl[5][i], p->ctrl[1][i]);
+ VectorCopy(p->ctrl[5][i], p->ctrl[4][i]);
+ VectorCopy(p->ctrl[5][i], p->ctrl[6][i]);
+ }
+ else
+ {
+ VectorCopy(p->ctrl[4][i], p->ctrl[8][i]);
+ VectorCopy(p->ctrl[1][i], p->ctrl[0][i]);
+ VectorCopy(p->ctrl[1][i], p->ctrl[10][i]);
+ VectorCopy(p->ctrl[3][i], p->ctrl[2][i]);
+ VectorCopy(p->ctrl[5][i], p->ctrl[4][i]);
+ VectorCopy(p->ctrl[7][i], p->ctrl[6][i]);
+ VectorCopy(p->ctrl[5][i], p->ctrl[7][i]);
+ VectorCopy(p->ctrl[3][i], p->ctrl[9][i]);
+ }
+ }
+ }
+ else
+ {
+ for ( i = 0 ; i < p->height ; i ++)
+ {
+ VectorCopy(p->ctrl[1][i], p->ctrl[2][i]);
+ VectorCopy(p->ctrl[7][i], p->ctrl[6][i]);
+ if (bBevel)
+ {
+ VectorCopy(p->ctrl[5][i], p->ctrl[4][i]);
+ }
+ }
+ }
+ }
+*/
+
+ b = AddBrushForPatch(p);
+
+
+#if 1
+ Select_Delete();
+ Select_Brush(b);
+#else
+ if (!bCone)
+ {
+ Select_Delete();
+ Select_Brush(b);
+ GenerateEndCaps(b, bBevel, bEndcap, bInverted);
+ eclass_t *pecNew = Eclass_ForName("func_group", false);
+ if (pecNew)
+ {
+ Entity_Create(pecNew);
+ }
+ }
+ else
+ {
+ Select_Delete();
+ Select_Brush(b);
+ }
+#endif
+
+}
+
+/*
+==================
+Patch_GenericMesh
+==================
+*/
+brush_t* Patch_GenericMesh(int nWidth, int nHeight, int nOrientation, bool bDeleteSource, bool bOverride)
+{
+ int i,j;
+
+ if (nHeight < 3 || nHeight > 15 || nWidth < 3 || nWidth > 15)
+ {
+ Sys_Printf("Invalid patch width or height.\n");
+ return NULL;
+ }
+
+ if (! bOverride && !QE_SingleBrush())
+ {
+ Sys_Printf("Cannot generate a patch from multiple selections.\n");
+ return NULL;
+ }
+
+
+
+ patchMesh_t* p = MakeNewPatch();
+ p->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
+
+ p->width = nWidth;
+ p->height = nHeight;
+ p->type = PATCH_GENERIC;
+
+ int nFirst = 0;
+ int nSecond = 1;
+ if (nOrientation == 0)
+ {
+ nFirst = 1;
+ nSecond = 2;
+ }
+ else if (nOrientation == 1)
+ {
+ nSecond = 2;
+ }
+
+ brush_t *b = selected_brushes.next;
+
+ int xStep = b->mins[nFirst];
+ float xAdj = abs((b->maxs[nFirst] - b->mins[nFirst]) / (nWidth - 1));
+ float yAdj = abs((b->maxs[nSecond] - b->mins[nSecond]) / (nHeight - 1));
+
+ for (i = 0; i < nWidth; i++)
+ {
+ int yStep = b->mins[nSecond];
+ for (j = 0; j < nHeight; j++)
+ {
+ p->ctrl[i][j].xyz[nFirst] = xStep;
+ p->ctrl[i][j].xyz[nSecond] = yStep;
+ p->ctrl[i][j].xyz[nOrientation] = 0;
+ yStep += yAdj;
+ }
+ xStep += xAdj;
+ }
+
+ Patch_Naturalize(p);
+
+ b = AddBrushForPatch(p);
+ if (bDeleteSource)
+ {
+ Select_Delete();
+ Select_Brush(b);
+ }
+
+ return b;
+ //g_qeglobals.d_select_mode = sel_curvepoint;
+}
+
+/*
+==================
+PointInMoveList
+==================
+*/
+int PointInMoveList(float *pf)
+{
+ for (int i = 0; i < g_qeglobals.d_num_move_points; i++)
+ {
+ if (pf == &g_qeglobals.d_move_points[i][0])
+ return i;
+ }
+ return -1;
+}
+
+/*
+==================
+PointValueInMoveList
+==================
+*/
+int PointValueInMoveList(vec3_t v)
+{
+ for (int i = 0; i < g_qeglobals.d_num_move_points; i++)
+ {
+ if (VectorCompare(v, g_qeglobals.d_move_points[i]))
+ return i;
+ }
+ return -1;
+}
+
+
+/*
+==================
+RemovePointFromMoveList
+==================
+*/
+void RemovePointFromMoveList(vec3_t v)
+{
+ int n;
+ while ( (n = PointValueInMoveList(v)) >= 0)
+ {
+ for (int i = n; i < g_qeglobals.d_num_move_points-1; i++)
+ {
+ g_qeglobals.d_move_points[i] = g_qeglobals.d_move_points[i+1];
+ }
+ g_qeglobals.d_num_move_points--;
+ }
+}
+
+/*
+==================
+ColumnSelected
+==================
+*/
+bool ColumnSelected(patchMesh_t* p, int nCol)
+{
+ for (int i = 0; i < p->height; i++)
+ {
+ if (PointInMoveList(p->ctrl[nCol][i].xyz) == -1)
+ return false;
+ }
+ return true;
+}
+
+/*
+==================
+AddPoint
+==================
+*/
+void AddPoint(patchMesh_t* p, vec3_t v, bool bWeldOrDrill = true)
+{
+ int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
+ int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = v;
+ if ((g_bPatchWeld || g_bPatchDrillDown) && bWeldOrDrill)
+ {
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ if (g_bPatchWeld)
+ {
+ if ( VectorCompare(v, p->ctrl[i][j].xyz)
+ && PointInMoveList(p->ctrl[i][j].xyz) == -1)
+ {
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = p->ctrl[i][j].xyz;
+ continue;
+ }
+ }
+ if (g_bPatchDrillDown && g_nPatchClickedView != W_CAMERA)
+ {
+ if ( (fabs(v[nDim1] - p->ctrl[i][j].xyz[nDim1]) <= EQUAL_EPSILON)
+ &&(fabs(v[nDim2] - p->ctrl[i][j].xyz[nDim2]) <= EQUAL_EPSILON))
+ {
+ if (PointInMoveList(p->ctrl[i][j].xyz) == -1)
+ {
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = p->ctrl[i][j].xyz;
+ continue;
+ }
+ }
+#if 0
+ int l = 0;
+ for ( int k = 0; k < 2; k++ )
+ {
+ if (fabs(v[k] - p->ctrl[i][j].xyz[k]) > EQUAL_EPSILON)
+ continue;
+ l++;
+ }
+ if (l >= 2 && PointInMoveList(p->ctrl[i][j].xyz) == -1)
+ {
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = p->ctrl[i][j].xyz;
+ continue;
+ }
+#endif
+ }
+ }
+ }
+ }
+#if 0
+ if (g_qeglobals.d_num_move_points == 1)
+ {
+ // single point selected
+ // FIXME: the two loops can probably be reduced to one
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ int n = PointInMoveList(v);
+ if (n >= 0)
+ {
+ if (((i & 0x01) && (j & 0x01)) == 0)
+ {
+ // put any sibling fixed points
+ // into the inverse list
+ int p1, p2, p3, p4;
+ p1 = i + 2;
+ p2 = i - 2;
+ p3 = j + 2;
+ p4 = j - 2;
+ if (p1 < p->width)
+ {
+
+ }
+ if (p2 >= 0)
+ {
+ }
+ if (p3 < p->height)
+ {
+ }
+ if (p4 >= 0)
+ {
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+}
+
+/*
+==================
+SelectRow
+==================
+*/
+void SelectRow(patchMesh_t* p, int nRow, bool bMulti)
+{
+ if (!bMulti)
+ g_qeglobals.d_num_move_points = 0;
+ for (int i = 0; i < p->width; i++)
+ {
+ AddPoint(p, p->ctrl[i][nRow].xyz, false);
+ }
+ //Sys_Printf("Selected Row %d\n", nRow);
+}
+
+/*
+==================
+SelectColumn
+==================
+*/
+void SelectColumn(patchMesh_t* p, int nCol, bool bMulti)
+{
+ if (!bMulti)
+ g_qeglobals.d_num_move_points = 0;
+ for (int i = 0; i < p->height; i++)
+ {
+ AddPoint(p, p->ctrl[nCol][i].xyz, false);
+ }
+ //Sys_Printf("Selected Col %d\n", nCol);
+}
+
+
+/*
+==================
+AddPatchMovePoint
+==================
+*/
+void AddPatchMovePoint(vec3_t v, bool bMulti, bool bFull)
+{
+ if (!g_bSameView && !bMulti && !bFull)
+ {
+ g_bSameView = true;
+ return;
+ }
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t* p = pb->pPatch;
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ if (VectorCompare(v, p->ctrl[i][j].xyz))
+ {
+ if (PointInMoveList(p->ctrl[i][j].xyz) == -1)
+ {
+ if (bFull) // if we want the full row/col this is on
+ {
+ SelectColumn(p, i, bMulti);
+ }
+ else
+ {
+ if (!bMulti)
+ g_qeglobals.d_num_move_points = 0;
+ AddPoint(p, p->ctrl[i][j].xyz);
+ //Sys_Printf("Selected col:row %d:%d\n", i, j);
+ }
+ //--if (!bMulti)
+ return;
+ }
+ else
+ {
+ if (bFull)
+ {
+ if (ColumnSelected(p, i))
+ {
+ SelectRow(p, j, bMulti);
+ }
+ else
+ {
+ SelectColumn(p, i, bMulti);
+ }
+ return;
+ }
+ if (g_bSameView)
+ {
+ RemovePointFromMoveList(v);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+==================
+Patch_UpdateSelected
+==================
+*/
+void Patch_UpdateSelected(vec3_t vMove)
+{
+ int i, j;
+ for (i=0 ; i < g_qeglobals.d_num_move_points ; i++)
+ {
+ VectorAdd (g_qeglobals.d_move_points[i], vMove, g_qeglobals.d_move_points[i]);
+ if (g_qeglobals.d_num_move_points == 1)
+ {
+ }
+ }
+
+ //--patchMesh_t* p = &patchMeshes[g_nSelectedPatch];
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t* p = pb->pPatch;
+
+
+ g_qeglobals.d_numpoints = 0;
+ for (i = 0 ; i < p->width ; i++ )
+ {
+ for ( j = 0 ; j < p->height ; j++ )
+ {
+ VectorCopy (p->ctrl[i][j].xyz, g_qeglobals.d_points[g_qeglobals.d_numpoints]);
+ if (g_qeglobals.d_numpoints < MAX_POINTS-1)
+ {
+ g_qeglobals.d_numpoints++;
+ }
+ }
+ }
+
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ }
+ }
+ //Brush_Free(p->pSymbiot);
+ //Select_Brush(AddBrushForPatch(g_nSelectedPatch));
+}
+
+
+
+/*
+===============
+SampleSinglePatch
+===============
+*/
+void SampleSinglePatch (float ctrl[3][3][5], float u, float v, float out[5]) {
+ float vCtrl[3][5];
+ int vPoint;
+ int axis;
+
+ // find the control points for the v coordinate
+ for (vPoint = 0 ; vPoint < 3 ; vPoint++)
+ {
+ for (axis = 0 ; axis < 5 ; axis++)
+ {
+ float a, b, c;
+ float qA, qB, qC;
+
+ a = ctrl[0][vPoint][axis];
+ b = ctrl[1][vPoint][axis];
+ c = ctrl[2][vPoint][axis];
+ qA = a - 2 * b + c;
+ qB = 2 * b - 2 * a;
+ qC = a;
+
+ vCtrl[vPoint][axis] = qA * u * u + qB * u + qC;
+ }
+ }
+
+ // interpolate the v value
+ for (axis = 0 ; axis < 5 ; axis++)
+ {
+ float a, b, c;
+ float qA, qB, qC;
+
+ a = vCtrl[0][axis];
+ b = vCtrl[1][axis];
+ c = vCtrl[2][axis];
+ qA = a - 2 * b + c;
+ qB = 2 * b - 2 * a;
+ qC = a;
+
+ out[axis] = qA * v * v + qB * v + qC;
+ }
+}
+
+/*
+===================
+DrawSinglePatch
+===================
+*/
+void DrawSinglePatch (float ctrl[3][3][5], bool bPoints)
+{
+ int i, j;
+ float u, v;
+ float verts[CBLOCK_SUBDIVISIONS+1][CBLOCK_SUBDIVISIONS+1][5];
+
+ for (i = 0 ; i <= CBLOCK_SUBDIVISIONS ; i++)
+ {
+ for (j = 0 ; j <= CBLOCK_SUBDIVISIONS ; j++)
+ {
+ u = (float)i / CBLOCK_SUBDIVISIONS;
+ v = (float)j / CBLOCK_SUBDIVISIONS;
+ SampleSinglePatch (ctrl, u, v, verts[i][j]);
+ }
+ }
+ // at this point we have
+
+ int nCount = -1;
+ for (i = 0 ; i < CBLOCK_SUBDIVISIONS ; i++)
+ {
+ qglBegin (GL_QUAD_STRIP);
+
+ for (j = 0 ; j <= CBLOCK_SUBDIVISIONS ; j++)
+ {
+ qglTexCoord2fv( verts[i+1][j] + 3 );
+ qglVertex3fv( verts[i+1][j] );
+/*
+ if (nCount >= 0)
+ {
+ VectorCopy(verts[i+1][j], vNormals[nCount]);
+ }
+ nCount++;
+ if (nCount == 3)
+ {
+ VectorSubtract(vNormals[0], vNormals[1], vNormals[0]);
+ VectorSubtract(vNormals[1], vNormals[2], vNormals[1]);
+ CrossProduct(vNormals[0], vNormals[1], vNormals[2]);
+ //VectorNormalize(vNormals[2]);
+ qglNormal3fv(vNormals[2]);
+ nCount = -1;
+ }
+*/
+ qglTexCoord2fv( verts[i][j] + 3 );
+ qglVertex3fv( verts[i][j] );
+/*
+ VectorCopy(verts[i][j], vNormals[nCount]);
+ nCount++;
+ if (nCount == 3)
+ {
+ VectorSubtract(vNormals[0], vNormals[1], vNormals[0]);
+ VectorSubtract(vNormals[1], vNormals[2], vNormals[1]);
+ CrossProduct(vNormals[0], vNormals[1], vNormals[2]);
+ //VectorNormalize(vNormals[2]);
+ qglNormal3fv(vNormals[2]);
+ nCount = -1;
+ }
+*/
+ }
+ qglEnd ();
+ }
+
+}
+
+/*
+=================
+DrawPatchMesh
+=================
+*/
+//FIXME: this routine needs to be reorganized.. should be about 1/4 the size and complexity
+void DrawPatchMesh( patchMesh_t *pm, bool bPoints, bool bShade = false ) {
+ int i, j, k, l;
+ float ctrl[3][3][5];
+
+ bool bOverlay = pm->bOverlay;
+ int nDrawMode = g_pParentWnd->GetCamera()->Camera().draw_mode;
+
+ //--float fColor[3];
+ //--if (bShade)
+ //--{
+ //-- face_t *f = pm->pSymbiot->brush_faces;
+ //-- _SetColor(f, fColor);
+ //--}
+ if (g_PrefsDlg.m_bDisplayLists)
+ {
+ if (pm->bDirty || pm->nListID <= 0)
+ {
+ if (pm->nListID <= 0)
+ pm->nListID = qglGenLists(1);
+ if (pm->nListID > 0)
+ {
+ qglNewList(pm->nListID, GL_COMPILE_AND_EXECUTE);
+ }
+
+
+
+ if (pm->type != PATCH_TRIANGLE)
+ {
+ //vec3_t *vMeshData = new vec3_t[pm->width * pm->height];
+
+ // wasteful
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ Patch_MeshNormals(pm);
+ for (i = 0; i < pm->width; i++)
+ {
+ for (j = 0; j < pm->height; j++)
+ {
+ //VectorCopy(pm->ctrl[i][j].xyz, vMeshData[(j * pm->width) + i]);
+ qglNormal3fv(pm->ctrl[i][j].normal);
+ }
+ }
+ }
+
+ for ( i = 0 ; i + 2 < pm->width ; i += 2 )
+ {
+ for ( j = 0 ; j + 2 < pm->height ; j += 2 )
+ {
+
+ for ( k = 0 ; k < 3 ; k++ )
+ {
+ vec3_t vAvg;
+ vAvg[0] = vAvg[1] = vAvg[2] = 0;
+ for ( l = 0 ; l < 3 ; l++ )
+ {
+ ctrl[k][l][0] = pm->ctrl[ i + k ][ j + l ].xyz[ 0 ];
+ ctrl[k][l][1] = pm->ctrl[ i + k ][ j + l ].xyz[ 1 ];
+ ctrl[k][l][2] = pm->ctrl[ i + k ][ j + l ].xyz[ 2 ];
+ ctrl[k][l][3] = pm->ctrl[ i + k ][ j + l ].xyz[ 3 ];
+ ctrl[k][l][4] = pm->ctrl[ i + k ][ j + l ].xyz[ 4 ];
+
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglNormal3fv(pm->ctrl[i+k][j+l].normal);
+ }
+ }
+
+ }
+
+//-- if (g_pParentWnd->GetCamera()->Camera().draw_mode == cd_texture)
+//-- {
+//-- VectorCopy(pm->ctrl[i][j].normal, plane.normal);
+//-- float shade = SetShadeForPlane(&plane);
+//-- qtexture_t *q = pm->d_texture;
+//-- vec3_t vColor;
+//--
+//-- vColor[0] = shade;// * q->color[0];
+//-- vColor[1] = shade;// * q->color[1];
+//-- vColor[2] = shade;// * q->color[2];
+//-- qglColor3fv(vColor);
+//-- }
+
+
+//-- if (g_PrefsDlg.m_bGLLighting)
+//-- {
+//-- //qglNormal3fv(pm->ctrl[i][j].normal);
+//-- }
+ DrawSinglePatch( ctrl, bPoints );
+ }
+ }
+
+ // we have an array of clean control points
+ //
+ /*
+ qglMap2f(GL_MAP2_NORMAL, 0, 1, 3, 3, 0, 1, 9, 3, (float*)&vMeshData);
+ for (i = 0; i < pm->width; i++)
+ {
+ for (j = 0; j < pm->height; j++)
+ {
+ qglEvalPoint2(i, j);
+ }
+ }
+
+ delete []vMeshData;
+ */
+ }
+ else
+ {
+ qglBegin (GL_TRIANGLES);
+ qglTexCoord2fv( pm->ctrl[0][0].st);
+ qglVertex3fv( pm->ctrl[0][0].xyz);
+ qglTexCoord2fv( pm->ctrl[2][0].st);
+ qglVertex3fv( pm->ctrl[2][0].xyz);
+ qglTexCoord2fv( pm->ctrl[2][2].st);
+ qglVertex3fv( pm->ctrl[2][2].xyz);
+ qglEnd();
+ }
+
+ if (pm->nListID > 0)
+ {
+ qglEndList();
+ pm->bDirty = false;
+ }
+ }
+ else
+ {
+ qglCallList(pm->nListID);
+ }
+ }
+ else
+ {
+ for ( i = 0 ; i + 2 < pm->width ; i += 2 )
+ {
+ for ( j = 0 ; j + 2 < pm->height ; j += 2 )
+ {
+ for ( k = 0 ; k < 3 ; k++ )
+ {
+ for ( l = 0 ; l < 3 ; l++ )
+ {
+ ctrl[k][l][0] = pm->ctrl[ i + k ][ j + l ].xyz[ 0 ];
+ ctrl[k][l][1] = pm->ctrl[ i + k ][ j + l ].xyz[ 1 ];
+ ctrl[k][l][2] = pm->ctrl[ i + k ][ j + l ].xyz[ 2 ];
+ ctrl[k][l][3] = pm->ctrl[ i + k ][ j + l ].xyz[ 3 ];
+ ctrl[k][l][4] = pm->ctrl[ i + k ][ j + l ].xyz[ 4 ];
+ }
+ }
+ //--if (bShade)
+ //--{
+ //-- _DecColor(fColor);
+ //--}
+ DrawSinglePatch( ctrl, bPoints );
+ }
+ }
+ }
+
+ vec3_t* pSelectedPoints[256];
+ int nIndex = 0;
+
+ qglPushAttrib(GL_CURRENT_BIT);
+ //--qglDisable(GL_BLEND);
+ //--qglDisable (GL_DEPTH_TEST);
+ //qglDisable (GL_TEXTURE_2D);
+
+ bool bDisabledLighting = qglIsEnabled(GL_LIGHTING);
+ if (bDisabledLighting)
+ {
+ qglDisable(GL_LIGHTING);
+ }
+
+
+ // FIXME: this bend painting code needs to be rolled up significantly as it is a cluster fuck right now
+ if (bPoints && (g_qeglobals.d_select_mode == sel_curvepoint || g_qeglobals.d_select_mode == sel_area || g_bPatchBendMode || g_bPatchInsertMode))
+ {
+ bOverlay = false;
+
+ // bending or inserting
+ if (g_bPatchBendMode || g_bPatchInsertMode)
+ {
+ qglPointSize(6);
+ if (g_bPatchAxisOnRow)
+ {
+ qglColor3f(1, 0, 1);
+ qglBegin(GL_POINTS);
+ for (i = 0; i < pm->width; i++)
+ {
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[i][g_nPatchAxisIndex].xyz));
+ }
+ qglEnd();
+
+ // could do all of this in one loop but it was pretty messy
+ if (g_bPatchInsertMode)
+ {
+ qglColor3f(0, 0, 1);
+ qglBegin(GL_POINTS);
+ for (i = 0; i < pm->width; i++)
+ {
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[i][g_nPatchAxisIndex].xyz));
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[i][g_nPatchAxisIndex+1].xyz));
+ }
+ qglEnd();
+ }
+ else
+ {
+ if (g_nPatchBendState == BEND_SELECT_EDGE || g_nPatchBendState == BEND_BENDIT || g_nPatchBendState == BEND_SELECT_ORIGIN)
+ {
+ qglColor3f(0, 0, 1);
+ qglBegin(GL_POINTS);
+ if (g_nPatchBendState == BEND_SELECT_ORIGIN)
+ {
+ qglVertex3fv(g_vBendOrigin);
+ }
+ else
+ {
+ for (i = 0; i < pm->width; i++)
+ {
+ if (g_bPatchLowerEdge)
+ {
+ for (j = 0; j < g_nPatchAxisIndex; j++)
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[i][j].xyz));
+ }
+ else
+ {
+ for (j = pm->height-1; j > g_nPatchAxisIndex; j--)
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[i][j].xyz));
+ }
+ }
+ }
+ qglEnd();
+ }
+ }
+ }
+ else
+ {
+ qglColor3f(1, 0, 1);
+ qglBegin(GL_POINTS);
+ for (i = 0; i < pm->height; i++)
+ {
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[g_nPatchAxisIndex][i].xyz));
+ }
+ qglEnd();
+
+ // could do all of this in one loop but it was pretty messy
+ if (g_bPatchInsertMode)
+ {
+ qglColor3f(0, 0, 1);
+ qglBegin(GL_POINTS);
+ for (i = 0; i < pm->height; i++)
+ {
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[g_nPatchAxisIndex][i].xyz));
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[g_nPatchAxisIndex+1][i].xyz));
+ }
+ qglEnd();
+ }
+ else
+ {
+ if (g_nPatchBendState == BEND_SELECT_EDGE || g_nPatchBendState == BEND_BENDIT || g_nPatchBendState == BEND_SELECT_ORIGIN)
+ {
+ qglColor3f(0, 0, 1);
+ qglBegin(GL_POINTS);
+ for (i = 0; i < pm->height; i++)
+ {
+ if (g_nPatchBendState == BEND_SELECT_ORIGIN)
+ {
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[g_nBendOriginIndex][i].xyz));
+ }
+ else
+ {
+ if (g_bPatchLowerEdge)
+ {
+ for (j = 0; j < g_nPatchAxisIndex; j++)
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[j][i].xyz));
+ }
+ else
+ {
+ for (j = pm->width-1; j > g_nPatchAxisIndex; j--)
+ qglVertex3fv(reinterpret_cast<float(*)>(&pm->ctrl[j][i].xyz));
+ }
+ }
+ }
+ qglEnd();
+ }
+ }
+ }
+ }
+ else // just painting the grid for selection
+ {
+ qglPointSize(6);
+ for ( i = 0 ; i < pm->width ; i++ )
+ {
+ for ( j = 0 ; j < pm->height ; j++ )
+ {
+ qglBegin(GL_POINTS);
+ // FIXME: need to not do loop lookups inside here
+ int n = PointValueInMoveList(pm->ctrl[i][j].xyz);
+ if (n >= 0)
+ {
+ pSelectedPoints[nIndex++] = reinterpret_cast<float(*)[3]>(&pm->ctrl[i][j].xyz);
+ }
+
+ if (i & 0x01 || j & 0x01)
+ qglColor3f(1, 0, 1);
+ else
+ qglColor3f(0, 1, 0);
+ qglVertex3fv(pm->ctrl[i][j].xyz);
+ qglEnd();
+ }
+ }
+ }
+ if (nIndex > 0)
+ {
+ qglBegin(GL_POINTS);
+ qglColor3f(0, 0, 1);
+ while (nIndex-- > 0)
+ {
+ qglVertex3fv(*pSelectedPoints[nIndex]);
+ }
+ qglEnd();
+ }
+ }
+
+ if (bOverlay)
+ {
+ qglPointSize(6);
+ qglColor3f(0.5, 0.5, 0.5);
+ for ( i = 0 ; i < pm->width ; i++ )
+ {
+ qglBegin(GL_POINTS);
+ for ( j = 0 ; j < pm->height ; j++ )
+ {
+ if (i & 0x01 || j & 0x01)
+ qglColor3f(0.5, 0, 0.5);
+ else
+ qglColor3f(0, 0.5, 0);
+ qglVertex3fv(pm->ctrl[i][j].xyz);
+ }
+ qglEnd();
+ }
+ }
+ //--qglEnable (GL_TEXTURE_2D);
+ //--qglEnable (GL_DEPTH_TEST);
+
+ if (bDisabledLighting)
+ {
+ qglEnable(GL_LIGHTING);
+ }
+
+ qglPopAttrib();
+
+}
+
+/*
+==================
+Patch_DrawXY
+==================
+*/
+void Patch_DrawXY(patchMesh_t *pm)
+{
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ if (pm->bSelected)
+ {
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
+ //qglDisable (GL_LINE_STIPPLE);
+ //qglLineWidth (1);
+ }
+ else
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
+
+ DrawPatchMesh( pm , pm->bSelected );
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ if (pm->bSelected)
+ {
+ //qglLineWidth (2);
+ //qglEnable (GL_LINE_STIPPLE);
+ }
+}
+
+/*
+==================
+Patch_DrawCam
+==================
+*/
+void Patch_DrawCam(patchMesh_t *pm)
+{
+ qglColor3f (1,1,1);
+ qglPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ if (g_bPatchWireFrame)
+ {
+ qglDisable( GL_CULL_FACE );
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+ qglDisable(GL_TEXTURE_2D);
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglDisable(GL_LIGHTING);
+ }
+ DrawPatchMesh( pm , pm->bSelected, true );
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ qglEnable(GL_LIGHTING);
+ }
+ qglEnable( GL_CULL_FACE );
+ }
+ else
+ {
+ if (g_PrefsDlg.m_bGLLighting)
+ {
+ //qglEnable(GL_NORMALIZE);
+ }
+ qglEnable( GL_CULL_FACE );
+ qglCullFace(GL_FRONT);
+ qglBindTexture (GL_TEXTURE_2D, pm->d_texture->texture_number);
+
+ if (pm->d_texture->bFromShader && pm->d_texture->fTrans < 1.0)
+ {
+ //qglEnable ( GL_BLEND );
+ //qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglColor4f(pm->d_texture->color[0], pm->d_texture->color[1], pm->d_texture->color[2], pm->d_texture->fTrans);
+ }
+ DrawPatchMesh( pm , pm->bSelected, true );
+
+ qglCullFace(GL_BACK);
+ //qglDisable(GL_TEXTURE_2D);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+
+ qglDisable ( GL_BLEND );
+ DrawPatchMesh( pm , pm->bSelected, true );
+ }
+
+#if 0 // this paints normal indicators on the ctrl points
+ //--qglDisable (GL_DEPTH_TEST);
+ qglDisable (GL_TEXTURE_2D);
+ qglColor3f (1,1,1);
+
+ for (int i = 0; i < pm->width; i++)
+ {
+ for (int j = 0; j < pm->height; j++)
+ {
+ vec3_t temp;
+ qglBegin (GL_LINES);
+ qglVertex3fv (pm->ctrl[i][j].xyz);
+ VectorMA (pm->ctrl[i][j].xyz, 8, pm->ctrl[i][j].normal, temp);
+ qglVertex3fv (temp);
+ qglEnd ();
+ }
+ }
+ qglEnable (GL_TEXTURE_2D);
+ //--qglEnable (GL_DEPTH_TEST);
+#endif
+
+
+ qglPopAttrib();
+}
+
+
+
+
+void ConvexHullForSection( float section[2][4][7] ) {
+}
+
+void BrushesForSection( float section[2][4][7] ) {
+}
+
+//
+//================
+//Patch_BuildPoints
+//================
+void Patch_BuildPoints (brush_t *b)
+{
+ face_t *f;
+ b->patchBrush = false;
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ if (f->texdef.flags & SURF_PATCH)
+ {
+ b->patchBrush = true;
+ //vec3_t vMin, vMax;
+ //Patch_CalcBounds(&patchMeshes[b->nPatchID], vMin, vMax);
+ //VectorCopy(vMin, b->mins);
+ //VectorCopy(vMax, b->maxs);
+ break;
+ }
+ }
+}
+
+
+
+//
+//===============
+//Patch_WriteFile
+//===============
+//
+#if 0
+void Patch_WriteFile (char *name)
+{
+ char patchName[1024];
+ time_t ltime;
+ strcpy(patchName, name);
+ StripExtension (patchName);
+ strcat (patchName, ".patch");
+
+ FILE *file = fopen(patchName, "w");
+ if (file)
+ {
+ time(&ltime);
+ fprintf (file, "// %s saved on %s\n", name, ctime(&ltime) );
+
+ for (int i = 0; i < numPatchMeshes; i++)
+ {
+ fprintf(file, "{\n");
+ fprintf(file, " %s\n", patchMeshes[i].d_texture->name);
+ fprintf(file, " ( %i %i %i ) \n", patchMeshes[i].width, patchMeshes[i].height, patchMeshes[i].negative);
+ for (int w = 0; w < patchMeshes[i].width; w++)
+ {
+ for (int h = 0; h < patchMeshes[i].height; h++)
+ {
+ fprintf(file, " ( ");
+ for (int k = 0; k < 5; k++)
+ {
+ float f = patchMeshes[i].ctrl[w][h][k];
+ if (f == int(f))
+ fprintf(file, "%i ", (int)f);
+ else
+ fprintf(file, "%f ", f);
+ }
+ fprintf(file, ")\n");
+ }
+ }
+ fprintf(file, "}\n");
+ }
+ fclose(file);
+ }
+}
+#endif
+
+/*
+==================
+Patch_Move
+==================
+*/
+void Patch_Move(patchMesh_t *pm, const vec3_t vMove, bool bRebuild)
+{
+ pm->bDirty = true;
+ for (int w = 0; w < pm->width; w++)
+ {
+ for (int h = 0; h < pm->height; h++)
+ {
+ VectorAdd(pm->ctrl[w][h].xyz, vMove, pm->ctrl[w][h].xyz);
+ }
+ }
+ if (bRebuild)
+ {
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(pm, vMin, vMax);
+ //Brush_RebuildBrush(patchMeshes[n].pSymbiot, vMin, vMax);
+ }
+ UpdatePatchInspector();
+
+}
+
+/*
+==================
+Patch_ApplyMatrix
+==================
+*/
+void Patch_ApplyMatrix(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[3], bool bSnap)
+{
+ vec3_t vTemp;
+
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ if ( (g_qeglobals.d_select_mode == sel_curvepoint || g_bPatchBendMode)
+ && PointInMoveList(p->ctrl[w][h].xyz) == -1)
+ continue;
+ VectorSubtract (p->ctrl[w][h].xyz, vOrigin, vTemp);
+ for (int j = 0; j < 3; j++)
+ {
+ p->ctrl[w][h].xyz[j] = DotProduct(vTemp, vMatrix[j]) + vOrigin[j];
+ if (bSnap)
+ {
+ p->ctrl[w][h].xyz[j] = floor(p->ctrl[w][h].xyz[j] + 0.5);
+ }
+ }
+ }
+ }
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+}
+
+/*
+==================
+Patch_EditPatch
+==================
+*/
+void Patch_EditPatch()
+{
+ //--patchMesh_t* p = &patchMeshes[n];
+ g_qeglobals.d_numpoints = 0;
+ g_qeglobals.d_num_move_points = 0;
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t* p = pb->pPatch;
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ VectorCopy (p->ctrl[i][j].xyz, g_qeglobals.d_points[g_qeglobals.d_numpoints]);
+ if (g_qeglobals.d_numpoints < MAX_POINTS-1)
+ {
+ g_qeglobals.d_numpoints++;
+ }
+ }
+ }
+ }
+ }
+ g_qeglobals.d_select_mode = sel_curvepoint;
+ //--g_nSelectedPatch = n;
+}
+
+
+
+/*
+==================
+Patch_Deselect
+==================
+*/
+//FIXME: need all sorts of asserts throughout a lot of this crap
+void Patch_Deselect()
+{
+ //--g_nSelectedPatch = -1;
+ clearSelection();
+
+ for (brush_t *b = selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ if (b->patchBrush)
+ {
+ b->pPatch->bSelected = false;
+ }
+ }
+
+ //for (int i = 0; i < numPatchMeshes; i++)
+ // patchMeshes[i].bSelected = false;
+
+ if (g_bPatchBendMode)
+ Patch_BendToggle();
+ if (g_bPatchInsertMode)
+ Patch_InsDelToggle();
+}
+
+
+/*
+==================
+Patch_Select
+==================
+*/
+void Patch_Select(patchMesh_t *p)
+{
+ // maintained for point manip.. which i need to fix as this
+ // is pf error prone
+ //--g_nSelectedPatch = n;
+ p->bSelected = true;
+}
+
+
+/*
+==================
+Patch_Deselect
+==================
+*/
+void Patch_Deselect(patchMesh_t *p)
+{
+ p->bSelected = false;
+}
+
+
+/*
+==================
+Patch_Delete
+==================
+*/
+void Patch_Delete(patchMesh_t *p)
+{
+ p->pSymbiot->pPatch = NULL;
+ p->pSymbiot->patchBrush = false;
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+#ifdef _DEBUG
+ if (!p->pData)
+ Sys_Printf("WARNING: unexpected IPluginTexdef* is NULL in Patch_Delete\n");
+ else
+#endif
+ {
+ GETPLUGINTEXDEF(p)->DecRef();
+ p->pData = NULL;
+ }
+ }
+ free(p);
+ p = NULL;
+
+ // bump the array down
+ //for (int i = n; i < numPatchMeshes; i++)
+ //{
+ // patchMeshes[i].pSymbiot->nPatchID--;
+ // patchMeshes[i] = patchMeshes[i+1];
+ //}
+ //numPatchMeshes--;
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_Scale
+==================
+*/
+void Patch_Scale(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuild)
+{
+
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ if (g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(p->ctrl[w][h].xyz) == -1)
+ continue;
+ for (int i=0 ; i<3 ; i++)
+ {
+ p->ctrl[w][h].xyz[i] -= vOrigin[i];
+ p->ctrl[w][h].xyz[i] *= vAmt[i];
+ p->ctrl[w][h].xyz[i] += vOrigin[i];
+ }
+ }
+ }
+ if (bRebuild)
+ {
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ }
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_Cleanup
+==================
+*/
+void Patch_Cleanup()
+{
+ //--g_nSelectedPatch = -1;
+ //numPatchMeshes = 0;
+}
+
+
+
+/*
+==================
+Patch_SetView
+==================
+*/
+void Patch_SetView(int n)
+{
+ g_bSameView = (n == g_nPatchClickedView);
+ g_nPatchClickedView = n;
+}
+
+
+/*
+==================
+Patch_SetTexture
+==================
+*/
+// FIXME: need array validation throughout
+void Patch_SetTexture(patchMesh_t *p, texdef_t *tex_def, IPluginTexdef* pPlugTexdef)
+{
+ p->d_texture = Texture_ForName(tex_def->name);
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+#ifdef _DEBUG
+ if (!p->pData)
+ Sys_Printf("WARNING: unexpected p->pData is NULL in Patch_SetTexture\n");
+ else
+#endif
+ GETPLUGINTEXDEF(p)->DecRef();
+ if (pPlugTexdef)
+ {
+ p->pData = pPlugTexdef->Copy();
+ GETPLUGINTEXDEF(p)->Hook(p);
+ }
+ else
+ {
+ g_SurfaceTable.m_pfnPatchAlloc( p );
+ GETPLUGINTEXDEF(p)->SetDefaultTexdef();
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_DragScale
+==================
+*/
+bool Patch_DragScale(patchMesh_t *p, vec3_t vAmt, vec3_t vMove)
+{
+ vec3_t vMin, vMax, vScale, vTemp, vMid;
+ int i;
+
+ Patch_CalcBounds(p, vMin, vMax);
+
+ VectorSubtract(vMax, vMin, vTemp);
+
+ // if we are scaling in the same dimension the patch has no depth
+ for (i = 0; i < 3; i ++)
+ {
+ if (vTemp[i] == 0 && vMove[i] != 0)
+ {
+ //Patch_Move(n, vMove, true);
+ return false;
+ }
+ }
+
+ for (i=0 ; i<3 ; i++)
+ vMid[i] = (vMin[i] + ((vMax[i] - vMin[i]) / 2));
+
+ for (i = 0; i < 3; i++)
+ {
+ if (vAmt[i] != 0)
+ {
+ vScale[i] = 1.0 + vAmt[i] / vTemp[i];
+ }
+ else
+ {
+ vScale[i] = 1.0;
+ }
+ }
+
+ Patch_Scale(p, vMid, vScale, false);
+
+ VectorSubtract(vMax, vMin, vTemp);
+
+ Patch_CalcBounds(p, vMin, vMax);
+
+ VectorSubtract(vMax, vMin, vMid);
+
+ VectorSubtract(vMid, vTemp, vTemp);
+
+ VectorScale(vTemp, 0.5, vTemp);
+
+ // abs of both should always be equal
+ if (!VectorCompare(vMove, vAmt))
+ {
+ for (i = 0; i < 3; i++)
+ {
+ if (vMove[i] != vAmt[i])
+ vTemp[i] = -(vTemp[i]);
+ }
+ }
+
+ Patch_Move(p, vTemp);
+ return true;
+}
+
+
+/*
+==================
+Patch_AddRow
+==================
+*/
+void Patch_AddRow(patchMesh_t *p)
+{
+ vec3_t vMin, vMax, vTemp;
+ int i, j;
+
+
+ if (p->height+2 < MAX_PATCH_HEIGHT)
+ {
+ Patch_CalcBounds(p, vMin, vMax);
+ VectorSubtract(vMax, vMin, vTemp);
+ for (i = 0; i < 3; i++)
+ {
+ vTemp[i] /= p->height + 2;
+ }
+
+ for (j = 0; j < p->width; j++)
+ {
+ VectorCopy(p->ctrl[j][p->height].xyz, p->ctrl[j][p->height+1].xyz);
+ VectorCopy(p->ctrl[j][p->height].xyz, p->ctrl[j][p->height+2].xyz);
+ p->height += 2;
+ i = 1;
+ while (i < p->height)
+ {
+ VectorAdd(p->ctrl[j][i].xyz, vTemp, p->ctrl[j][i].xyz);
+ i++;
+ }
+ }
+
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ }
+ UpdatePatchInspector();
+}
+
+/*
+==================
+Patch_InsertColumn
+==================
+*/
+void Patch_InsertColumn(patchMesh_t *p, bool bAdd)
+{
+ int h, w, i, j;
+ vec3_t vTemp;
+
+ if (p->width + 2 >= MAX_PATCH_WIDTH)
+ return;
+
+ if (bAdd) // add column?
+ {
+ for (h = 0; h < p->height; h++)
+ {
+ j = p->width-1;
+ VectorSubtract(p->ctrl[j][h].xyz, p->ctrl[j-1][h].xyz, vTemp);
+ for (i = 0; i < 3; i++)
+ vTemp[i] /= 3;
+
+ memcpy(&p->ctrl[j+2][h],&p->ctrl[j][h], sizeof(drawVert_t));
+ memcpy(&p->ctrl[j][h],&p->ctrl[j-1][h], sizeof(drawVert_t));
+
+ VectorAdd(p->ctrl[j][h].xyz, vTemp, p->ctrl[j][h].xyz);
+ memcpy(&p->ctrl[j+1][h], &p->ctrl[j][h], sizeof(drawVert_t));
+ VectorAdd(p->ctrl[j+1][h].xyz, vTemp, p->ctrl[j+1][h].xyz);
+ }
+ }
+ else
+ {
+ for (h = 0; h < p->height; h++)
+ {
+ w = p->width-1;
+ while (w >= 0)
+ {
+ memcpy(&p->ctrl[w+2][h],&p->ctrl[w][h], sizeof(drawVert_t));
+ w--;
+ }
+ VectorSubtract(p->ctrl[1][h].xyz, p->ctrl[0][h].xyz, vTemp);
+ for (i = 0; i < 3; i++)
+ vTemp[i] /= 3;
+ VectorCopy(p->ctrl[0][h].xyz, p->ctrl[1][h].xyz);
+ VectorAdd(p->ctrl[1][h].xyz, vTemp, p->ctrl[1][h].xyz);
+ VectorCopy(p->ctrl[1][h].xyz, p->ctrl[2][h].xyz);
+ VectorAdd(p->ctrl[2][h].xyz, vTemp, p->ctrl[2][h].xyz);
+ }
+ }
+ p->width += 2;
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_InsertRow
+==================
+*/
+void Patch_InsertRow(patchMesh_t *p, bool bAdd)
+{
+ int h, w, i, j;
+ vec3_t vTemp;
+
+ if (p->height + 2 >= MAX_PATCH_HEIGHT)
+ return;
+
+ if (bAdd) // add column?
+ {
+ for (w = 0; w < p->width; w++)
+ {
+ j = p->height-1;
+ VectorSubtract(p->ctrl[w][j].xyz, p->ctrl[w][j-1].xyz, vTemp);
+ for (i = 0; i < 3; i++)
+ vTemp[i] /= 3;
+
+ memcpy(&p->ctrl[w][j+2],&p->ctrl[w][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[w][j],&p->ctrl[w][j-1], sizeof(drawVert_t));
+
+ VectorAdd(p->ctrl[w][j].xyz, vTemp, p->ctrl[w][j].xyz);
+ memcpy(&p->ctrl[w][j+1], &p->ctrl[w][j], sizeof(drawVert_t));
+ VectorAdd(p->ctrl[w][j+1].xyz, vTemp, p->ctrl[w][j+1].xyz);
+ }
+ }
+ else
+ {
+ for (w = 0; w < p->width; w++)
+ {
+ h = p->height-1;
+ while (h >= 0)
+ {
+ memcpy(&p->ctrl[w][h+2],&p->ctrl[w][h], sizeof(drawVert_t));
+ h--;
+ }
+ VectorSubtract(p->ctrl[w][1].xyz, p->ctrl[w][0].xyz, vTemp);
+ for (i = 0; i < 3; i++)
+ vTemp[i] /= 3;
+ VectorCopy(p->ctrl[w][0].xyz, p->ctrl[w][1].xyz);
+ VectorAdd(p->ctrl[w][1].xyz, vTemp, p->ctrl[w][1].xyz);
+ VectorCopy(p->ctrl[w][1].xyz, p->ctrl[w][2].xyz);
+ VectorAdd(p->ctrl[w][2].xyz, vTemp, p->ctrl[w][2].xyz);
+ }
+ }
+ p->height += 2;
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_RemoveRow
+==================
+*/
+void Patch_RemoveRow(patchMesh_t *p, bool bFirst)
+{
+
+ if (p->height <= MIN_PATCH_HEIGHT)
+ return;
+
+ p->height -= 2;
+
+ if (bFirst)
+ {
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ memcpy(&p->ctrl[w][h], &p->ctrl[w][h+2], sizeof(drawVert_t));
+ }
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_RemoveColumn
+==================
+*/
+void Patch_RemoveColumn(patchMesh_t *p, bool bFirst)
+{
+
+ if (p->width <= MIN_PATCH_WIDTH)
+ return;
+
+ p->width -= 2;
+
+ if (bFirst)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ for (int w = 0; w < p->width; w++)
+ {
+ memcpy(&p->ctrl[w][h], &p->ctrl[w+2][h], sizeof(drawVert_t));
+ }
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_AdjustColumns
+==================
+*/
+void Patch_AdjustColumns(patchMesh_t *p, int nCols)
+{
+ vec3_t vTemp, vTemp2;
+ int i, w, h;
+
+ if (nCols & 0x01 || p->width + nCols < 3 || p->width + nCols > MAX_PATCH_WIDTH)
+ return;
+
+ // add in column adjustment
+ p->width += nCols;
+
+ for (h = 0; h < p->height; h++)
+ {
+ // for each column, we need to evenly disperse p->width number
+ // of points across the old bounds
+
+ // calc total distance to interpolate
+ VectorSubtract(p->ctrl[p->width - 1 - nCols][h].xyz, p->ctrl[0][h].xyz, vTemp);
+
+ // amount per cycle
+ for (i = 0; i < 3; i ++)
+ {
+ vTemp2[i] = vTemp[i] / (p->width - 1);
+ }
+
+ // move along
+ for (w = 0; w < p->width-1; w++)
+ {
+ VectorAdd(p->ctrl[w][h].xyz, vTemp2, p->ctrl[w+1][h].xyz);
+ }
+
+ }
+ for ( w = 0 ; w < p->width ; w++ )
+ {
+ for ( h = 0 ; h < p->height ; h++ )
+ {
+ p->ctrl[w][h].st[0] = 4 * (float)w / (p->width - 1);
+ p->ctrl[w][h].st[1] = 4 * (float)h / (p->height - 1);
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+/*
+==================
+Patch_AdjustRows
+==================
+*/
+void Patch_AdjustRows(patchMesh_t *p, int nRows)
+{
+ vec3_t vTemp, vTemp2;
+ int i, w, h;
+
+ if (nRows & 0x01 || p->height + nRows < 3 || p->height + nRows > MAX_PATCH_HEIGHT)
+ return;
+
+ // add in column adjustment
+ p->height += nRows;
+
+ for (w = 0; w < p->width; w++)
+ {
+ // for each row, we need to evenly disperse p->height number
+ // of points across the old bounds
+
+ // calc total distance to interpolate
+ VectorSubtract(p->ctrl[w][p->height - 1 - nRows].xyz, p->ctrl[w][0].xyz, vTemp);
+
+ //vTemp[0] = vTemp[1] = vTemp[2] = 0;
+ //for (h = 0; h < p->height - nRows; h ++)
+ //{
+ // VectorAdd(vTemp, p->ctrl[w][h], vTemp);
+ //}
+
+ // amount per cycle
+ for (i = 0; i < 3; i ++)
+ {
+ vTemp2[i] = vTemp[i] / (p->height - 1);
+ }
+
+ // move along
+ for (h = 0; h < p->height-1; h++)
+ {
+ VectorAdd(p->ctrl[w][h].xyz, vTemp2, p->ctrl[w][h+1].xyz);
+ }
+
+ }
+ for ( w = 0 ; w < p->width ; w++ )
+ {
+ for ( h = 0 ; h < p->height ; h++ )
+ {
+ p->ctrl[w][h].st[0] = 4 * (float)w / (p->width - 1);
+ p->ctrl[w][h].st[1] = 4 * (float)h / (p->height - 1);
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+void Patch_DisperseRows()
+{
+ vec3_t vTemp, vTemp2;
+ int i, w, h;
+
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ Patch_Rebuild(p);
+ for (w = 0; w < p->width; w++)
+ {
+ // for each row, we need to evenly disperse p->height number
+ // of points across the old bounds
+
+ // calc total distance to interpolate
+ VectorSubtract(p->ctrl[w][p->height - 1].xyz, p->ctrl[w][0].xyz, vTemp);
+
+ //vTemp[0] = vTemp[1] = vTemp[2] = 0;
+ //for (h = 0; h < p->height - nRows; h ++)
+ //{
+ // VectorAdd(vTemp, p->ctrl[w][h], vTemp);
+ //}
+
+ // amount per cycle
+ for (i = 0; i < 3; i ++)
+ {
+ vTemp2[i] = vTemp[i] / (p->height - 1);
+ }
+
+ // move along
+ for (h = 0; h < p->height-1; h++)
+ {
+ VectorAdd(p->ctrl[w][h].xyz, vTemp2, p->ctrl[w][h+1].xyz);
+ }
+ Patch_Naturalize(p);
+
+ }
+ }
+ }
+ UpdatePatchInspector();
+
+}
+
+/*
+==================
+Patch_AdjustColumns
+==================
+*/
+void Patch_DisperseColumns()
+{
+ vec3_t vTemp, vTemp2;
+ int i, w, h;
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ Patch_Rebuild(p);
+
+ for (h = 0; h < p->height; h++)
+ {
+ // for each column, we need to evenly disperse p->width number
+ // of points across the old bounds
+
+ // calc total distance to interpolate
+ VectorSubtract(p->ctrl[p->width - 1][h].xyz, p->ctrl[0][h].xyz, vTemp);
+
+ // amount per cycle
+ for (i = 0; i < 3; i ++)
+ {
+ vTemp2[i] = vTemp[i] / (p->width - 1);
+ }
+
+ // move along
+ for (w = 0; w < p->width-1; w++)
+ {
+ VectorAdd(p->ctrl[w][h].xyz, vTemp2, p->ctrl[w+1][h].xyz);
+ }
+
+ }
+ Patch_Naturalize(p);
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+
+/*
+==================
+Patch_AdjustSelected
+==================
+*/
+void Patch_AdjustSelected(bool bInsert, bool bColumn, bool bFlag)
+{
+ bool bUpdate = false;
+ for (brush_t* pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ if (bInsert)
+ {
+ if (bColumn)
+ {
+ Patch_InsertColumn(pb->pPatch, bFlag);
+ }
+ else
+ {
+ Patch_InsertRow(pb->pPatch, bFlag);
+ }
+ }
+ else
+ {
+ if (bColumn)
+ {
+ Patch_RemoveColumn(pb->pPatch, bFlag);
+ }
+ else
+ {
+ Patch_RemoveRow(pb->pPatch, bFlag);
+ }
+ }
+ bUpdate = true;
+ vec3_t vMin, vMax;
+ patchMesh_t *p = pb->pPatch;
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ }
+ }
+ if (bUpdate)
+ {
+ Sys_UpdateWindows(W_ALL);
+ }
+}
+
+
+/*
+==================
+Patch_AdjustSelectedRowCols
+==================
+*/
+void Patch_AdjustSelectedRowCols(int nRows, int nCols)
+{
+ for (brush_t* pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ Patch_InsertColumn(pb->pPatch, false);
+ if (nRows != 0)
+ {
+ Patch_AdjustRows(pb->pPatch, nRows);
+ }
+
+ if (nCols != 0)
+ {
+ Patch_AdjustColumns(pb->pPatch, nCols);
+ }
+ }
+ }
+ UpdatePatchInspector();
+}
+
+
+
+void Parse1DMatrix(int x, float* p)
+{
+ GetToken(true); // (
+ for (int i = 0; i < x; i++)
+ {
+ GetToken(false);
+ p[i] = atof(token);
+ }
+ GetToken(true); // )
+}
+
+void Parse2DMatrix(int y, int x, float* p)
+{
+ GetToken(true); // (
+ for (int i = 0; i < y; i++)
+ {
+ Parse1DMatrix(x, p + i*x);
+ }
+ GetToken(true); // )
+}
+
+void Parse3DMatrix(int z, int y, int x, float* p)
+{
+ GetToken(true); // (
+ for (int i = 0; i < z; i++)
+ {
+ Parse2DMatrix(y, x, p + i*(x*MAX_PATCH_HEIGHT));
+ }
+ GetToken(true); // )
+}
+
+// parses a patch
+brush_t* Patch_Parse(bool bOld)
+{
+ //--if (bOld)
+ //--{
+ //-- return Patch_ParseOld();
+ //--}
+
+ GetToken(true);
+
+ if (strcmp(token, "{"))
+ return NULL;
+
+ patchMesh_t *pm = MakeNewPatch();
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ GETPLUGINTEXDEF(pm)->ParsePatchTexdef();
+ }
+ else
+ {
+ // texture def
+ GetToken(true);
+
+ // band-aid
+ if (strcmp(token, "("))
+ {
+ pm->d_texture = Texture_ForName(token);
+ GetToken(true);
+ }
+ else
+ {
+ pm->d_texture = notexture;
+ Sys_Printf("Warning: Patch read with no texture, using notexture... \n");
+ }
+
+ if (strcmp(token, "("))
+ return NULL;
+
+ // width, height, flags (currently only negative)
+ GetToken(false);
+ pm->width = atoi(token);
+
+ GetToken(false);
+ pm->height = atoi(token);
+
+ GetToken(false);
+ pm->contents = atoi(token);
+
+ GetToken(false);
+ pm->flags = atoi(token);
+
+ GetToken(false);
+ pm->value = atoi(token);
+
+ if (!bOld)
+ {
+ GetToken(false);
+ pm->type = atoi(token);
+ }
+
+ GetToken(false);
+ if (strcmp(token, ")"))
+ return NULL;
+
+ }
+
+
+
+ float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
+ Parse3DMatrix(pm->width, pm->height, 5, reinterpret_cast<float*>(&ctrl));
+
+ int w, h;
+
+ for (w = 0; w < pm->width; w++)
+ {
+ for (h = 0; h < pm->height; h++)
+ {
+ pm->ctrl[w][h].xyz[0] = ctrl[w][h][0];
+ pm->ctrl[w][h].xyz[1] = ctrl[w][h][1];
+ pm->ctrl[w][h].xyz[2] = ctrl[w][h][2];
+ pm->ctrl[w][h].st[0] = ctrl[w][h][3];
+ pm->ctrl[w][h].st[1] = ctrl[w][h][4];
+ }
+ }
+
+ GetToken(true);
+
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // we are in brush primit mode, but maybe it's a classic patch that needs converting, test "}"
+ if (strcmp(token, "}") && strcmp (token, "(") )
+ {
+ epair_t *ep = ParseEpair();
+ ep->next = pm->epairs;
+ pm->epairs = ep;
+ GetToken(true);
+ }
+ }
+
+ if (strcmp(token, "}"))
+ return NULL;
+
+ brush_t *b = AddBrushForPatch(pm, false);
+
+ return b;
+}
+
+
+/*
+==================
+Patch_Write
+==================
+*/
+void Patch_Write (patchMesh_t *p, CMemFile *file)
+{
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ Sys_Printf("WARNING: Patch_Write to a CMemFile and Surface Properties plugin not done\n");
+ }
+ //--MemFile_fprintf(file, " {\n patchDef3\n {\n");
+ MemFile_fprintf(file, " {\n patchDef2\n {\n");
+
+ MemFile_fprintf(file, " %s\n",p->d_texture->name);
+ //--MemFile_fprintf(file, " ( %i %i %i %i %i %i ) \n", p->width, p->height, p->contents, p->flags, p->value, p->type);
+ MemFile_fprintf(file, " ( %i %i %i %i %i ) \n", p->width, p->height, p->contents, p->flags, p->value);
+
+
+ float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
+
+ int w, h;
+ for (w = 0; w < p->width; w++)
+ {
+ for (h = 0; h < p->height; h++)
+ {
+ ctrl[w][h][0] = p->ctrl[w][h].xyz[0];
+ ctrl[w][h][1] = p->ctrl[w][h].xyz[1];
+ ctrl[w][h][2] = p->ctrl[w][h].xyz[2];
+ ctrl[w][h][3] = p->ctrl[w][h].st[0];
+ ctrl[w][h][4] = p->ctrl[w][h].st[1];
+ }
+ }
+
+ _Write3DMatrix(file, p->width, p->height, 5, reinterpret_cast<float*>(&ctrl));
+
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (p->epairs)
+ {
+ for (epair_t *ep = p->epairs ; ep ; ep=ep->next)
+ {
+ MemFile_fprintf (file, "\"%s\" \"%s\"\n", ep->key, ep->value);
+ }
+ }
+ }
+
+ MemFile_fprintf(file, " }\n }\n");
+}
+
+void Patch_Write (patchMesh_t *p, FILE *file)
+{
+ fprintf(file, " {\n patchDef2\n {\n");
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+#ifdef _DEBUG
+ if ( !p->pData )
+ Sys_Printf("ERROR: no IPluginTexdef in patch\n");
+#endif
+ g_File = file;
+ GETPLUGINTEXDEF(p)->WritePatchTexdef( QERApp_MapPrintf_FILE );
+ }
+ else
+ {
+ fprintf(file, " %s\n",p->d_texture->name);
+ fprintf(file, " ( %i %i %i %i %i ) \n", p->width, p->height, p->contents, p->flags, p->value);
+ }
+
+ float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
+
+ int w, h;
+ for (w = 0; w < p->width; w++)
+ {
+ for (h = 0; h < p->height; h++)
+ {
+ ctrl[w][h][0] = p->ctrl[w][h].xyz[0];
+ ctrl[w][h][1] = p->ctrl[w][h].xyz[1];
+ ctrl[w][h][2] = p->ctrl[w][h].xyz[2];
+ ctrl[w][h][3] = p->ctrl[w][h].st[0];
+ ctrl[w][h][4] = p->ctrl[w][h].st[1];
+ }
+ }
+
+ _Write3DMatrix(file, p->width, p->height, 5, reinterpret_cast<float*>(&ctrl));
+
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (p->epairs)
+ {
+ for (epair_t *ep = p->epairs ; ep ; ep=ep->next)
+ {
+ fprintf (file, "\"%s\" \"%s\"\n", ep->key, ep->value);
+ }
+ }
+ }
+
+ fprintf(file, " }\n }\n");
+}
+
+
+/*
+==================
+Patch_RotateTexture
+==================
+*/
+void Patch_RotateTexture(patchMesh_t *p, float fAngle)
+{
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(p, vMin, vMax);
+ p->bDirty = true;
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ if (g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(p->ctrl[w][h].xyz) == -1)
+ continue;
+
+ float x = p->ctrl[w][h].st[0];
+ float y = p->ctrl[w][h].st[1];
+ p->ctrl[w][h].st[0] = x * cos(fAngle * Q_PI / 180) - y * sin(fAngle * Q_PI / 180);
+ p->ctrl[w][h].st[1] = y * cos(fAngle * Q_PI / 180) + x * sin(fAngle * Q_PI / 180);
+ }
+ }
+}
+
+
+/*
+==================
+Patch_ScaleTexture
+==================
+*/
+void Patch_ScaleTexture(patchMesh_t *p, float fx, float fy, bool bFixup)
+{
+ // FIXME:
+ // this hack turns scales into 1.1 or 0.9
+ if (bFixup)
+ {
+ fx = (fx == 0) ? 1.0 : (fx > 0) ? 0.9 : 1.10;
+ fy = (fy == 0) ? 1.0 : (fy > 0) ? 0.9 : 1.10;
+ }
+ else
+ {
+ if (fx == 0)
+ fx = 1.0;
+ if (fy == 0)
+ fy = 1.0;
+ }
+
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ if (g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(p->ctrl[w][h].xyz) == -1)
+ continue;
+
+ p->ctrl[w][h].st[0] *= fx;
+ p->ctrl[w][h].st[1] *= fy;
+ }
+ }
+ p->bDirty = true;
+}
+
+
+/*
+==================
+Patch_ShiftTexture
+==================
+*/
+void Patch_ShiftTexture(patchMesh_t *p, float fx, float fy)
+{
+ //if (fx)
+ // fx = (fx > 0) ? 0.1 : -0.1;
+ //if (fy)
+ // fy = (fy > 0) ? 0.1 : -0.1;
+
+ fx = (abs(fx) >= 1) ? fx / 10 : fx;
+ fy = (abs(fy) >= 1) ? fy / 10 : fy;
+
+ for (int w = 0; w < p->width; w++)
+ {
+ for (int h = 0; h < p->height; h++)
+ {
+ if (g_qeglobals.d_select_mode == sel_curvepoint && PointInMoveList(p->ctrl[w][h].xyz) == -1)
+ continue;
+
+ p->ctrl[w][h].st[0] += fx;
+ p->ctrl[w][h].st[1] += fy;
+ }
+ }
+ p->bDirty = true;
+}
+
+void patchInvert(patchMesh_t *p)
+{
+ drawVert_t vertTemp;
+ p->bDirty = true;
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for (int j = 0; j < p->height / 2; j++)
+ {
+ memcpy(&vertTemp, &p->ctrl[i][p->height - 1- j], sizeof (drawVert_t));
+ memcpy(&p->ctrl[i][p->height - 1 - j], &p->ctrl[i][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[i][j], &vertTemp, sizeof(drawVert_t));
+ }
+ }
+}
+
+/*
+==================
+Patch_ToggleInverted
+==================
+*/
+void Patch_ToggleInverted()
+{
+ bool bUpdate = false;
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ bUpdate = true;
+ patchInvert(pb->pPatch);
+ }
+ }
+
+ if (bUpdate)
+ {
+ Sys_UpdateWindows(W_ALL);
+ }
+ UpdatePatchInspector();
+}
+
+/*
+==================
+Patch_ToggleInverted
+==================
+*/
+void Patch_InvertTexture(bool bY)
+{
+ bool bUpdate = false;
+
+ float fTemp[2];
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ bUpdate = true;
+ patchMesh_t *p = pb->pPatch;
+ p->bDirty = true;
+ if (bY)
+ {
+ for ( int i = 0 ; i < p->height ; i++ )
+ {
+ for (int j = 0; j < p->width / 2; j++)
+ {
+ memcpy(fTemp, &p->ctrl[p->width - 1- j][i].st[0], sizeof (float[2]));
+ memcpy(&p->ctrl[p->width - 1- j][i].st[0], &p->ctrl[j][i].st[0], sizeof(float[2]));
+ memcpy(&p->ctrl[j][i].st[0], fTemp, sizeof(float[2]));
+ }
+ }
+ }
+ else
+ {
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for (int j = 0; j < p->height / 2; j++)
+ {
+ memcpy(fTemp, &p->ctrl[i][p->height - 1- j].st[0], sizeof (float[2]));
+ memcpy(&p->ctrl[i][p->height - 1 - j].st[0], &p->ctrl[i][j].st[0], sizeof(float[2]));
+ memcpy(&p->ctrl[i][j].st[0], fTemp, sizeof(float[2]));
+ }
+ }
+ }
+ }
+ }
+
+ if (bUpdate)
+ {
+ Sys_UpdateWindows(W_ALL);
+ }
+ UpdatePatchInspector();
+}
+
+
+
+
+/*
+==================
+Patch_Save
+==================
+ Saves patch ctrl info (originally to deal with a
+ cancel in the surface dialog
+*/
+void Patch_Save(patchMesh_t *p)
+{
+ patchSave.width = p->width;
+ patchSave.height = p->height;
+ memcpy(patchSave.ctrl, p->ctrl, sizeof(p->ctrl));
+}
+
+
+/*
+==================
+Patch_Restore
+==================
+*/
+void Patch_Restore(patchMesh_t *p)
+{
+ p->width = patchSave.width;
+ p->height = patchSave.height;
+ memcpy(p->ctrl, patchSave.ctrl, sizeof(p->ctrl));
+}
+
+void Patch_ResetTexturing(float fx, float fy)
+{
+ for (brush_t* pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ p->bDirty = true;
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ p->ctrl[i][j].st[0] = fx * (float)i / (p->width - 1);
+ p->ctrl[i][j].st[1] = fy * (float)j / (p->height - 1);
+ }
+ }
+ }
+ }
+}
+
+
+void Patch_FitTexturing()
+{
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ p->bDirty = true;
+ for ( int i = 0 ; i < p->width ; i++ )
+ {
+ for ( int j = 0 ; j < p->height ; j++ )
+ {
+ p->ctrl[i][j].st[0] = 1 * (float)i / (p->width - 1);
+ p->ctrl[i][j].st[1] = 1 * (float)j / (p->height - 1);
+ }
+ }
+ }
+ }
+}
+
+
+void Patch_SetTextureInfo(texdef_t *pt)
+{
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ if (pt->rotate)
+ Patch_RotateTexture(pb->pPatch, pt->rotate);
+
+ if (pt->shift[0] || pt->shift[1])
+ Patch_ShiftTexture(pb->pPatch, pt->shift[0], pt->shift[1]);
+
+ if (pt->scale[0] || pt->scale[1])
+ Patch_ScaleTexture(pb->pPatch, pt->scale[0], pt->scale[1], false);
+
+ patchMesh_t *p = pb->pPatch;
+ p->contents = pt->contents;
+ p->flags = pt->flags;
+ p->value = pt->value;
+ }
+ }
+}
+
+bool WINAPI OnlyPatchesSelected()
+{
+ if (g_ptrSelectedFaces.GetSize() > 0 || selected_brushes.next == &selected_brushes)
+ return false;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (!pb->patchBrush)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WINAPI AnyPatchesSelected()
+{
+ if (g_ptrSelectedFaces.GetSize() > 0 || selected_brushes.next == &selected_brushes)
+ return false;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+patchMesh_t* SinglePatchSelected()
+{
+ if (selected_brushes.next->patchBrush)
+ {
+ return selected_brushes.next->pPatch;
+ }
+ return NULL;
+}
+
+void Patch_BendToggle()
+{
+ if (g_bPatchBendMode)
+ {
+ g_bPatchBendMode = false;
+ HideInfoDialog();
+ g_pParentWnd->UpdatePatchToolbarButtons() ;
+ return;
+ }
+
+ brush_t* b = selected_brushes.next;
+
+ if (!QE_SingleBrush() || !b->patchBrush)
+ {
+ Sys_Printf("Must bend a single patch");
+ return;
+ }
+
+ Patch_Save(b->pPatch);
+ g_bPatchBendMode = true;
+ g_nPatchBendState = BEND_SELECT_ROTATION;
+ g_bPatchAxisOnRow = true;
+ g_nPatchAxisIndex = 1;
+ ShowInfoDialog(g_pBendStateMsg[BEND_SELECT_ROTATION]);
+}
+
+void Patch_BendHandleTAB()
+{
+ if (!g_bPatchBendMode)
+ {
+ return;
+ }
+
+ brush_t* b = selected_brushes.next;
+ if (!QE_SingleBrush() || !b->patchBrush)
+ {
+ Patch_BendToggle();
+ Sys_Printf("No patch to bend!");
+ return;
+ }
+
+ patchMesh_t *p = b->pPatch;
+
+ bool bShift = (GetKeyState(VK_SHIFT) & 0x8000);
+
+ if (g_nPatchBendState == BEND_SELECT_ROTATION)
+ {
+ // only able to deal with odd numbered rows/cols
+ g_nPatchAxisIndex += (bShift) ? -2 : 2;
+ if (g_bPatchAxisOnRow)
+ {
+ if ((bShift) ? g_nPatchAxisIndex <= 0 : g_nPatchAxisIndex >= p->height)
+ {
+ g_bPatchAxisOnRow = false;
+ g_nPatchAxisIndex = (bShift) ? p->width-1 : 1;
+ }
+ }
+ else
+ {
+ if ((bShift) ? g_nPatchAxisIndex <= 0 : g_nPatchAxisIndex >= p->width)
+ {
+ g_bPatchAxisOnRow = true;
+ g_nPatchAxisIndex = (bShift) ? p->height-1 : 1;
+ }
+ }
+ }
+ else
+ if (g_nPatchBendState == BEND_SELECT_ORIGIN)
+ {
+ g_nBendOriginIndex += (bShift) ? -1 : 1;
+ if (g_bPatchAxisOnRow)
+ {
+ if (bShift)
+ {
+ if (g_nBendOriginIndex < 0)
+ g_nBendOriginIndex = p->width-1;
+ }
+ else
+ {
+ if (g_nBendOriginIndex > p->width-1)
+ g_nBendOriginIndex = 0;
+ }
+ VectorCopy(p->ctrl[g_nBendOriginIndex][g_nPatchAxisIndex].xyz, g_vBendOrigin);
+ }
+ else
+ {
+ if (bShift)
+ {
+ if (g_nBendOriginIndex < 0)
+ g_nBendOriginIndex = p->height-1;
+ }
+ else
+ {
+ if (g_nBendOriginIndex > p->height-1)
+ g_nBendOriginIndex = 0;
+ }
+ VectorCopy(p->ctrl[g_nPatchAxisIndex][g_nBendOriginIndex].xyz, g_vBendOrigin);
+ }
+ }
+ else
+ if (g_nPatchBendState == BEND_SELECT_EDGE)
+ {
+ g_bPatchLowerEdge ^= 1;
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+void Patch_BendHandleENTER()
+{
+ if (!g_bPatchBendMode)
+ {
+ return;
+ }
+
+ if (g_nPatchBendState < BEND_BENDIT)
+ {
+ g_nPatchBendState++;
+ ShowInfoDialog(g_pBendStateMsg[g_nPatchBendState]);
+ if (g_nPatchBendState == BEND_SELECT_ORIGIN)
+ {
+ g_vBendOrigin[0] = g_vBendOrigin[1] = g_vBendOrigin[2] = 0;
+ g_nBendOriginIndex = 0;
+ Patch_BendHandleTAB();
+ }
+ else
+ if (g_nPatchBendState == BEND_SELECT_EDGE)
+ {
+ g_bPatchLowerEdge = true;
+ }
+ else
+ if (g_nPatchBendState == BEND_BENDIT)
+ {
+ // basically we go into rotation mode, set the axis to the center of the
+ }
+ }
+ else
+ {
+ // done
+ Patch_BendToggle();
+ }
+ Sys_UpdateWindows(W_ALL);
+
+}
+
+
+void Patch_BendHandleESC()
+{
+ if (!g_bPatchBendMode)
+ {
+ return;
+ }
+ Patch_BendToggle();
+ brush_t* b = selected_brushes.next;
+ if (QE_SingleBrush() && b->patchBrush)
+ {
+ Patch_Restore(b->pPatch);
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+void Patch_SetBendRotateOrigin(patchMesh_t *p)
+{
+#if 1
+ int nType = g_pParentWnd->ActiveXY()->GetViewType();
+ int nDim3 = (nType == XY) ? 2 : (nType == YZ) ? 0 : 1;
+
+ g_vBendOrigin[nDim3] = 0;
+ VectorCopy(g_vBendOrigin, g_pParentWnd->ActiveXY()->RotateOrigin());
+ return;
+#else
+ int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
+ int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
+
+ float fxLo, fyLo, fxHi, fyHi;
+ fxLo = fyLo = 9999;
+ fxHi = fyHi = -9999;
+
+ if (g_bPatchAxisOnRow)
+ {
+ for (int i = 0; i < p->width; i++)
+ {
+ if (p->ctrl[i][g_nPatchAxisIndex].xyz[nDim1] < fxLo)
+ fxLo = p->ctrl[i][g_nPatchAxisIndex].xyz[nDim1];
+
+ if (p->ctrl[i][g_nPatchAxisIndex].xyz[nDim1] > fxHi)
+ fxHi = p->ctrl[i][g_nPatchAxisIndex].xyz[nDim1];
+
+ if (p->ctrl[i][g_nPatchAxisIndex].xyz[nDim2] < fyLo)
+ fyLo = p->ctrl[i][g_nPatchAxisIndex].xyz[nDim2];
+
+ if (p->ctrl[i][g_nPatchAxisIndex].xyz[nDim2] > fyHi)
+ fyHi = p->ctrl[i][g_nPatchAxisIndex].xyz[nDim2];
+ }
+ }
+ else
+ {
+ for (int i = 0; i < p->height; i++)
+ {
+ if (p->ctrl[g_nPatchAxisIndex][i].xyz[nDim1] < fxLo)
+ fxLo = p->ctrl[g_nPatchAxisIndex][i].xyz[nDim1];
+
+ if (p->ctrl[g_nPatchAxisIndex][i].xyz[nDim1] > fxHi)
+ fxHi = p->ctrl[g_nPatchAxisIndex][i].xyz[nDim1];
+
+ if (p->ctrl[g_nPatchAxisIndex][i].xyz[nDim2] < fyLo)
+ fyLo = p->ctrl[g_nPatchAxisIndex][i].xyz[nDim2];
+
+ if (p->ctrl[g_nPatchAxisIndex][i].xyz[nDim2] > fyHi)
+ fyHi = p->ctrl[g_nPatchAxisIndex][i].xyz[nDim2];
+ }
+ }
+
+ g_pParentWnd->ActiveXY()->RotateOrigin()[0] = g_pParentWnd->ActiveXY()->RotateOrigin()[1] = g_pParentWnd->ActiveXY()->RotateOrigin()[2] = 0.0;
+ g_pParentWnd->ActiveXY()->RotateOrigin()[nDim1] = (fxLo + fxHi) * 0.5;
+ g_pParentWnd->ActiveXY()->RotateOrigin()[nDim2] = (fyLo + fyHi) * 0.5;
+#endif
+}
+
+// also sets the rotational origin
+void Patch_SelectBendAxis()
+{
+ brush_t* b = selected_brushes.next;
+ if (!QE_SingleBrush() || !b->patchBrush)
+ {
+ // should not ever happen
+ Patch_BendToggle();
+ return;
+ }
+
+ patchMesh_t *p = b->pPatch;
+ if (g_bPatchAxisOnRow)
+ {
+ SelectRow(p, g_nPatchAxisIndex, false);
+ }
+ else
+ {
+ SelectColumn(p, g_nPatchAxisIndex, false);
+ }
+
+ //FIXME: this only needs to be set once...
+ Patch_SetBendRotateOrigin(p);
+
+}
+
+void Patch_SelectBendNormal()
+{
+ brush_t* b = selected_brushes.next;
+ if (!QE_SingleBrush() || !b->patchBrush)
+ {
+ // should not ever happen
+ Patch_BendToggle();
+ return;
+ }
+
+ patchMesh_t *p = b->pPatch;
+
+ g_qeglobals.d_num_move_points = 0;
+ if (g_bPatchAxisOnRow)
+ {
+ if (g_bPatchLowerEdge)
+ {
+ for (int j = 0; j < g_nPatchAxisIndex; j++)
+ SelectRow(p, j, true);
+ }
+ else
+ {
+ for (int j = p->height-1; j > g_nPatchAxisIndex; j--)
+ SelectRow(p, j, true);
+ }
+ }
+ else
+ {
+ if (g_bPatchLowerEdge)
+ {
+ for (int j = 0; j < g_nPatchAxisIndex; j++)
+ SelectColumn(p, j, true);
+ }
+ else
+ {
+ for (int j = p->width-1; j > g_nPatchAxisIndex; j--)
+ SelectColumn(p, j, true);
+ }
+ }
+ Patch_SetBendRotateOrigin(p);
+}
+
+
+
+void Patch_InsDelToggle()
+{
+ if (g_bPatchInsertMode)
+ {
+ g_bPatchInsertMode = false;
+ HideInfoDialog();
+ g_pParentWnd->UpdatePatchToolbarButtons() ;
+ return;
+ }
+
+ brush_t* b = selected_brushes.next;
+
+ if (!QE_SingleBrush() || !b->patchBrush)
+ {
+ Sys_Printf("Must work with a single patch");
+ return;
+ }
+
+ Patch_Save(b->pPatch);
+ g_bPatchInsertMode = true;
+ g_nPatchInsertState = INSERT_SELECT_EDGE;
+ g_bPatchAxisOnRow = true;
+ g_nPatchAxisIndex = 0;
+ ShowInfoDialog(g_pInsertStateMsg[INSERT_SELECT_EDGE]);
+
+}
+
+void Patch_InsDelESC()
+{
+ if (!g_bPatchInsertMode)
+ {
+ return;
+ }
+ Patch_InsDelToggle();
+ Sys_UpdateWindows(W_ALL);
+}
+
+
+void Patch_InsDelHandleENTER()
+{
+}
+
+void Patch_InsDelHandleTAB()
+{
+ if (!g_bPatchInsertMode)
+ {
+ Patch_InsDelToggle();
+ return;
+ }
+
+ brush_t* b = selected_brushes.next;
+ if (!QE_SingleBrush() || !b->patchBrush)
+ {
+ Patch_BendToggle();
+ Sys_Printf("No patch to bend!");
+ return;
+ }
+
+ patchMesh_t *p = b->pPatch;
+
+ // only able to deal with odd numbered rows/cols
+ g_nPatchAxisIndex += 2;
+ if (g_bPatchAxisOnRow)
+ {
+ if (g_nPatchAxisIndex >= p->height-1)
+ {
+ g_bPatchAxisOnRow = false;
+ g_nPatchAxisIndex = 0;
+ }
+ }
+ else
+ {
+ if (g_nPatchAxisIndex >= p->width-1)
+ {
+ g_bPatchAxisOnRow = true;
+ g_nPatchAxisIndex = 0;
+ }
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+
+void _Write1DMatrix (FILE *f, int x, float *m) {
+ int i;
+
+ fprintf (f, "( ");
+ for (i = 0 ; i < x ; i++) {
+ if (m[i] == (int)m[i] ) {
+ fprintf (f, "%i ", (int)m[i]);
+ } else {
+ fprintf (f, "%f ", m[i]);
+ }
+ }
+ fprintf (f, ")");
+}
+
+void _Write2DMatrix (FILE *f, int y, int x, float *m) {
+ int i;
+
+ fprintf (f, "( ");
+ for (i = 0 ; i < y ; i++) {
+ _Write1DMatrix (f, x, m + i*x);
+ fprintf (f, " ");
+ }
+ fprintf (f, ")\n");
+}
+
+
+void _Write3DMatrix (FILE *f, int z, int y, int x, float *m) {
+ int i;
+
+ fprintf (f, "(\n");
+ for (i = 0 ; i < z ; i++) {
+ _Write2DMatrix (f, y, x, m + i*(x*MAX_PATCH_HEIGHT) );
+ }
+ fprintf (f, ")\n");
+}
+
+void _Write1DMatrix (CMemFile *f, int x, float *m) {
+ int i;
+
+ MemFile_fprintf (f, "( ");
+ for (i = 0 ; i < x ; i++) {
+ if (m[i] == (int)m[i] ) {
+ MemFile_fprintf (f, "%i ", (int)m[i]);
+ } else {
+ MemFile_fprintf (f, "%f ", m[i]);
+ }
+ }
+ MemFile_fprintf (f, ")");
+}
+
+void _Write2DMatrix (CMemFile *f, int y, int x, float *m) {
+ int i;
+
+ MemFile_fprintf (f, "( ");
+ for (i = 0 ; i < y ; i++) {
+ _Write1DMatrix (f, x, m + i*x);
+ MemFile_fprintf (f, " ");
+ }
+ MemFile_fprintf (f, ")\n");
+}
+
+
+void _Write3DMatrix (CMemFile *f, int z, int y, int x, float *m) {
+ int i;
+
+ MemFile_fprintf (f, "(\n");
+ for (i = 0 ; i < z ; i++) {
+ _Write2DMatrix (f, y, x, m + i*(x*MAX_PATCH_HEIGHT) );
+ }
+ MemFile_fprintf (f, ")\n");
+}
+
+
+void Patch_NaturalizeSelected(bool bCap, bool bCycleCap)
+{
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ if (bCap)
+ Patch_CapTexture(pb->pPatch, bCycleCap);
+ else
+ Patch_Naturalize(pb->pPatch);
+ }
+ }
+}
+
+bool within(vec3_t vTest, vec3_t vTL, vec3_t vBR)
+{
+ int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
+ int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
+ if ((vTest[nDim1] > vTL[nDim1] && vTest[nDim1] < vBR[nDim1]) ||
+ (vTest[nDim1] < vTL[nDim1] && vTest[nDim1] > vBR[nDim1]))
+ {
+ if ((vTest[nDim2] > vTL[nDim2] && vTest[nDim2] < vBR[nDim2]) ||
+ (vTest[nDim2] < vTL[nDim2] && vTest[nDim2] > vBR[nDim2]))
+ return true;
+ }
+ return false;
+}
+
+
+void Patch_SelectAreaPoints()
+{
+ g_qeglobals.d_num_move_points = 0;
+ g_nPatchClickedView = -1;
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ for (int i = 0; i < p->width; i++)
+ {
+ for (int j = 0; j < p->height; j++)
+ {
+ if (within(p->ctrl[i][j].xyz, g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR))
+ {
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = p->ctrl[i][j].xyz;
+ }
+ }
+ }
+ }
+ }
+}
+
+const char* Patch_GetTextureName()
+{
+ brush_t* b = selected_brushes.next;
+ if (b->patchBrush)
+ {
+ patchMesh_t *p = b->pPatch;
+ if (p->d_texture->name)
+ return p->d_texture->name;
+ }
+ return "";
+}
+
+patchMesh_t* Patch_Duplicate(patchMesh_t *pFrom)
+{
+ patchMesh_t* p = MakeNewPatch();
+ memcpy(p, pFrom , sizeof(patchMesh_t));
+ p->bSelected = false;
+ p->bDirty = true;
+ p->bOverlay = false;
+ p->nListID = -1;
+ // surface plugin
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+#ifdef _DEBUG
+ if (!pFrom->pData)
+ Sys_Printf("WARNING: unexpected pFrom->pData is NULL in Patch_Duplicate\n");
+ else
+#endif
+ p->pData = GETPLUGINTEXDEF(pFrom)->Copy();
+ }
+ AddBrushForPatch(p);
+ return p;
+}
+
+
+void Patch_Thicken(int nAmount, bool bSeam)
+{
+ int i, j, h, w;
+ brush_t *b;
+ patchMesh_t *pSeam;
+ vec3_t vMin, vMax;
+ CPtrArray brushes;
+
+ nAmount = -nAmount;
+
+
+ if (!QE_SingleBrush())
+ {
+ Sys_Printf("Cannot thicken multiple patches. Please select a single patch.\n");
+ return;
+ }
+
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ Patch_MeshNormals(p);
+ patchMesh_t *pNew = Patch_Duplicate(p);
+ for (i = 0; i < p->width; i++)
+ {
+ for (j = 0; j < p->height; j++)
+ {
+ VectorMA (p->ctrl[i][j].xyz, nAmount, p->ctrl[i][j].normal, pNew->ctrl[i][j].xyz);
+ }
+ }
+
+ Patch_Rebuild(pNew);
+ pNew->type |= PATCH_THICK;
+ brushes.Add(pNew->pSymbiot);
+
+ if (bSeam)
+ {
+
+ // FIXME: this should detect if any edges of the patch are closed and act appropriately
+ //
+ if (!(p->type & PATCH_CYLINDER))
+ {
+ b = Patch_GenericMesh(3, p->height, 2, false, true);
+ pSeam = b->pPatch;
+ pSeam->type |= PATCH_SEAM;
+ for (i = 0; i < p->height; i++)
+ {
+ VectorCopy(p->ctrl[0][i].xyz, pSeam->ctrl[0][i].xyz);
+ VectorCopy(pNew->ctrl[0][i].xyz, pSeam->ctrl[2][i].xyz);
+ VectorAdd(pSeam->ctrl[0][i].xyz, pSeam->ctrl[2][i].xyz, pSeam->ctrl[1][i].xyz);
+ VectorScale(pSeam->ctrl[1][i].xyz, 0.5, pSeam->ctrl[1][i].xyz);
+ }
+
+
+ Patch_CalcBounds(pSeam, vMin, vMax);
+ Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
+ //--Patch_CapTexture(pSeam);
+ Patch_Naturalize(pSeam);
+ patchInvert(pSeam);
+ brushes.Add(b);
+
+ w = p->width - 1;
+ b = Patch_GenericMesh(3, p->height, 2, false, true);
+ pSeam = b->pPatch;
+ pSeam->type |= PATCH_SEAM;
+ for (i = 0; i < p->height; i++)
+ {
+ VectorCopy(p->ctrl[w][i].xyz, pSeam->ctrl[0][i].xyz);
+ VectorCopy(pNew->ctrl[w][i].xyz, pSeam->ctrl[2][i].xyz);
+ VectorAdd(pSeam->ctrl[0][i].xyz, pSeam->ctrl[2][i].xyz, pSeam->ctrl[1][i].xyz);
+ VectorScale(pSeam->ctrl[1][i].xyz, 0.5, pSeam->ctrl[1][i].xyz);
+ }
+ Patch_CalcBounds(pSeam, vMin, vMax);
+ Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
+ //--Patch_CapTexture(pSeam);
+ Patch_Naturalize(pSeam);
+ brushes.Add(b);
+ }
+
+ //--{
+ // otherwise we will add one per end
+ b = Patch_GenericMesh(p->width, 3, 2, false, true);
+ pSeam = b->pPatch;
+ pSeam->type |= PATCH_SEAM;
+ for (i = 0; i < p->width; i++)
+ {
+ VectorCopy(p->ctrl[i][0].xyz, pSeam->ctrl[i][0].xyz);
+ VectorCopy(pNew->ctrl[i][0].xyz, pSeam->ctrl[i][2].xyz);
+ VectorAdd(pSeam->ctrl[i][0].xyz, pSeam->ctrl[i][2].xyz, pSeam->ctrl[i][1].xyz);
+ VectorScale(pSeam->ctrl[i][1].xyz, 0.5, pSeam->ctrl[i][1].xyz);
+ }
+
+
+ Patch_CalcBounds(pSeam, vMin, vMax);
+ Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
+ //--Patch_CapTexture(pSeam);
+ Patch_Naturalize(pSeam);
+ patchInvert(pSeam);
+ brushes.Add(b);
+
+ h = p->height - 1;
+ b = Patch_GenericMesh(p->width, 3, 2, false, true);
+ pSeam = b->pPatch;
+ pSeam->type |= PATCH_SEAM;
+ for (i = 0; i < p->width; i++)
+ {
+ VectorCopy(p->ctrl[i][h].xyz, pSeam->ctrl[i][0].xyz);
+ VectorCopy(pNew->ctrl[i][h].xyz, pSeam->ctrl[i][2].xyz);
+ VectorAdd(pSeam->ctrl[i][0].xyz, pSeam->ctrl[i][2].xyz, pSeam->ctrl[i][1].xyz);
+ VectorScale(pSeam->ctrl[i][1].xyz, 0.5, pSeam->ctrl[i][1].xyz);
+ }
+ Patch_CalcBounds(pSeam, vMin, vMax);
+ Brush_RebuildBrush(pSeam->pSymbiot, vMin, vMax);
+ //--Patch_CapTexture(pSeam);
+ Patch_Naturalize(pSeam);
+ brushes.Add(b);
+
+ eclass_t *pecNew = Eclass_ForName("func_group", false);
+ if (pecNew)
+ {
+ entity_t *e = Entity_Create(pecNew);
+ SetKeyValue(e, "type", "patchThick");
+ }
+
+
+ //--}
+ }
+ patchInvert(pNew);
+ }
+ }
+
+ for (i = 0; i < brushes.GetSize(); i++)
+ {
+ Select_Brush(reinterpret_cast<brush_t*>(brushes.GetAt(i)));
+ }
+
+ UpdatePatchInspector();
+}
+
+
+/*
+lets get another list together as far as necessities..
+
+*snapping stuff to the grid (i will only snap movements by the mouse to the grid.. snapping the rotational bend stuff will fubar everything)
+
+capping bevels/endcaps
+
+hot keys
+
+texture fix for caps
+
+clear clipboard
+
+*region fix
+
+*surface dialog
+
+*/
+
+void Patch_SetOverlays()
+{
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ pb->pPatch->bOverlay = true;
+ }
+ }
+}
+
+
+
+void Patch_ClearOverlays()
+{
+ brush_t *pb;
+ for (pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ pb->pPatch->bOverlay = false;
+ }
+ }
+
+ for (pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ pb->pPatch->bOverlay = false;
+ }
+ }
+
+}
+
+// freezes selected vertices
+void Patch_Freeze()
+{
+ brush_t *pb;
+ for (pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ pb->pPatch->bOverlay = false;
+ }
+ }
+
+ for (pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ pb->pPatch->bOverlay = false;
+ }
+ }
+
+}
+
+void Patch_UnFreeze(bool bAll)
+{
+}
+
+
+
+void Patch_Transpose()
+{
+ int i, j, w;
+ drawVert_t dv;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+
+ if ( p->width > p->height )
+ {
+ for ( i = 0 ; i < p->height ; i++ )
+ {
+ for ( j = i + 1 ; j < p->width ; j++ )
+ {
+ if ( j < p->height )
+ {
+ // swap the value
+ memcpy(&dv,&p->ctrl[j][i],sizeof(drawVert_t));
+ memcpy(&p->ctrl[j][i],&p->ctrl[i][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[i][j],&dv, sizeof(drawVert_t));
+ }
+ else
+ {
+ // just copy
+ memcpy(&p->ctrl[j][i],&p->ctrl[i][j], sizeof(drawVert_t));
+ }
+ }
+ }
+ }
+ else
+ {
+ for ( i = 0 ; i < p->width ; i++ )
+ {
+ for ( j = i + 1 ; j < p->height ; j++ )
+ {
+ if ( j < p->width )
+ {
+ // swap the value
+ memcpy(&dv,&p->ctrl[i][j], sizeof(drawVert_t));
+ memcpy(&p->ctrl[i][j],&p->ctrl[j][i], sizeof(drawVert_t));
+ memcpy(&p->ctrl[j][i],&dv, sizeof(drawVert_t));
+ }
+ else
+ {
+ // just copy
+ memcpy(&p->ctrl[i][j],&p->ctrl[j][i], sizeof(drawVert_t));
+ }
+ }
+ }
+ }
+
+ w = p->width;
+ p->width = p->height;
+ p->height = w;
+ patchInvert(p);
+ Patch_Rebuild(p);
+ }
+ }
+}
+
+
+
+void Select_SnapToGrid()
+{
+ int i,j, k;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+#if 0
+ float ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT][5];
+ memcpy(ctrl, p->ctrl, sizeof(p->ctrl));
+ i = p->width;
+ p->width = p->height;
+ p->height = i;
+ for (i = 0; i < p->width; i++)
+ {
+ int l = p->height-1;
+ for (j = 0; j < p->height; j++)
+ {
+ for (k = 0; k < 5; k++)
+ {
+ p->ctrl[i][l][k] = ctrl[j][i][k];
+ }
+ l--;
+ }
+ }
+#else
+ for (i = 0; i < p->width; i++)
+ {
+ for (j = 0; j < p->height; j++)
+ {
+ for (k = 0; k < 3; k++)
+ {
+ p->ctrl[i][j].xyz[k] = floor(p->ctrl[i][j].xyz[k] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ }
+ }
+ }
+#endif
+ vec3_t vMin, vMax;
+ Patch_CalcBounds(p, vMin, vMax);
+ Brush_RebuildBrush(p->pSymbiot, vMin, vMax);
+ }
+ else
+ {
+ Brush_SnapToGrid(pb);
+ }
+ }
+}
+
+
+void Patch_FindReplaceTexture(brush_t *pb, const char *pFind, const char *pReplace, bool bForce)
+{
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ if (bForce || strcmpi(p->d_texture->name, pFind) == 0)
+ {
+ p->d_texture = Texture_ForName(pReplace);
+ //strcpy(p->d_texture->name, pReplace);
+ }
+ }
+}
+
+void Patch_ReplaceQTexture(brush_t *pb, qtexture_t *pOld, qtexture_t *pNew)
+{
+ if (pb->patchBrush)
+ {
+ patchMesh_t *p = pb->pPatch;
+ if (p->d_texture == pOld)
+ {
+ p->d_texture = pNew;
+ }
+ }
+}
+
+void Patch_Clone(patchMesh_t *p, brush_t *pNewOwner)
+{
+}
+
+void Patch_FromTriangle(vec5_t vx, vec5_t vy, vec5_t vz)
+{
+ patchMesh_t* p = MakeNewPatch();
+ p->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
+ p->width = 3;
+ p->height = 3;
+ p->type = PATCH_TRIANGLE;
+
+ // 0 0 goes to x
+ // 0 1 goes to x
+ // 0 2 goes to x
+
+ // 1 0 goes to mid of x and z
+ // 1 1 goes to mid of x y and z
+ // 1 2 goes to mid of x and y
+
+ // 2 0 goes to z
+ // 2 1 goes to mid of y and z
+ // 2 2 goes to y
+
+ vec5_t vMidXZ;
+ vec5_t vMidXY;
+ vec5_t vMidYZ;
+
+
+ for (int j = 0; j < 3; j++)
+ {
+ _Vector5Add(vx, vz, vMidXZ);
+ _Vector5Scale(vMidXZ, 0.5, vMidXZ);
+ //vMidXZ[j] = vx[j] + abs((vx[j] - vz[j]) * 0.5);
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ _Vector5Add(vx, vy, vMidXY);
+ _Vector5Scale(vMidXY, 0.5, vMidXY);
+ //vMidXY[j] = vx[j] + abs((vx[j] - vy[j]) * 0.5);
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ _Vector5Add(vy, vz, vMidYZ);
+ _Vector5Scale(vMidYZ, 0.5, vMidYZ);
+ //vMidYZ[j] = vy[j] + abs((vy[j] - vz[j]) * 0.5);
+ }
+
+ _Vector53Copy(vx, p->ctrl[0][0].xyz);
+ _Vector53Copy(vx, p->ctrl[0][1].xyz);
+ _Vector53Copy(vx, p->ctrl[0][2].xyz);
+ p->ctrl[0][0].st[0] = vx[3];
+ p->ctrl[0][0].st[1] = vx[4];
+ p->ctrl[0][1].st[0] = vx[3];
+ p->ctrl[0][1].st[1] = vx[4];
+ p->ctrl[0][2].st[0] = vx[3];
+ p->ctrl[0][2].st[1] = vx[4];
+
+ _Vector53Copy(vMidXY, p->ctrl[1][0].xyz);
+ _Vector53Copy(vx, p->ctrl[1][1].xyz);
+ _Vector53Copy(vMidXZ, p->ctrl[1][2].xyz);
+ p->ctrl[1][0].st[0] = vMidXY[3];
+ p->ctrl[1][0].st[1] = vMidXY[4];
+ p->ctrl[1][1].st[0] = vx[3];
+ p->ctrl[1][1].st[1] = vx[4];
+ p->ctrl[1][2].st[0] = vMidXZ[3];
+ p->ctrl[1][2].st[1] = vMidXZ[4];
+
+ _Vector53Copy(vy, p->ctrl[2][0].xyz);
+ _Vector53Copy(vMidYZ, p->ctrl[2][1].xyz);
+ _Vector53Copy(vz, p->ctrl[2][2].xyz);
+ p->ctrl[2][0].st[0] = vy[3];
+ p->ctrl[2][0].st[1] = vy[4];
+ p->ctrl[2][1].st[0] = vMidYZ[3];
+ p->ctrl[2][1].st[1] = vMidYZ[4];
+ p->ctrl[2][2].st[0] = vz[3];
+ p->ctrl[2][2].st[1] = vz[4];
+
+
+ //Patch_Naturalize(p);
+
+ brush_t *b = AddBrushForPatch(p);
+
+}
+
+
+/*
+==============
+Patch_SetEpair
+sets an epair for the given patch
+==============
+*/
+void Patch_SetEpair(patchMesh_t *p, const char *pKey, const char *pValue)
+{
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ SetKeyValue(p->epairs, pKey, pValue);
+ }
+}
+
+/*
+=================
+Patch_GetKeyValue
+=================
+*/
+const char* Patch_GetKeyValue(patchMesh_t *p, const char *pKey)
+{
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ return ValueForKey(p->epairs, pKey);
+ }
+ return "";
+}
+
+
+//Real nitpicky, but could you make CTRL-S save the current map with the current name? (ie: File/Save)
+/*
+Feature addition.
+When reading in textures, please check for the presence of a file called "textures.link" or something, which contains one line such as;
+
+g:\quake3\baseq3\textures\common
+
+ So that, when I'm reading in, lets say, my \eerie directory, it goes through and adds my textures to the palette, along with everything in common.
+
+ Don't forget to add "Finer texture alignment" to the list. I'd like to be able to move in 0.1 increments using the Shift-Arrow Keys.
+
+ No. Sometimes textures are drawn the wrong way on patches. We'd like the ability to flip a texture. Like the way X/Y scale -1 used to worked.
+
+ 1) Easier way of deleting rows, columns
+2) Fine tuning of textures on patches (X/Y shifts other than with the surface dialog)
+2) Patch matrix transposition
+
+ 1) Actually, bump texture flipping on patches to the top of the list of things to do.
+2) When you select a patch, and hit S, it should read in the selected patch texture. Should not work if you multiselect patches and hit S
+3) Brandon has a wierd anomoly. He fine-tunes a patch with caps. It looks fine when the patch is selected, but as soon as he escapes out, it reverts to it's pre-tuned state. When he selects the patch again, it looks tuned
+
+
+*1) Flipping textures on patches
+*2) When you select a patch, and hit S, it should read in the selected patch texture. Should not work if you multiselect patches and hit S
+3) Easier way of deleting rows columns
+*4) Thick Curves
+5) Patch matrix transposition
+6) Inverted cylinder capping
+*7) bugs
+*8) curve speed
+
+ Have a new feature request. "Compute Bounding Box" for mapobjects (md3 files). This would be used for misc_mapobject (essentially, drop in 3DS Max models into our maps)
+
+ Ok, Feature Request. Load and draw MD3's in the Camera view with proper bounding boxes. This should be off misc_model
+
+ Feature Addition: View/Hide Hint Brushes -- This should be a specific case.
+*/
diff --git a/q3radiant/PMESH.H b/q3radiant/PMESH.H
new file mode 100755
index 0000000..3d49eae
--- /dev/null
+++ b/q3radiant/PMESH.H
@@ -0,0 +1,21 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
diff --git a/q3radiant/POINTS.CPP b/q3radiant/POINTS.CPP
new file mode 100755
index 0000000..db443a7
--- /dev/null
+++ b/q3radiant/POINTS.CPP
@@ -0,0 +1,156 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+
+#include "qe3.h"
+
+
+#define MAX_POINTFILE 8192
+static vec3_t s_pointvecs[MAX_POINTFILE];
+static int s_num_points, s_check_point;
+
+void Pointfile_Delete (void)
+{
+ char name[1024];
+
+ strcpy (name, currentmap);
+ StripExtension (name);
+ strcat (name, ".lin");
+
+ remove(name);
+}
+
+// advance camera to next point
+void Pointfile_Next (void)
+{
+ vec3_t dir;
+
+ if (s_check_point >= s_num_points-2)
+ {
+ Sys_Status ("End of pointfile", 0);
+ return;
+ }
+ s_check_point++;
+ VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetCamera()->Camera().origin);
+ VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetXYWnd()->GetOrigin());
+ VectorSubtract (s_pointvecs[s_check_point+1], g_pParentWnd->GetCamera()->Camera().origin, dir);
+ VectorNormalize (dir);
+ g_pParentWnd->GetCamera()->Camera().angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
+ g_pParentWnd->GetCamera()->Camera().angles[0] = asin (dir[2])*180/3.14159;
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+// advance camera to previous point
+void Pointfile_Prev (void)
+{
+ vec3_t dir;
+
+ if ( s_check_point == 0)
+ {
+ Sys_Status ("Start of pointfile", 0);
+ return;
+ }
+ s_check_point--;
+ VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetCamera()->Camera().origin);
+ VectorCopy (s_pointvecs[s_check_point], g_pParentWnd->GetXYWnd()->GetOrigin());
+ VectorSubtract (s_pointvecs[s_check_point+1], g_pParentWnd->GetCamera()->Camera().origin, dir);
+ VectorNormalize (dir);
+ g_pParentWnd->GetCamera()->Camera().angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
+ g_pParentWnd->GetCamera()->Camera().angles[0] = asin (dir[2])*180/3.14159;
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+void WINAPI Pointfile_Check (void)
+{
+ char name[1024];
+ FILE *f;
+ vec3_t v;
+
+ strcpy (name, currentmap);
+ StripExtension (name);
+ strcat (name, ".lin");
+
+ f = fopen (name, "r");
+ if (!f)
+ return;
+
+ Sys_Printf ("Reading pointfile %s\n", name);
+
+ if (!g_qeglobals.d_pointfile_display_list)
+ g_qeglobals.d_pointfile_display_list = qglGenLists(1);
+
+ s_num_points = 0;
+ qglNewList (g_qeglobals.d_pointfile_display_list, GL_COMPILE);
+ qglColor3f (1, 0, 0);
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglLineWidth (4);
+ qglBegin(GL_LINE_STRIP);
+ do
+ {
+ if (fscanf (f, "%f %f %f\n", &v[0], &v[1], &v[2]) != 3)
+ break;
+ if (s_num_points < MAX_POINTFILE)
+ {
+ VectorCopy (v, s_pointvecs[s_num_points]);
+ s_num_points++;
+ }
+ qglVertex3fv (v);
+ } while (1);
+ qglEnd();
+ qglLineWidth (1);
+ qglEndList ();
+
+ s_check_point = 0;
+ fclose (f);
+ //Pointfile_Next ();
+}
+
+void Pointfile_Draw( void )
+{
+ int i;
+
+ qglColor3f( 1.0F, 0.0F, 0.0F );
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglLineWidth (4);
+ qglBegin(GL_LINE_STRIP);
+ for ( i = 0; i < s_num_points; i++ )
+ {
+ qglVertex3fv( s_pointvecs[i] );
+ }
+ qglEnd();
+ qglLineWidth( 1 );
+}
+
+void Pointfile_Clear (void)
+{
+ if (!g_qeglobals.d_pointfile_display_list)
+ return;
+
+ qglDeleteLists (g_qeglobals.d_pointfile_display_list, 1);
+ g_qeglobals.d_pointfile_display_list = 0;
+ Sys_UpdateWindows (W_ALL);
+}
+
diff --git a/q3radiant/PatchDensityDlg.cpp b/q3radiant/PatchDensityDlg.cpp
new file mode 100755
index 0000000..3fda571
--- /dev/null
+++ b/q3radiant/PatchDensityDlg.cpp
@@ -0,0 +1,89 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PatchDensityDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "PatchDensityDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPatchDensityDlg dialog
+
+
+CPatchDensityDlg::CPatchDensityDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CPatchDensityDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CPatchDensityDlg)
+ //}}AFX_DATA_INIT
+}
+
+
+void CPatchDensityDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CPatchDensityDlg)
+ DDX_Control(pDX, IDC_COMBO_WIDTH, m_wndWidth);
+ DDX_Control(pDX, IDC_COMBO_HEIGHT, m_wndHeight);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CPatchDensityDlg, CDialog)
+ //{{AFX_MSG_MAP(CPatchDensityDlg)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPatchDensityDlg message handlers
+
+int g_nXLat[] = {3,5,7,9,11,13,15};
+
+void CPatchDensityDlg::OnOK()
+{
+ int nWidth = m_wndWidth.GetCurSel();
+ int nHeight = m_wndHeight.GetCurSel();
+
+ if (nWidth >= 0 && nWidth <= 6 && nHeight >= 0 && nHeight <= 6)
+ {
+ Patch_GenericMesh(g_nXLat[nWidth], g_nXLat[nHeight], g_pParentWnd->ActiveXY()->GetViewType());
+ Sys_UpdateWindows(W_ALL);
+ }
+
+ CDialog::OnOK();
+}
+
+BOOL CPatchDensityDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_wndWidth.SetCurSel(0);
+ m_wndHeight.SetCurSel(0);
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/PatchDensityDlg.h b/q3radiant/PatchDensityDlg.h
new file mode 100755
index 0000000..9297e16
--- /dev/null
+++ b/q3radiant/PatchDensityDlg.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_PATCHDENSITYDLG_H__509162A1_1023_11D2_AFFB_00AA00A410FC__INCLUDED_)
+#define AFX_PATCHDENSITYDLG_H__509162A1_1023_11D2_AFFB_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// PatchDensityDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CPatchDensityDlg dialog
+
+class CPatchDensityDlg : public CDialog
+{
+// Construction
+public:
+ CPatchDensityDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CPatchDensityDlg)
+ enum { IDD = IDD_DIALOG_NEWPATCH };
+ CComboBox m_wndWidth;
+ CComboBox m_wndHeight;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPatchDensityDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CPatchDensityDlg)
+ virtual void OnOK();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PATCHDENSITYDLG_H__509162A1_1023_11D2_AFFB_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/PatchDialog.cpp b/q3radiant/PatchDialog.cpp
new file mode 100755
index 0000000..316e145
--- /dev/null
+++ b/q3radiant/PatchDialog.cpp
@@ -0,0 +1,354 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PatchDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "PatchDialog.h"
+#include "TextureLayout.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CPatchDialog dialog
+
+CPatchDialog g_PatchDialog;
+
+CPatchDialog::CPatchDialog(CWnd* pParent /*=NULL*/)
+ : CDialog(CPatchDialog::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CPatchDialog)
+ m_strName = _T("");
+ m_fS = 0.0f;
+ m_fT = 0.0f;
+ m_fX = 0.0f;
+ m_fY = 0.0f;
+ m_fZ = 0.0f;
+ m_fHScale = 0.05f;
+ m_fHShift = 0.05f;
+ m_fRotate = 45;
+ m_fVScale = 0.05f;
+ m_fVShift = 0.05f;
+ //}}AFX_DATA_INIT
+ m_Patch = NULL;
+}
+
+
+void CPatchDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CPatchDialog)
+ DDX_Control(pDX, IDC_SPIN_VSHIFT, m_wndVShift);
+ DDX_Control(pDX, IDC_SPIN_VSCALE, m_wndVScale);
+ DDX_Control(pDX, IDC_SPIN_ROTATE, m_wndRotate);
+ DDX_Control(pDX, IDC_SPIN_HSHIFT, m_wndHShift);
+ DDX_Control(pDX, IDC_SPIN_HSCALE, m_wndHScale);
+ DDX_Control(pDX, IDC_COMBO_TYPE, m_wndType);
+ DDX_Control(pDX, IDC_COMBO_ROW, m_wndRows);
+ DDX_Control(pDX, IDC_COMBO_COL, m_wndCols);
+ DDX_Text(pDX, IDC_EDIT_NAME, m_strName);
+ DDX_Text(pDX, IDC_EDIT_S, m_fS);
+ DDX_Text(pDX, IDC_EDIT_T, m_fT);
+ DDX_Text(pDX, IDC_EDIT_X, m_fX);
+ DDX_Text(pDX, IDC_EDIT_Y, m_fY);
+ DDX_Text(pDX, IDC_EDIT_Z, m_fZ);
+ DDX_Text(pDX, IDC_HSCALE, m_fHScale);
+ DDX_Text(pDX, IDC_HSHIFT, m_fHShift);
+ DDX_Text(pDX, IDC_ROTATE, m_fRotate);
+ DDX_Text(pDX, IDC_VSCALE, m_fVScale);
+ DDX_Text(pDX, IDC_VSHIFT, m_fVShift);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CPatchDialog, CDialog)
+ //{{AFX_MSG_MAP(CPatchDialog)
+ ON_BN_CLICKED(IDC_BTN_PATCHDETAILS, OnBtnPatchdetails)
+ ON_BN_CLICKED(IDC_BTN_PATCHFIT, OnBtnPatchfit)
+ ON_BN_CLICKED(IDC_BTN_PATCHNATURAL, OnBtnPatchnatural)
+ ON_BN_CLICKED(IDC_BTN_PATCHRESET, OnBtnPatchreset)
+ ON_CBN_SELCHANGE(IDC_COMBO_COL, OnSelchangeComboCol)
+ ON_CBN_SELCHANGE(IDC_COMBO_ROW, OnSelchangeComboRow)
+ ON_CBN_SELCHANGE(IDC_COMBO_TYPE, OnSelchangeComboType)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HSCALE, OnDeltaposSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ROTATE, OnDeltaposSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VSCALE, OnDeltaposSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VSHIFT, OnDeltaposSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HSHIFT, OnDeltaposSpin)
+ ON_WM_DESTROY()
+ ON_BN_CLICKED(ID_APPLY, OnApply)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPatchDialog message handlers
+
+void CPatchDialog::OnBtnPatchdetails()
+{
+ Patch_NaturalizeSelected(true);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CPatchDialog::OnBtnPatchfit()
+{
+ Patch_FitTexturing();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CPatchDialog::OnBtnPatchnatural()
+{
+ Patch_NaturalizeSelected();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CPatchDialog::OnBtnPatchreset()
+{
+ CTextureLayout dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ Patch_ResetTexturing(dlg.m_fX, dlg.m_fY);
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CPatchDialog::OnSelchangeComboCol()
+{
+ UpdateRowColInfo();
+}
+
+void CPatchDialog::OnSelchangeComboRow()
+{
+ UpdateRowColInfo();
+}
+
+void CPatchDialog::OnSelchangeComboType()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CPatchDialog::OnOK()
+{
+ m_Patch = NULL;
+
+ CDialog::OnOK();
+}
+
+void CPatchDialog::OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ UpdateSpinners((pNMUpDown->iDelta > 0), pNMUpDown->hdr.idFrom);
+ *pResult = 0;
+}
+
+BOOL CPatchDialog::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ m_wndHScale.SetRange(0, 1000);
+ m_wndVScale.SetRange(0, 1000);
+ m_wndHShift.SetRange(0, 1000);
+ m_wndVShift.SetRange(0, 1000);
+ m_wndRotate.SetRange(0, 1000);
+
+ GetPatchInfo();
+
+ // TODO: Add extra initialization here
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+
+
+void CPatchDialog::GetPatchInfo()
+{
+ m_Patch = SinglePatchSelected();
+ if (m_Patch != NULL)
+ {
+ CString str;
+ int i;
+ m_wndRows.ResetContent();
+ for (i = 0; i < m_Patch->height; i++)
+ {
+ str.Format("%i", i);
+ m_wndRows.AddString(str);
+ }
+ m_wndRows.SetCurSel(0);
+ m_wndCols.ResetContent();
+ for (i = 0; i < m_Patch->width; i++)
+ {
+ str.Format("%i", i);
+ m_wndCols.AddString(str);
+ }
+ m_wndCols.SetCurSel(0);
+ }
+ UpdateRowColInfo();
+}
+
+void CPatchDialog::SetPatchInfo()
+{
+
+}
+
+void DoPatchInspector()
+{
+ if (g_PatchDialog.GetSafeHwnd() == NULL)
+ {
+ g_PatchDialog.Create(IDD_DIALOG_PATCH);
+ CRect rct;
+ LONG lSize = sizeof(rct);
+ if (LoadRegistryInfo("Radiant::PatchWindow", &rct, &lSize))
+ {
+ g_PatchDialog.SetWindowPos(NULL, rct.left, rct.top, 0,0, SWP_NOSIZE);
+ }
+ }
+ g_PatchDialog.ShowWindow(SW_SHOW);
+ g_PatchDialog.GetPatchInfo();
+}
+
+void UpdatePatchInspector()
+{
+ if (g_PatchDialog.GetSafeHwnd() != NULL)
+ {
+ g_PatchDialog.UpdateInfo();
+ }
+
+}
+
+void CPatchDialog::OnDestroy()
+{
+ if (GetSafeHwnd())
+ {
+ CRect rct;
+ GetWindowRect(rct);
+ SaveRegistryInfo("Radiant::PatchWindow", &rct, sizeof(rct));
+ }
+ CDialog::OnDestroy();
+}
+
+void CPatchDialog::UpdateRowColInfo()
+{
+ m_fX = m_fY = m_fZ = m_fS = m_fT = 0.0;
+
+ if (m_Patch != NULL)
+ {
+ int r = m_wndRows.GetCurSel();
+ int c = m_wndCols.GetCurSel();
+ if (r >= 0 && r < m_Patch->height && c >= 0 && c < m_Patch->width)
+ {
+ m_fX = m_Patch->ctrl[c][r].xyz[0];
+ m_fY = m_Patch->ctrl[c][r].xyz[1];
+ m_fZ = m_Patch->ctrl[c][r].xyz[2];
+ m_fS = m_Patch->ctrl[c][r].st[0];
+ m_fT = m_Patch->ctrl[c][r].st[1];
+ }
+ }
+ UpdateData(FALSE);
+}
+
+void CPatchDialog::UpdateInfo()
+{
+ GetPatchInfo();
+}
+
+void CPatchDialog::OnApply()
+{
+ UpdateData(TRUE);
+ if (m_Patch != NULL)
+ {
+ int r = m_wndRows.GetCurSel();
+ int c = m_wndCols.GetCurSel();
+ if (r >= 0 && r < m_Patch->height && c >= 0 && c < m_Patch->width)
+ {
+ m_Patch->ctrl[c][r].xyz[0] = m_fX;
+ m_Patch->ctrl[c][r].xyz[1] = m_fY;
+ m_Patch->ctrl[c][r].xyz[2] = m_fZ;
+ m_Patch->ctrl[c][r].st[0] = m_fS;
+ m_Patch->ctrl[c][r].st[1] = m_fT;
+ m_Patch->bDirty = true;
+ Sys_UpdateWindows(W_ALL);
+ }
+ }
+}
+
+void CPatchDialog::UpdateSpinners(bool bUp, int nID)
+{
+ texdef_t td;
+
+ td.rotate = 0.0;
+ td.scale[0] = td.scale[1] = 0.0;
+ td.shift[0] = td.shift[1] = 0.0;
+ td.contents = 0;
+ td.flags = 0;
+ td.value = 0;
+
+
+ UpdateData(TRUE);
+
+ if (nID == IDC_SPIN_ROTATE)
+ {
+ if (bUp)
+ td.rotate = m_fRotate;
+ else
+ td.rotate = -m_fRotate;
+ }
+ else if (nID == IDC_SPIN_HSCALE)
+ {
+ if (bUp)
+ td.scale[0] = 1 - m_fHScale;
+ else
+ td.scale[0] = 1 + m_fHScale;
+ }
+ else if (nID == IDC_SPIN_VSCALE)
+ {
+ if (bUp)
+ td.scale[1] = 1 - m_fVScale;
+ else
+ td.scale[1] = 1 + m_fVScale;
+ }
+
+ else if (nID == IDC_SPIN_HSHIFT)
+ {
+ if (bUp)
+ td.shift[0] = m_fHShift;
+ else
+ td.shift[0] = -m_fHShift;
+ }
+ else if (nID == IDC_SPIN_VSHIFT)
+ {
+ if (bUp)
+ td.shift[1] = m_fVShift;
+ else
+ td.shift[1] = -m_fVShift;
+ }
+
+ Patch_SetTextureInfo(&td);
+ Sys_UpdateWindows(W_CAMERA);
+}
+
+
diff --git a/q3radiant/PatchDialog.h b/q3radiant/PatchDialog.h
new file mode 100755
index 0000000..572acc9
--- /dev/null
+++ b/q3radiant/PatchDialog.h
@@ -0,0 +1,102 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_PATCHDIALOG_H__DE62DFB4_E9EC_11D2_A509_0020AFEB881A__INCLUDED_)
+#define AFX_PATCHDIALOG_H__DE62DFB4_E9EC_11D2_A509_0020AFEB881A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// PatchDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CPatchDialog dialog
+
+class CPatchDialog : public CDialog
+{
+ patchMesh_t *m_Patch;
+// Construction
+public:
+ void UpdateInfo();
+ void SetPatchInfo();
+ void GetPatchInfo();
+ CPatchDialog(CWnd* pParent = NULL); // standard constructor
+ void UpdateSpinners(bool bUp, int nID);
+
+// Dialog Data
+ //{{AFX_DATA(CPatchDialog)
+ enum { IDD = IDD_DIALOG_PATCH };
+ CSpinButtonCtrl m_wndVShift;
+ CSpinButtonCtrl m_wndVScale;
+ CSpinButtonCtrl m_wndRotate;
+ CSpinButtonCtrl m_wndHShift;
+ CSpinButtonCtrl m_wndHScale;
+ CComboBox m_wndType;
+ CComboBox m_wndRows;
+ CComboBox m_wndCols;
+ CString m_strName;
+ float m_fS;
+ float m_fT;
+ float m_fX;
+ float m_fY;
+ float m_fZ;
+ float m_fHScale;
+ float m_fHShift;
+ float m_fRotate;
+ float m_fVScale;
+ float m_fVShift;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPatchDialog)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ void UpdateRowColInfo();
+
+ // Generated message map functions
+ //{{AFX_MSG(CPatchDialog)
+ afx_msg void OnBtnPatchdetails();
+ afx_msg void OnBtnPatchfit();
+ afx_msg void OnBtnPatchnatural();
+ afx_msg void OnBtnPatchreset();
+ afx_msg void OnSelchangeComboCol();
+ afx_msg void OnSelchangeComboRow();
+ afx_msg void OnSelchangeComboType();
+ virtual void OnOK();
+ afx_msg void OnDeltaposSpin(NMHDR* pNMHDR, LRESULT* pResult);
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDestroy();
+ afx_msg void OnApply();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PATCHDIALOG_H__DE62DFB4_E9EC_11D2_A509_0020AFEB881A__INCLUDED_)
diff --git a/q3radiant/PlugIn.cpp b/q3radiant/PlugIn.cpp
new file mode 100755
index 0000000..7c19044
--- /dev/null
+++ b/q3radiant/PlugIn.cpp
@@ -0,0 +1,297 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PlugIn.cpp: implementation of the CPlugIn class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "PlugIn.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPlugIn::CPlugIn()
+{
+ m_hDLL = NULL;
+ m_pQERPlugEntitiesFactory = NULL;
+}
+
+CPlugIn::~CPlugIn()
+{
+ if (m_pQERPlugEntitiesFactory)
+ delete m_pQERPlugEntitiesFactory;
+ if (m_hDLL != NULL)
+ free();
+}
+
+bool CPlugIn::load(const char *p)
+{
+ m_hDLL = ::LoadLibrary(p);
+ if (m_hDLL != NULL)
+ {
+ m_pfnInit = reinterpret_cast<PFN_QERPLUG_INIT>(::GetProcAddress(m_hDLL, QERPLUG_INIT));
+ if (m_pfnInit != NULL)
+ {
+ m_strVersion = (*m_pfnInit)(AfxGetApp()->m_hInstance, g_pParentWnd->GetSafeHwnd());
+ Sys_Printf("Loaded plugin > %s\n", m_strVersion);
+
+ m_pfnGetName = reinterpret_cast<PFN_QERPLUG_GETNAME>(::GetProcAddress(m_hDLL, QERPLUG_GETNAME));
+ if (m_pfnGetName != NULL)
+ {
+ m_strName = (*m_pfnGetName)();
+ }
+
+ m_pfnGetCommandList = reinterpret_cast<PFN_QERPLUG_GETCOMMANDLIST>(::GetProcAddress(m_hDLL, QERPLUG_GETCOMMANDLIST));
+ if (m_pfnGetCommandList)
+ {
+ CString str = (*m_pfnGetCommandList)();
+ char cTemp[1024];
+ strcpy(cTemp, str);
+ char* token = strtok(cTemp, ",;");
+ if (token && *token == ' ')
+ {
+ while (*token == ' ')
+ token++;
+ }
+ while (token != NULL)
+ {
+ m_CommandStrings.Add(token);
+ token = strtok(NULL, ",;");
+ }
+ }
+
+ m_pfnDispatch = reinterpret_cast<PFN_QERPLUG_DISPATCH>(::GetProcAddress(m_hDLL, QERPLUG_DISPATCH));
+ m_pfnGetFuncTable = reinterpret_cast<PFN_QERPLUG_GETFUNCTABLE>(::GetProcAddress(m_hDLL, QERPLUG_GETFUNCTABLE));
+
+ m_pfnGetTextureInfo = reinterpret_cast<PFN_QERPLUG_GETTEXTUREINFO>(::GetProcAddress(m_hDLL, QERPLUG_GETTEXTUREINFO));
+ m_pfnLoadTexture = reinterpret_cast<PFN_QERPLUG_LOADTEXTURE>(::GetProcAddress(m_hDLL, QERPLUG_LOADTEXTURE));
+
+ m_pfnGetSurfaceFlags = reinterpret_cast<PFN_QERPLUG_GETSURFACEFLAGS>(::GetProcAddress(m_hDLL, QERPLUG_GETSURFACEFLAGS));
+
+ m_pfnRegisterPluginEntities = reinterpret_cast<PFN_QERPLUG_REGISTERPLUGINENTITIES>(::GetProcAddress(m_hDLL, QERPLUG_REGISTERPLUGINENTITIES));
+
+ m_pfnInitSurfaceProperties = reinterpret_cast<PFN_QERPLUG_INITSURFACEPROPERTIES>(::GetProcAddress(m_hDLL, QERPLUG_INITSURFACEPROPERTIES));
+
+ m_pfnRequestInterface = reinterpret_cast<PFN_QERPLUG_REQUESTINTERFACE>(::GetProcAddress(m_hDLL, QERPLUG_REQUESTINTERFACE));
+
+ return (m_pfnDispatch != NULL && m_pfnGetFuncTable != NULL);
+ //--return true;
+ }
+ Sys_Printf("FAILED to Load plugin > %s\n", p);
+ }
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL
+ );
+ Sys_Printf("LoadLibrary failed on %s: GetLastError: %s\n", p, lpMsgBuf );
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+ free();
+ return false;
+}
+
+_QERTextureInfo* CPlugIn::getTextureInfo()
+{
+ if (m_pfnGetTextureInfo != NULL)
+ {
+ return reinterpret_cast<_QERTextureInfo*>((*m_pfnGetTextureInfo)());
+ }
+ return NULL;
+}
+
+void CPlugIn::loadTexture(LPCSTR pFilename)
+{
+ if (m_pfnLoadTexture != NULL)
+ {
+ (*m_pfnLoadTexture)(pFilename);
+ }
+}
+
+LPVOID CPlugIn::getSurfaceFlags()
+{
+ if (m_pfnGetSurfaceFlags != NULL)
+ {
+ return reinterpret_cast<LPVOID>((*m_pfnGetSurfaceFlags)());
+ }
+ return NULL;
+}
+
+void CPlugIn::free()
+{
+ if (m_hDLL != NULL)
+ ::FreeLibrary(m_hDLL);
+ m_hDLL = NULL;
+}
+
+const char* CPlugIn::getVersionStr()
+{
+ return m_pfnGetName();
+}
+
+const char* CPlugIn::getMenuName()
+{
+ return m_strName;
+}
+
+int CPlugIn::getCommandCount()
+{
+ return m_CommandStrings.GetSize();
+}
+
+const char* CPlugIn::getCommand(int n)
+{
+ return m_CommandStrings.GetAt(n);
+}
+
+void CPlugIn::dispatchCommand(const char* p, vec3_t vMin, vec3_t vMax, BOOL bSingleBrush)
+{
+ if (m_pfnDispatch)
+ {
+ (*m_pfnDispatch)(p, vMin, vMax, bSingleBrush);
+ }
+}
+
+void CPlugIn::addMenuID(int n)
+{
+ m_CommandIDs.Add(n);
+}
+
+bool CPlugIn::ownsCommandID(int n)
+{
+ for (int i = 0; i < m_CommandIDs.GetSize(); i++)
+ {
+ if (m_CommandIDs.GetAt(i) == n)
+ return true;
+ }
+ return false;
+}
+
+void* CPlugIn::getFuncTable()
+{
+ if (m_pfnGetFuncTable)
+ {
+ return (*m_pfnGetFuncTable)();
+ }
+ return NULL;
+}
+
+void CPlugIn::RegisterPluginEntities()
+{
+ // if we found the QERPlug_RegisterPluginEntities export, it means this plugin provides his own entities
+ if (m_pfnRegisterPluginEntities)
+ {
+ // resquest a _QERPlugEntitiesFactory
+ if (m_pfnRequestInterface)
+ {
+ m_pQERPlugEntitiesFactory = new _QERPlugEntitiesFactory;
+ m_pQERPlugEntitiesFactory->m_nSize = sizeof(_QERPlugEntitiesFactory);
+ if (m_pfnRequestInterface( QERPlugEntitiesFactory_GUID, m_pQERPlugEntitiesFactory ))
+ {
+ // create an IEpair interface for the project settings
+ CEpairsWrapper *pProjectEp = new CEpairsWrapper( g_qeglobals.d_project_entity );
+ m_pfnRegisterPluginEntities( pProjectEp );
+ }
+ else
+ Sys_Printf( "WARNING: failed to request QERPlugEntitiesFactory from plugin %s\n", m_strName.GetBuffer(0) );
+ }
+ else
+ Sys_Printf( "WARNING: QERPlug_RequestInterface not found in %s\n", m_strName.GetBuffer(0) );
+ }
+}
+
+void CPlugIn::InitBSPFrontendPlugin()
+{
+ if (m_pfnRequestInterface)
+ {
+ // request a _QERPlugBSPFrontendTable
+ g_BSPFrontendTable.m_nSize = sizeof( _QERPlugBSPFrontendTable );
+ if ( m_pfnRequestInterface( QERPlugBSPFrontendTable_GUID, &g_BSPFrontendTable ) )
+ {
+ g_qeglobals.bBSPFrontendPlugin = true;
+ }
+ }
+}
+
+void CPlugIn::InitSurfacePlugin()
+{
+ // if we found the QERPlug_InitSurfaceProperties export, it means this plugin does surface properties
+ if (m_pfnInitSurfaceProperties)
+ {
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ Sys_Printf( "WARNING: conflict for surface properties plugins. %s ignored.\n", m_strName );
+ return;
+ }
+ if (m_pfnRequestInterface)
+ {
+ // call the plugin surface properties init
+ m_pfnInitSurfaceProperties();
+ // request filling of the global _QERPlugSurfaceTable
+ g_SurfaceTable.m_nSize = sizeof( g_SurfaceTable );
+ if ( m_pfnRequestInterface( QERPlugSurfaceTable_GUID, &g_SurfaceTable ) )
+ {
+ // update the global so we know we have a surface properties plugin
+ g_qeglobals.bSurfacePropertiesPlugin = true;
+ }
+ else
+ Sys_Printf( "WARNING: _QERPlugSurfaceTable interface request failed for surface plugin\n" );
+ }
+ else
+ Sys_Printf("WARNING: QERPlug_RequestInterface export not found in surface properties plugin.\n");
+ }
+}
+
+// create a plugin entity
+// e is the entity being created
+// e->eclass is the plugin eclass info
+// e->epairs will be accessed by the plugin entity through a IEpair interface
+IPluginEntity * CPlugIn::CreatePluginEntity(entity_t *e)
+{
+ if (m_pQERPlugEntitiesFactory)
+ {
+ // create an IEpair interface for e->epairs
+ CEpairsWrapper *pEp = new CEpairsWrapper( e );
+ IPluginEntity *pEnt = m_pQERPlugEntitiesFactory->m_pfnCreateEntity( e->eclass, pEp );
+ if ( pEnt )
+ return pEnt;
+ delete pEp;
+ return NULL;
+ }
+ Sys_Printf("WARNING: unexpected m_pQERPlugEntitiesFactory is NULL in CPlugin::CreatePluginEntity\n");
+ return NULL;
+}
diff --git a/q3radiant/PlugIn.h b/q3radiant/PlugIn.h
new file mode 100755
index 0000000..d534ae3
--- /dev/null
+++ b/q3radiant/PlugIn.h
@@ -0,0 +1,82 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PlugIn.h: interface for the CPlugIn class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PLUGIN_H__B501A832_5755_11D2_B084_00AA00A410FC__INCLUDED_)
+#define AFX_PLUGIN_H__B501A832_5755_11D2_B084_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CPlugIn : public CObject
+{
+private:
+ HMODULE m_hDLL;
+ PFN_QERPLUG_INIT m_pfnInit;
+ PFN_QERPLUG_GETNAME m_pfnGetName;
+ PFN_QERPLUG_GETCOMMANDLIST m_pfnGetCommandList;
+ PFN_QERPLUG_DISPATCH m_pfnDispatch;
+ PFN_QERPLUG_GETFUNCTABLE m_pfnGetFuncTable;
+ PFN_QERPLUG_GETTEXTUREINFO m_pfnGetTextureInfo;
+ PFN_QERPLUG_LOADTEXTURE m_pfnLoadTexture;
+ PFN_QERPLUG_GETSURFACEFLAGS m_pfnGetSurfaceFlags;
+ PFN_QERPLUG_REGISTERPLUGINENTITIES m_pfnRegisterPluginEntities;
+ PFN_QERPLUG_INITSURFACEPROPERTIES m_pfnInitSurfaceProperties;
+ PFN_QERPLUG_REQUESTINTERFACE m_pfnRequestInterface;
+ CWordArray m_CommandIDs;
+ CStringArray m_CommandStrings;
+ CString m_strName;
+ CString m_strVersion;
+
+ // for plugins that provide plugin entities
+ _QERPlugEntitiesFactory* m_pQERPlugEntitiesFactory;
+
+public:
+ void InitBSPFrontendPlugin();
+ IPluginEntity * CreatePluginEntity( entity_t * );
+ HMODULE GetDLLModule() { return m_hDLL; }
+ void InitSurfacePlugin();
+ void RegisterPluginEntities();
+ void* getFuncTable();
+ bool ownsCommandID(int n);
+ void addMenuID(int n);
+ CPlugIn();
+ virtual ~CPlugIn();
+ bool load(const char *p);
+ void free();
+ const char* getVersionStr();
+ const char* getMenuName();
+ int getCommandCount();
+ const char* getCommand(int n);
+ void dispatchCommand(const char* p, vec3_t vMin, vec3_t vMax, BOOL bSingleBrush);
+
+ _QERTextureInfo *getTextureInfo();
+ void loadTexture(LPCSTR pFilename);
+
+ LPVOID getSurfaceFlags();
+
+};
+
+#endif // !defined(AFX_PLUGIN_H__B501A832_5755_11D2_B084_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/PlugInManager.cpp b/q3radiant/PlugInManager.cpp
new file mode 100755
index 0000000..1a9e76a
--- /dev/null
+++ b/q3radiant/PlugInManager.cpp
@@ -0,0 +1,1665 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PlugInManager.cpp: implementation of the CPlugInManager class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "io.h"
+#include "Radiant.h"
+#include "PlugInManager.h"
+#include "PlugIn.h"
+#include "DialogInfo.h"
+#include "pakstuff.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPlugInManager::CPlugInManager()
+{
+ m_pTexturePlug = NULL;
+ m_pSurfaceListPlug = NULL;
+ PatchesMode = EActivePatches;
+}
+
+CPlugInManager::~CPlugInManager()
+{
+ Cleanup();
+}
+
+void CPlugInManager::Init(const char * pPath)
+{
+ Cleanup();
+
+ // set some globals
+ g_qeglobals.bSurfacePropertiesPlugin = false;
+ g_qeglobals.bBSPFrontendPlugin = false;
+
+ CString strPath(pPath);
+ strPath += "*.dll";
+
+ bool bGo = true;
+
+ struct _finddata_t fileinfo;
+ int handle = _findfirst (strPath, &fileinfo);
+ if (handle != -1)
+ {
+ do
+ {
+ strPath.Format("%s\\%s", pPath, fileinfo.name);
+ CPlugIn *pPlug = new CPlugIn();
+ if (pPlug->load(strPath))
+ {
+ if(FillFuncTable(pPlug)) // PGM
+ {
+ m_PlugIns.Add(pPlug);
+
+ pPlug->RegisterPluginEntities();
+
+ // if this thing handles surface properties
+ pPlug->InitSurfacePlugin();
+
+ // will test and init if it's a BSP frontend
+ pPlug->InitBSPFrontendPlugin();
+
+ g_pParentWnd->AddPlugInMenuItem(pPlug);
+
+ // if this thing handles textures
+ if (pPlug->getTextureInfo() != NULL)
+ {
+ this->m_pTexturePlug = pPlug;
+
+ // if this is a wad style texture extension, have it load everything now
+ if (pPlug->getTextureInfo()->m_bWadStyle)
+ {
+ CString strPath = ValueForKey(g_qeglobals.d_project_entity, "texturepath");
+ pPlug->loadTexture(strPath);
+ }
+ }
+
+ if (pPlug->getSurfaceFlags() != NULL)
+ {
+ this->m_pSurfaceListPlug = pPlug;
+ }
+ }
+ else
+ {
+ delete pPlug; // PGM
+ }
+ }
+ else
+ {
+ delete pPlug;
+ }
+ } while (_findnext( handle, &fileinfo ) != -1);
+ _findclose (handle);
+ }
+
+}
+
+void CPlugInManager::Cleanup()
+{
+ int i;
+ for (i = 0; i < m_PlugIns.GetSize(); i++)
+ {
+ CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
+ plug->free();
+ delete plug;
+ }
+ m_PlugIns.RemoveAll();
+
+ for (i = 0; i < m_BrushHandles.GetSize(); i++)
+ {
+ brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
+ Brush_Free(pb);
+ }
+ m_BrushHandles.RemoveAll();
+
+ for (i = 0; i < m_EntityHandles.GetSize(); i++)
+ {
+ entity_t *pe = reinterpret_cast<entity_t*>(m_EntityHandles.GetAt(i));
+ Entity_Free(pe);
+ }
+ m_EntityHandles.RemoveAll();
+
+ // patches
+ // these are linked into the map
+ m_PatchesHandles.RemoveAll();
+ // these patches were allocated by Radiant on plugin request
+ // if the list is not empty, it means either the plugin asked for allocation and never commited them to the map
+ // in which case we are supposed to delete them
+ // or it commited them but never called m_pfnReleasePatchHandles, in case the patches may have already been
+ // erased and we are trying a second time, therefore crashing ..
+ //++timo FIXME: for now I leave a leak warning, we'd need a table to keep track of commited patches
+#ifdef _DEBUG
+ if (m_PluginPatches.GetSize() != 0)
+ Sys_Printf("WARNING: m_PluginPatches.GetSize() != 0 in CPlugInManager::Cleanup, possible leak\n");
+#endif
+/* for (i = 0; i < m_PluginPatches.GetSize(); i++)
+ {
+ patchMesh_t *pMesh = reinterpret_cast<patchMesh_t*>(m_PluginPatches.GetAt(i));
+ if (pMesh->pSymbiot)
+ delete pMesh;
+ }
+ m_PluginPatches.RemoveAll(); */
+}
+
+void CPlugInManager::Dispatch(int n, const char * p)
+{
+ for (int i = 0; i < m_PlugIns.GetSize(); i++)
+ {
+ CPlugIn *plug = reinterpret_cast<CPlugIn*>(m_PlugIns.GetAt(i));
+ if (plug->ownsCommandID(n))
+ {
+ vec3_t vMin, vMax;
+ if (selected_brushes.next == &selected_brushes)
+ {
+ vMin[0] = vMin[1] = vMin[2] = 0;
+ VectorCopy(vMin, vMax);
+ }
+ else
+ {
+ Select_GetBounds (vMin, vMax);
+ }
+ plug->dispatchCommand(p, vMin, vMax, QE_SingleBrush(true)); // PGM -- added quiet
+ break;
+ }
+ }
+}
+
+// creates a dummy brush in the active brushes list
+// FIXME : is this one really USED ?
+void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
+ Entity_LinkBrush (world_entity, pBrush);
+ Brush_Build(pBrush);
+ Brush_AddToList (pBrush, &active_brushes);
+ Select_Brush(pBrush);
+ Sys_UpdateWindows(W_ALL);
+}
+
+LPVOID CPlugInManager::CreateBrushHandle()
+{
+ brush_t *pb = Brush_Alloc();
+ pb->numberId = g_nBrushId++;
+ m_BrushHandles.Add(pb);
+ return (LPVOID)pb;
+}
+
+void CPlugInManager::DeleteBrushHandle(void * vp)
+{
+ CPtrArray* pHandles[3];
+ pHandles[0] = &m_SelectedBrushHandles;
+ pHandles[1] = &m_ActiveBrushHandles;
+ pHandles[2] = &m_BrushHandles;
+
+ for (int j = 0; j < 3; j++)
+ {
+ for (int i = 0; i < pHandles[j]->GetSize(); i++)
+ {
+ brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
+ if (pb == reinterpret_cast<brush_t*>(vp))
+ {
+ if (j == 2)
+ {
+ // only remove it from the list if it is work area
+ // this allows the selected and active list indexes to remain constant
+ // throughout a session (i.e. between an allocate and release)
+ pHandles[j]->RemoveAt(i);
+ }
+ Brush_Free(pb);
+ Sys_MarkMapModified(); // PGM
+ return;
+ }
+ }
+ }
+}
+
+void CPlugInManager::CommitBrushHandleToMap(void * vp)
+{
+ g_bScreenUpdates = false;
+ for (int i = 0; i < m_BrushHandles.GetSize(); i++)
+ {
+ brush_t *pb = reinterpret_cast<brush_t*>(m_BrushHandles.GetAt(i));
+ if (pb == reinterpret_cast<brush_t*>(vp))
+ {
+ m_BrushHandles.RemoveAt(i);
+ Entity_LinkBrush (world_entity, pb);
+ Brush_Build(pb);
+ Brush_AddToList (pb, &active_brushes);
+ Select_Brush(pb);
+ }
+ }
+ g_bScreenUpdates = true;
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CPlugInManager::AddFaceToBrushHandle(void * vp, vec3_t v1, vec3_t v2, vec3_t v3)
+{
+ brush_t *bp = FindBrushHandle(vp);
+ if (bp != NULL)
+ {
+ face_t *f = Face_Alloc();
+ f->texdef = g_qeglobals.d_texturewin.texdef;
+ f->texdef.flags &= ~SURF_KEEP;
+ f->texdef.contents &= ~CONTENTS_KEEP;
+ f->next = bp->brush_faces;
+ bp->brush_faces = f;
+ VectorCopy (v1, f->planepts[0]);
+ VectorCopy (v2, f->planepts[1]);
+ VectorCopy (v3, f->planepts[2]);
+ }
+}
+
+brush_t* CPlugInManager::FindBrushHandle(void * vp)
+{
+ CPtrArray* pHandles[4];
+ pHandles[0] = &m_SelectedBrushHandles;
+ pHandles[1] = &m_ActiveBrushHandles;
+ pHandles[2] = &m_BrushHandles;
+ pHandles[3] = &m_EntityBrushHandles;
+
+ for (int j = 0; j < 4; j++)
+ {
+ for (int i = 0; i < pHandles[j]->GetSize(); i++)
+ {
+ brush_t *pb = reinterpret_cast<brush_t*>(pHandles[j]->GetAt(i));
+ if (pb == reinterpret_cast<brush_t*>(vp))
+ {
+ return pb;
+ }
+ }
+ }
+ return NULL;
+}
+
+patchMesh_t* CPlugInManager::FindPatchHandle(int index)
+{
+ switch (PatchesMode)
+ {
+ case EActivePatches:
+ case ESelectedPatches:
+ if ( index < m_PatchesHandles.GetSize() )
+ {
+ brush_t *pb = reinterpret_cast<brush_t *>(m_PatchesHandles.GetAt(index));
+ return pb->pPatch;
+ }
+#ifdef _DEBUG
+ Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
+#endif
+ break;
+ case EAllocatedPatches:
+ if ( index < m_PluginPatches.GetSize() )
+ {
+ patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>(m_PluginPatches.GetAt(index));
+ return pPatch;
+ }
+#ifdef _DEBUG
+ Sys_Printf("WARNING: out of bounds in CPlugInManager::FindPatchHandle\n");
+#endif
+ break;
+ }
+ return NULL;
+}
+
+LPVOID WINAPI QERApp_CreateBrushHandle()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ return g_pParentWnd->GetPlugInMgr().CreateBrushHandle();
+}
+
+void WINAPI QERApp_DeleteBrushHandle(LPVOID vp)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().DeleteBrushHandle(vp);
+}
+
+void WINAPI QERApp_CommitBrushHandleToMap(LPVOID vp)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().CommitBrushHandleToMap(vp);
+}
+
+void WINAPI QERApp_AddFace(LPVOID vp, vec3_t v1, vec3_t v2, vec3_t v3)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().AddFaceToBrushHandle(vp, v1, v2, v3);
+}
+
+void WINAPI QERApp_DeleteSelection()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Select_Delete();
+}
+
+void WINAPI QERApp_SysMsg(LPCSTR pMsg)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ CString str = pMsg;
+ Sys_Printf(str.GetBuffer(0));
+}
+
+// NOTE: called only in case of plugin error. We can try a plugin refresh instead of a straight crash ?
+void WINAPI QERApp_ErrorMsg(LPCSTR pMsg)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ CString str = pMsg;
+ Error(str.GetBuffer(0));
+}
+
+void WINAPI QERApp_InfoMsg(LPCSTR pMsg)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ ShowInfoDialog(pMsg);
+}
+
+void WINAPI QERApp_HideInfoMsg()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ HideInfoDialog();
+}
+
+//=====
+//PGM
+void WINAPI QERApp_PositionView(vec3_t v1, vec3_t v2)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->ActiveXY()->SetOrigin(v1);
+ // FIXME - implement this!
+ Sys_UpdateWindows(W_ALL);
+}
+//PGM
+//=====
+
+//FIXME: this AcquirePath stuff is pretty much a mess and needs cleaned up
+bool g_bPlugWait = false;
+bool g_bPlugOK = false;
+int g_nPlugCount = 0;
+
+void _PlugDone(bool b, int n)
+{
+ g_bPlugWait = false;
+ g_bPlugOK = b;
+ g_nPlugCount = n;
+}
+
+void WINAPI QERApp_GetPoints(int nMax, _QERPointData *pData, LPCSTR pMsg)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ ShowInfoDialog(pMsg);
+ g_bPlugWait = true;
+ g_bPlugOK = false;
+ g_nPlugCount = 0;
+// g_nPlugCount=nMax-1;
+ AcquirePath(nMax, &_PlugDone);
+ while (g_bPlugWait)
+ {
+ MSG msg;
+ if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ HideInfoDialog();
+
+ pData->m_nCount = 0;
+ pData->m_pVectors = NULL;
+
+ if (g_bPlugOK && g_nPlugCount > 0)
+ {
+ pData->m_nCount = g_nPlugCount;
+ pData->m_pVectors = reinterpret_cast<vec3_t*>(qmalloc(g_nPlugCount * sizeof(vec3_t)));
+ vec3_t *pOut = pData->m_pVectors;
+ for (int i = 0; i < g_nPlugCount; i++)
+ {
+ memcpy(pOut, &g_PathPoints[i],sizeof(vec3_t));
+ pOut++;
+ }
+ }
+}
+
+void WINAPI QERApp_AddFaceData(LPVOID pv, _QERFaceData *pData)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+
+ brush_t* pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ face_t *f = Face_Alloc();
+ f->texdef = g_qeglobals.d_texturewin.texdef;
+ f->texdef.flags = pData->m_nFlags;
+ f->texdef.contents = pData->m_nContents;
+ f->texdef.value = pData->m_nValue;
+ f->texdef.rotate = pData->m_fRotate;
+ f->texdef.shift[0] = pData->m_fShift[0];
+ f->texdef.shift[1] = pData->m_fShift[1];
+ f->texdef.scale[0] = pData->m_fScale[0];
+ f->texdef.scale[1] = pData->m_fScale[1];
+ //strcpy(f->texdef.name, pData->m_TextureName);
+ f->texdef.SetName(pData->m_TextureName);
+ f->next = pBrush->brush_faces;
+ pBrush->brush_faces = f;
+ VectorCopy (pData->m_v1, f->planepts[0]);
+ VectorCopy (pData->m_v2, f->planepts[1]);
+ VectorCopy (pData->m_v3, f->planepts[2]);
+ Sys_MarkMapModified(); // PGM
+ }
+}
+
+int WINAPI QERApp_GetFaceCount(LPVOID pv)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+ {
+ n++;
+ }
+ }
+ return n;
+}
+
+_QERFaceData* WINAPI QERApp_GetFaceData(LPVOID pv, int nFaceIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ static _QERFaceData face;
+ int n = 0;
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+
+ if (pBrush != NULL)
+ {
+ for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+ {
+
+#ifdef _DEBUG
+ if (!pBrush->brush_faces)
+ {
+ Sys_Printf( "Warning : pBrush->brush_faces is NULL in QERApp_GetFaceData\n" );
+ return NULL;
+ }
+#endif
+
+ if (n == nFaceIndex)
+ {
+ face.m_nContents = f->texdef.contents;
+ face.m_nFlags = f->texdef.flags;
+ face.m_fRotate = f->texdef.rotate;
+ face.m_fScale[0] = f->texdef.scale[0];
+ face.m_fScale[1] = f->texdef.scale[1];
+ face.m_fShift[0] = f->texdef.shift[0];
+ face.m_fShift[1] = f->texdef.shift[1];
+ face.m_nValue = f->texdef.value;
+ strcpy(face.m_TextureName, f->texdef.name);
+ VectorCopy(f->planepts[0], face.m_v1);
+ VectorCopy(f->planepts[1], face.m_v2);
+ VectorCopy(f->planepts[2], face.m_v3);
+ return &face;
+ }
+ n++;
+ }
+ }
+ return NULL;
+}
+
+void WINAPI QERApp_SetFaceData(LPVOID pv, int nFaceIndex, _QERFaceData *pData)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+
+ if (pBrush != NULL)
+ {
+ for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+ {
+ if (n == nFaceIndex)
+ {
+ f->texdef.flags = pData->m_nFlags;
+ f->texdef.contents = pData->m_nContents;
+ f->texdef.value = pData->m_nValue;
+ f->texdef.rotate = pData->m_fRotate;
+ f->texdef.shift[0] = pData->m_fShift[0];
+ f->texdef.shift[1] = pData->m_fShift[1];
+ f->texdef.scale[0] = pData->m_fScale[0];
+ f->texdef.scale[1] = pData->m_fScale[1];
+ //strcpy(f->texdef.name, pData->m_TextureName);
+ f->texdef.SetName(pData->m_TextureName);
+ VectorCopy(pData->m_v1, f->planepts[0]);
+ VectorCopy(pData->m_v2, f->planepts[1]);
+ VectorCopy(pData->m_v3, f->planepts[2]);
+ Sys_MarkMapModified(); // PGM
+ return; // PGM
+ }
+ n++;
+ }
+ }
+}
+
+void WINAPI QERApp_DeleteFace(LPVOID pv, int nFaceIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ face_t *pPrev = pBrush->brush_faces;
+ for (face_t *f = pBrush->brush_faces; f; f = f->next)
+ {
+ if (n == nFaceIndex)
+ {
+ pPrev->next = f->next;
+ Face_Free (f);
+ Sys_MarkMapModified(); // PGM
+ return;
+ }
+ n++;
+ pPrev = f;
+ }
+ }
+}
+
+//==========
+//PGM
+void WINAPI QERApp_BuildBrush (LPVOID pv)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ Brush_Build(pBrush);
+ Sys_UpdateWindows(W_ALL);
+ }
+}
+
+//Timo : another version with bConvert flag
+//++timo since 1.7 is not compatible with earlier plugin versions, remove this one and update QERApp_BuildBrush
+void WINAPI QERApp_BuildBrush2 (LPVOID pv, int bConvert)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ Brush_Build( pBrush, true, true, bConvert );
+ Sys_UpdateWindows(W_ALL);
+ }
+}
+
+void WINAPI QERApp_SelectBrush (LPVOID pv)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ Select_Brush(pBrush, false);
+ Sys_UpdateWindows(W_ALL);
+ }
+
+}
+
+void WINAPI QERApp_DeselectBrush (LPVOID pv)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ // FIXME - implement this!
+}
+
+void WINAPI QERApp_ResetPlugins()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->OnPluginsRefresh();
+}
+
+void WINAPI QERApp_DeselectAllBrushes ()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Select_Deselect();
+ Sys_UpdateWindows(W_ALL);
+}
+//PGM
+//==========
+
+void WINAPI QERApp_TextureBrush(LPVOID pv, LPCSTR pName)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ brush_t *pBrush = g_pParentWnd->GetPlugInMgr().FindBrushHandle(pv);
+ if (pBrush != NULL)
+ {
+ for (face_t *f = pBrush->brush_faces ; f; f = f->next)
+ {
+ //strcpy(f->texdef.name, pName);
+ f->texdef.SetName(pName);
+ }
+ Sys_MarkMapModified(); // PGM
+ }
+}
+
+int WINAPI QERApp_SelectedBrushCount()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ n++;
+ }
+ return n;
+}
+
+int WINAPI QERApp_ActiveBrushCount()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+ {
+ n++;
+ }
+ return n;
+}
+
+int WINAPI QERApp_AllocateSelectedBrushHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ n++;
+ g_pParentWnd->GetPlugInMgr().GetSelectedHandles().Add(pb);
+ }
+ return n;
+}
+
+int WINAPI QERApp_AllocateActiveBrushHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+ {
+ n++;
+ g_pParentWnd->GetPlugInMgr().GetActiveHandles().Add(pb);
+ }
+ return n;
+}
+
+void WINAPI QERApp_ReleaseSelectedBrushHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().GetSelectedHandles().RemoveAll();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void WINAPI QERApp_ReleaseActiveBrushHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().GetActiveHandles().RemoveAll();
+ Sys_UpdateWindows(W_ALL);
+}
+
+LPVOID WINAPI QERApp_GetActiveBrushHandle(int nIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (nIndex < g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetSize())
+ {
+ return reinterpret_cast<LPVOID>(g_pParentWnd->GetPlugInMgr().GetActiveHandles().GetAt(nIndex));
+ }
+ return NULL;
+}
+
+LPVOID WINAPI QERApp_GetSelectedBrushHandle(int nIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (nIndex < g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetSize())
+ {
+ return reinterpret_cast<LPVOID>(g_pParentWnd->GetPlugInMgr().GetSelectedHandles().GetAt(nIndex));
+ }
+ return NULL;
+}
+
+int WINAPI QERApp_TextureCount()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ Texture_StartPos ();
+ int x, y;
+ int n = 0;
+ while (1)
+ {
+ qtexture_t *q = Texture_NextPos (&x, &y);
+ if (!q)
+ break;
+ n++;
+ }
+ return n;
+}
+
+LPCSTR WINAPI QERApp_GetTexture(int nIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ static char name[QER_MAX_NAMELEN];
+ Texture_StartPos ();
+ int x, y;
+ int n = 0;
+ while (1)
+ {
+ qtexture_t *q = Texture_NextPos (&x, &y);
+ if (!q)
+ break;
+ if (n == nIndex)
+ {
+ strcpy(name, q->name);
+ return name;
+ }
+ n++;
+ }
+ return NULL;
+}
+
+LPCSTR WINAPI QERApp_GetCurrentTexture()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ return g_qeglobals.d_texturewin.texdef.name;
+}
+
+void WINAPI QERApp_SetCurrentTexture(LPCSTR strName)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ //++timo hu ?? tex is not initialized ?? can be any value ..
+ texdef_t tex;
+ //++timo added a brushprimit_texdef ..
+ // smthg to be done here
+ brushprimit_texdef_t brushprimit_tex;
+ //strcpy(tex.name, strName);
+ tex.SetName(strName);
+ Texture_SetTexture(&tex,&brushprimit_tex);
+}
+
+int WINAPI QERApp_GetEClassCount()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ for (eclass_t *e = eclass ; e ; e = e->next)
+ {
+ n++;
+ }
+ return n;
+}
+
+LPCSTR WINAPI QERApp_GetEClass(int nIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 0;
+ for (eclass_t *e = eclass ; e ; e = e->next)
+ {
+ if (n == nIndex)
+ {
+ return e->name;
+ }
+ }
+ return NULL;
+}
+
+void WINAPI QERApp_LoadTextureRGBA(LPVOID vp)
+{
+ Texture_LoadFromPlugIn(vp);
+}
+
+// v1.70 code
+// world_entity holds the worldspawn and is indexed as 0
+// other entities are in the entities doubly linked list
+// QERApp_GetEntityCount counts the entities like in any C array: [0..length-1]
+int WINAPI QERApp_GetEntityCount()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ int n = 1;
+ for (entity_t *pe = entities.next ; pe != &entities ; pe = pe->next)
+ {
+ n++;
+ }
+ return n;
+}
+
+// We don't store entities in CPtrArray, we need to walk the list
+LPVOID WINAPI QERApp_GetEntityHandle(int nIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (nIndex==0)
+ // looks for the worldspawn
+ return static_cast<LPVOID>(world_entity);
+ entity_t *pe = &entities;
+ int n = 0;
+ while ( n < nIndex )
+ {
+ pe = pe->next;
+ n++;
+ }
+ return static_cast<LPVOID>(pe);
+}
+
+epair_t** WINAPI QERApp_GetEntityKeyValList(LPVOID vp)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ entity_t *pe = static_cast<entity_t *>(vp);
+ return &pe->epairs;
+}
+
+epair_t* WINAPI QERApp_AllocateEpair( char *key, char *val )
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ epair_t *e = (epair_t*)qmalloc (sizeof(*e));
+ e->key = (char*)qmalloc(strlen(key)+1);
+ strcpy (e->key, key);
+ e->value = (char*)qmalloc(strlen(val)+1);
+ strcpy (e->value, val);
+ return e;
+}
+
+void WINAPI QERApp_SetEntityKeyValList(LPVOID vp, epair_t* ep)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ entity_t *pe = static_cast<entity_t *>(vp);
+ if (pe->epairs)
+ Sys_Printf( "Warning : pe->epairs != NULL in QERApp_SetEntityKeyValList, will not set\n" );
+ else
+ pe->epairs = ep;
+}
+
+int WINAPI QERApp_AllocateEntityBrushHandles(LPVOID vp)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ entity_t *pe = static_cast<entity_t *>(vp);
+ int n = 0;
+ if (!pe->brushes.onext)
+ return 0;
+ g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
+ for (brush_t *pb = pe->brushes.onext ; pb != &pe->brushes ; pb=pb->onext)
+ {
+ n++;
+ g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().Add(pb);
+ }
+ return n;
+}
+
+void WINAPI QERApp_ReleaseEntityBrushHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().RemoveAll();
+}
+
+LPVOID WINAPI QERApp_GetEntityBrushHandle(int nIndex)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ if (nIndex < g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetSize())
+ return g_pParentWnd->GetPlugInMgr().GetEntityBrushHandles().GetAt(nIndex);
+ return NULL;
+}
+
+LPVOID WINAPI QERApp_CreateEntityHandle()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ entity_t *pe = reinterpret_cast<entity_t*>(qmalloc(sizeof(entity_t)));
+ pe->brushes.onext = pe->brushes.oprev = &pe->brushes;
+ g_pParentWnd->GetPlugInMgr().GetEntityHandles().Add(static_cast<LPVOID>(pe));
+ return static_cast<LPVOID>(pe);
+}
+
+// the vpBrush needs to be in m_BrushHandles
+//++timo we don't have allocation nor storage for vpEntity, no checks for this one
+void WINAPI QERApp_CommitBrushHandleToEntity(LPVOID vpBrush, LPVOID vpEntity)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().CommitBrushHandleToEntity(vpBrush, vpEntity);
+ return;
+}
+
+char* WINAPI QERApp_ReadProjectKey(char* key)
+{
+ return ValueForKey(g_qeglobals.d_project_entity, key);
+}
+
+int WINAPI QERApp_ScanFileForEClass(char *filename )
+{
+ // set single class parsing
+ parsing_single = true;
+ Eclass_ScanFile(filename);
+ if (eclass_found)
+ {
+ eclass_e->nShowFlags |= ECLASS_PLUGINENTITY;
+ return 1;
+ }
+ return 0;
+}
+
+// the vpBrush needs to be in m_BrushHandles
+//++timo add a debug check to see if we found the brush handle
+// NOTE : seems there's no way to check vpEntity is valid .. this is dangerous
+// links the brush to its entity, everything else is done when commiting the entity to the map
+void CPlugInManager::CommitBrushHandleToEntity(LPVOID vpBrush, LPVOID vpEntity)
+{
+ brush_t* pb;
+ entity_t* pe;
+ for (int i=0 ; i < m_BrushHandles.GetSize() ; i++)
+ {
+ if (vpBrush == m_BrushHandles.GetAt(i))
+ {
+ m_BrushHandles.RemoveAt(i);
+ pb = reinterpret_cast<brush_t*>(vpBrush);
+ pe = reinterpret_cast<entity_t *>(vpEntity);
+ Entity_LinkBrush (pe, pb);
+ }
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+// the vpEntity must be in m_EntityHandles
+void WINAPI QERApp_CommitEntityHandleToMap(LPVOID vpEntity)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().CommitEntityHandleToMap(vpEntity);
+ return;
+}
+
+int WINAPI QERApp_LoadFile( const char *pLocation, void ** buffer )
+{
+ char cPath[1024];
+ sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
+ int nSize = LoadFile( cPath, buffer);
+ if (nSize == -1)
+ {
+ nSize = PakLoadAnyFile(cPath, buffer);
+ }
+ return nSize;
+}
+
+char * WINAPI QERApp_ExpandReletivePath (char *p)
+{
+ return ExpandReletivePath(p);
+}
+
+// NOTE: this is a simplified version
+int WINAPI QERApp_HasShader( const char *pName )
+{
+ CShaderInfo *pInfo = hasShader( pName );
+ if (pInfo)
+ return 1;
+ return 0;
+}
+
+qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
+{
+ // if the texture is not loaded yet, this call will get it loaded
+ // but: when we assign a GL bind number, we need to be in the g_qeglobals.d_hdcBase , g_qeglobals.d_hglrcBase GL context
+ // the plugin may set the GL context to whatever he likes, but then load would fail
+ // NOTE: is context switching time-consuming? then maybe the plugin could handle the context switch and only add a
+ // sanity check in debug mode here
+ // read current context
+ HDC pluginHDC = qwglGetCurrentDC();
+ HGLRC pluginHGLRC = qwglGetCurrentContext();
+ qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase );
+ qtexture_t* qtex = Texture_ForName( name );
+ return qtex;
+ qwglMakeCurrent( pluginHDC, pluginHGLRC );
+}
+
+void WINAPI QERApp_RadiantFree( void * buf )
+{
+ free( buf );
+}
+
+char* WINAPI QERApp_Token()
+{
+ return token;
+}
+
+char* WINAPI QERApp_GetMapName()
+{
+ return currentmap;
+}
+
+void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity)
+{
+ entity_t *pe;
+ eclass_t *e;
+ brush_t *b;
+ vec3_t mins,maxs;
+ bool has_brushes;
+ for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
+ {
+ if (vpEntity == m_EntityHandles.GetAt(i))
+ {
+ m_EntityHandles.RemoveAt(i);
+ pe = reinterpret_cast<entity_t*>(vpEntity);
+ // fill additional fields
+ // straight copy from Entity_Parse
+ // entity_t::origin
+ GetVectorForKey (pe, "origin", pe->origin);
+ // entity_t::eclass
+ if (pe->brushes.onext == &pe->brushes)
+ has_brushes = false;
+ else
+ has_brushes = true;
+ e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
+ pe->eclass = e;
+ // fixedsize
+ if (e->fixedsize)
+ {
+ if (pe->brushes.onext != &pe->brushes)
+ {
+ Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
+ }
+ // create a custom brush
+ VectorAdd(e->mins, pe->origin, mins);
+ VectorAdd(e->maxs, pe->origin, maxs);
+ float a = 0;
+ if (e->nShowFlags & ECLASS_MISCMODEL)
+ {
+ char* p = ValueForKey(pe, "model");
+ if (p != NULL && strlen(p) > 0)
+ {
+ vec3_t vMin, vMax;
+ a = FloatForKey (pe, "angle");
+ if (GetCachedModel(pe, p, vMin, vMax))
+ {
+ // create a custom brush
+ VectorAdd (pe->md3Class->mins, pe->origin, mins);
+ VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
+ }
+ }
+ }
+
+ b = Brush_Create (mins, maxs, &e->texdef);
+
+ if (a)
+ {
+ vec3_t vAngle;
+ vAngle[0] = vAngle[1] = 0;
+ vAngle[2] = a;
+ Brush_Rotate(b, vAngle, pe->origin, false);
+ }
+
+ b->owner = pe;
+
+ b->onext = pe->brushes.onext;
+ b->oprev = &pe->brushes;
+ pe->brushes.onext->oprev = b;
+ pe->brushes.onext = b;
+ }
+ else
+ { // brush entity
+ if (pe->brushes.next == &pe->brushes)
+ Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
+ }
+
+ // add brushes to the active brushes list
+ // and build them along the way
+ for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
+ {
+ // convert between old brushes and brush primitive
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // we only filled the shift scale rot fields, needs conversion
+ Brush_Build( b, true, true, true );
+ }
+ else
+ {
+ // we are using old brushes
+ Brush_Build( b );
+ }
+ b->next = active_brushes.next;
+ active_brushes.next->prev = b;
+ b->prev = &active_brushes;
+ active_brushes.next = b;
+ }
+
+ // handle worldspawn entities
+ // if worldspawn has no brushes, use the new one
+ if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
+ {
+ if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
+ {
+ // worldspawn already has brushes
+ Sys_Printf ("Commiting worldspawn as func_group\n");
+ SetKeyValue(pe, "classname", "func_group");
+ // add the entity to the end of the entity list
+ pe->next = &entities;
+ pe->prev = entities.prev;
+ entities.prev->next = pe;
+ entities.prev = pe;
+ g_qeglobals.d_num_entities++;
+ }
+ else
+ {
+ // there's a worldspawn with no brushes, we assume the map is empty
+ if ( world_entity )
+ {
+ Entity_Free( world_entity );
+ world_entity = pe;
+ }
+ else
+ Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
+ }
+ }
+ else
+ {
+ // add the entity to the end of the entity list
+ pe->next = &entities;
+ pe->prev = entities.prev;
+ entities.prev->next = pe;
+ entities.prev = pe;
+ g_qeglobals.d_num_entities++;
+ }
+ }
+ }
+}
+
+void WINAPI QERApp_SetScreenUpdate(int bScreenUpdates)
+{
+ g_bScreenUpdates = bScreenUpdates;
+}
+
+texturewin_t* WINAPI QERApp_QeglobalsTexturewin()
+{
+ return &g_qeglobals.d_texturewin;
+}
+
+_QERTextureInfo* CPlugInManager::GetTextureInfo()
+{
+ if (m_pTexturePlug != NULL)
+ {
+ return m_pTexturePlug->getTextureInfo();
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+LPVOID CPlugInManager::GetSurfaceFlags()
+{
+ if (m_pSurfaceListPlug != NULL)
+ {
+ return m_pSurfaceListPlug->getSurfaceFlags();
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void CPlugInManager::LoadTexture(const char *pFilename)
+{
+ if (m_pTexturePlug != NULL)
+ {
+ m_pTexturePlug->loadTexture(pFilename);
+ }
+}
+
+patchMesh_t* WINAPI QERApp_GetSelectedPatch( )
+{
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ return pb->pPatch;
+ }
+ }
+#ifdef _DEBUG
+ Sys_Printf("WARNING: QERApp_GetSelectedPatchTexdef called with no patch selected\n");
+#endif
+ return NULL;
+}
+
+char* WINAPI QERApp_GetGamePath()
+{
+ return g_PrefsDlg.m_strQuake2.GetBuffer(0);
+}
+
+char* WINAPI QERApp_GetQERPath()
+{
+ return g_strAppPath.GetBuffer(0);
+}
+
+// patches in/out -----------------------------------
+int WINAPI QERApp_AllocateActivePatchHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ return g_pParentWnd->GetPlugInMgr().AllocateActivePatchHandles();
+}
+
+int CPlugInManager::AllocateActivePatchHandles()
+{
+ int n = 0;
+ for (brush_t *pb = active_brushes.next ; pb != &active_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ n++;
+ m_PatchesHandles.Add(pb);
+ }
+ }
+ return n;
+}
+
+int WINAPI QERApp_AllocateSelectedPatchHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ return g_pParentWnd->GetPlugInMgr().AllocateSelectedPatchHandles();
+}
+
+int CPlugInManager::AllocateSelectedPatchHandles()
+{
+ int n = 0;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ n++;
+ m_PatchesHandles.Add(pb);
+ }
+ }
+ return n;
+}
+
+void WINAPI QERApp_ReleasePatchHandles()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().ReleasePatchesHandles();
+}
+
+patchMesh_t* WINAPI QERApp_GetPatchData(int index)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ static patchMesh_t patch;
+ patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
+ if (pPatch)
+ {
+ memcpy( &patch, pPatch, sizeof(patchMesh_t) );
+ return &patch;
+ }
+ return NULL;
+}
+
+void WINAPI QERApp_DeletePatch(int index)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ patchMesh_t *pPatch = g_pParentWnd->GetPlugInMgr().FindPatchHandle(index);
+ if (pPatch)
+ {
+ brush_t *pb = pPatch->pSymbiot;
+ Patch_Delete( pPatch );
+ if (pb)
+ Brush_Free( pb );
+ }
+#ifdef _DEBUG
+ Sys_Printf("Warning: QERApp_DeletePatch: FindPatchHandle failed\n");
+#endif
+}
+
+int WINAPI QERApp_CreatePatchHandle()
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ return g_pParentWnd->GetPlugInMgr().CreatePatchHandle();
+}
+
+int CPlugInManager::CreatePatchHandle()
+{
+ // NOTE: we can't call the AddBrushForPatch until we have filled the patchMesh_t structure
+ patchMesh_t *pPatch = MakeNewPatch();
+ m_PluginPatches.Add( pPatch );
+ // change mode
+ PatchesMode = EAllocatedPatches;
+ return m_PluginPatches.GetSize()-1;
+}
+
+void WINAPI QERApp_CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
+{
+ AFX_MANAGE_STATE(AfxGetStaticModuleState());
+ g_pParentWnd->GetPlugInMgr().CommitPatchHandleToMap(index, pMesh, texName);
+}
+
+void CPlugInManager::CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName)
+{
+ if (PatchesMode==EAllocatedPatches)
+ {
+ patchMesh_t *pPatch = reinterpret_cast<patchMesh_t *>( m_PluginPatches.GetAt(index) );
+ memcpy( pPatch, pMesh, sizeof( patchMesh_t ) );
+ // patch texturing, if none given use current texture
+ if (texName)
+ pPatch->d_texture = Texture_ForName(texName);
+ if ( !pPatch->d_texture )
+ {
+ pPatch->d_texture = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
+ // checking .. just in case
+ if (!pPatch->d_texture)
+ {
+#ifdef _DEBUG
+ Sys_Printf("WARNING: failed to set patch to current texture in CPlugInManager::CommitPatchHandleToMap\n");
+#endif
+ pPatch->d_texture = notexture;
+ }
+ }
+ g_bScreenUpdates = false;
+ // the bLinkToWorld flag in AddBrushForPatch takes care of Brush_AddToList Entity_linkBrush and Brush_Build
+ brush_t *pb = AddBrushForPatch( pPatch, true );
+ Select_Brush( pb );
+ g_bScreenUpdates = true;
+ Sys_UpdateWindows(W_ALL);
+ }
+ else
+ {
+ brush_t *pBrush = reinterpret_cast<brush_t *>( m_PatchesHandles.GetAt(index) );
+ patchMesh_t *pPatch = pBrush->pPatch;
+ pPatch->width = pMesh->width;
+ pPatch->height = pMesh->height;
+ pPatch->contents = pMesh->contents;
+ pPatch->flags = pMesh->flags;
+ pPatch->value = pMesh->value;
+ pPatch->type = pMesh->type;
+ memcpy( pPatch->ctrl, pMesh->ctrl, sizeof(drawVert_t)*MAX_PATCH_HEIGHT*MAX_PATCH_WIDTH );
+ pPatch->bDirty = true;
+ }
+}
+
+// this gets called when the plugin needs specific services, for example the OpenGL drawing interface
+//++timo plugins should be able to dynamically register their own interfaces in there
+int WINAPI QERApp_RequestInterface( REFGUID refGUID, LPVOID pInterface )
+{
+ if (IsEqualGUID( refGUID, QERQglTable_GUID ))
+ {
+ _QERQglTable *pQglTable = static_cast<_QERQglTable *>(pInterface);
+ if ( pQglTable->m_nSize != sizeof(_QERQglTable) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERQglTable interface\n");
+ return 0;
+ }
+ pQglTable->m_pfn_qglAlphaFunc = qglAlphaFunc;
+ pQglTable->m_pfn_qglBegin = qglBegin;
+ pQglTable->m_pfn_qglBindTexture = qglBindTexture;
+ pQglTable->m_pfn_qglBlendFunc = qglBlendFunc;
+ pQglTable->m_pfn_qglCallList = qglCallList;
+ pQglTable->m_pfn_qglCallLists = qglCallLists;
+ pQglTable->m_pfn_qglClear = qglClear;
+ pQglTable->m_pfn_qglClearColor = qglClearColor;
+ pQglTable->m_pfn_qglClearDepth = qglClearDepth;
+ pQglTable->m_pfn_qglColor3f = qglColor3f;
+ pQglTable->m_pfn_qglColor4f = qglColor4f;
+ pQglTable->m_pfn_qglCullFace = qglCullFace;
+ pQglTable->m_pfn_qglDisable = qglDisable;
+ pQglTable->m_pfn_qglDeleteLists = qglDeleteLists;
+ pQglTable->m_pfn_qglEnable = qglEnable;
+ pQglTable->m_pfn_qglEnd = qglEnd;
+ pQglTable->m_pfn_qglEndList = qglEndList;
+ pQglTable->m_pfn_qglGenLists = qglGenLists;
+ pQglTable->m_pfn_qglListBase = qglListBase;
+ pQglTable->m_pfn_qglLoadIdentity = qglLoadIdentity;
+ pQglTable->m_pfn_qglMatrixMode = qglMatrixMode;
+ pQglTable->m_pfn_qglNewList = qglNewList;
+ pQglTable->m_pfn_qglNormal3f = qglNormal3f;
+ pQglTable->m_pfn_qglOrtho = qglOrtho;
+ pQglTable->m_pfn_qglPointSize = qglPointSize;
+ pQglTable->m_pfn_qglPolygonMode = qglPolygonMode;
+ pQglTable->m_pfn_qglPopMatrix = qglPopMatrix;
+ pQglTable->m_pfn_qglPushMatrix = qglPushMatrix;
+ pQglTable->m_pfn_qglRotated = qglRotated;
+ pQglTable->m_pfn_qglRotatef = qglRotatef;
+ pQglTable->m_pfn_qglScalef = qglScalef;
+ pQglTable->m_pfn_qglTexCoord2f = qglTexCoord2f;
+ pQglTable->m_pfn_qglTexEnvf = qglTexEnvf;
+ pQglTable->m_pfn_qglTexGenf = qglTexGenf;
+ pQglTable->m_pfn_qglTexParameterf = qglTexParameterf;
+ pQglTable->m_pfn_qglTranslated = qglTranslated;
+ pQglTable->m_pfn_qglTranslatef = qglTranslatef;
+ pQglTable->m_pfn_qglVertex2f = qglVertex2f;
+ pQglTable->m_pfn_qglVertex3f = qglVertex3f;
+ pQglTable->m_pfn_qglViewport = qglViewport;
+ pQglTable->m_pfn_QE_CheckOpenGLForErrors = &QE_CheckOpenGLForErrors;
+ pQglTable->m_pfn_QEW_SetupPixelFormat = &QEW_SetupPixelFormat;
+ pQglTable->m_pfn_qwglCreateContext = qwglCreateContext;
+ pQglTable->m_pfn_qwglDeleteContext = qwglDeleteContext;
+ pQglTable->m_pfn_qwglMakeCurrent = qwglMakeCurrent;
+ pQglTable->m_pfn_qwglShareLists = qwglShareLists;
+ pQglTable->m_pfn_qwglSwapBuffers = qwglSwapBuffers;
+ pQglTable->m_pfn_qwglUseFontBitmaps = qwglUseFontBitmaps;
+ pQglTable->m_pfnGetQeglobalsHGLRC = &QERApp_GetQeglobalsHGLRC;
+ pQglTable->m_pfn_qgluPerspective = qgluPerspective;
+ pQglTable->m_pfn_qgluLookAt = qgluLookAt;
+ pQglTable->m_pfnHookXYGLWindow = QERApp_HookXYGLWindow;
+ pQglTable->m_pfnUnHookGLWindow = QERApp_UnHookGLWindow;
+
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERSelectedFaceTable_GUID ))
+ {
+ _QERSelectedFaceTable *pSelectedFaceTable = static_cast<_QERSelectedFaceTable *>(pInterface);
+ if ( pSelectedFaceTable->m_nSize != sizeof(_QERSelectedFaceTable) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERSelectedFaceTable interface\n");
+ return 0;
+ }
+ pSelectedFaceTable->m_pfnGetTextureNumber = &QERApp_ISelectedFace_GetTextureNumber;
+ pSelectedFaceTable->m_pfnGetFaceInfo = &QERApp_GetFaceInfo;
+ pSelectedFaceTable->m_pfnSetFaceInfo = &QERApp_SetFaceInfo;
+ pSelectedFaceTable->m_pfnGetTextureSize = &QERApp_GetTextureSize;
+ pSelectedFaceTable->m_pfnTextureForName = &QERApp_Texture_ForName;
+ pSelectedFaceTable->m_pfnSelect_SetTexture = &Select_SetTexture;
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERPluginEntitiesTable_GUID ))
+ {
+ _QERPluginEntitiesTable *pPluginEntitiesTable = static_cast<_QERPluginEntitiesTable *>(pInterface);
+ if ( pPluginEntitiesTable->m_nSize != sizeof(_QERPluginEntitiesTable) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERPluginEntitiesTable interface\n");
+ return 0;
+ }
+ pPluginEntitiesTable->m_pfnEClassScanDir = &QERApp_EClassScanDir;
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERScripLibTable_GUID ))
+ {
+ _QERScripLibTable *pScripLibTable = static_cast<_QERScripLibTable *>(pInterface);
+ if ( pScripLibTable->m_nSize != sizeof( _QERScripLibTable ) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERScripLibTable\n");
+ return 0;
+ }
+ pScripLibTable->m_pfnGetToken = &GetToken;
+ pScripLibTable->m_pfnToken = &QERApp_Token;
+ pScripLibTable->m_pfnUnGetToken = &UngetToken;
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERAppSurfaceTable_GUID ))
+ {
+ _QERAppSurfaceTable *pSurfaceTable = static_cast<_QERAppSurfaceTable *>(pInterface);
+ if ( pSurfaceTable->m_nSize != sizeof( _QERAppSurfaceTable ) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERAppSurfaceTable\n");
+ return 0;
+ }
+ pSurfaceTable->m_pfnAnyPatchesSelected = &AnyPatchesSelected;
+ pSurfaceTable->m_pfnOnlyPatchesSelected = &OnlyPatchesSelected;
+ pSurfaceTable->m_pfnQeglobalsTexturewin = &QERApp_QeglobalsTexturewin;
+ pSurfaceTable->m_pfnGetSelectedPatch = &QERApp_GetSelectedPatch;
+ pSurfaceTable->m_pfnPatchRebuild = &Patch_Rebuild;
+ pSurfaceTable->m_pfnGetTwoSelectedPatch = &QERApp_GetTwoSelectedPatch;
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERAppBSPFrontendTable_GUID ))
+ {
+ _QERAppBSPFrontendTable *pBSPFrontendTable = static_cast<_QERAppBSPFrontendTable *>(pInterface);
+ if ( pBSPFrontendTable->m_nSize != sizeof( _QERAppBSPFrontendTable ) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERAppBSPFrontendTable\n");
+ return 0;
+ }
+ pBSPFrontendTable->m_pfnGetMapName = &QERApp_GetMapName;
+ pBSPFrontendTable->m_pfnLoadPointFile = &Pointfile_Check;
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERMessaging_GUID ))
+ {
+ _QERMessagingTable *pMessagingTable = static_cast<_QERMessagingTable *>(pInterface);
+ if ( pMessagingTable->m_nSize != sizeof( _QERMessagingTable ) )
+ {
+ Sys_Printf("wrong m_nSize in plugin-requested _QERMessagingTable\n");
+ return 0;
+ }
+ pMessagingTable->m_pfnHookWindow = QERApp_HookWindow;
+ pMessagingTable->m_pfnUnHookWindow = QERApp_UnHookWindow;
+ pMessagingTable->m_pfnGetXYWndWrapper = QERApp_GetXYWndWrapper;
+ pMessagingTable->m_pfnHookListener = QERApp_HookListener;
+ pMessagingTable->m_pfnUnHookListener = QERApp_UnHookListener;
+ return 1;
+ }
+ else if (IsEqualGUID( refGUID, QERShadersTable_GUID ))
+ {
+ _QERShadersTable *pShadersTable = static_cast<_QERShadersTable *>(pInterface);
+ if ( pShadersTable->m_nSize != sizeof( _QERShadersTable ) )
+ {
+ Sys_Printf("wring m_nSize in plugin-requested _QERShadersTable\n");
+ return 0;
+ }
+ pShadersTable->m_pfnTryTextureForName = QERApp_TryTextureForName;
+ return 1;
+ }
+ return 0;
+}
+
+int CPlugInManager::FillFuncTable(CPlugIn *pPlug)
+{
+ _QERFuncTable_1 *pTable = reinterpret_cast<_QERFuncTable_1*>(pPlug->getFuncTable());
+ if (pTable != NULL)
+ {
+ if (pTable->m_fVersion != QER_PLUG_VERSION)
+ {
+ Sys_Printf("Radiant plugin manager was built with version %.2f, Plugin %s is version %.2f\n", QER_PLUG_VERSION, pPlug->getVersionStr() , pTable->m_fVersion);
+ }
+ if (pTable->m_fVersion >= QER_PLUG_VERSION_1)
+ {
+ pTable->m_pfnCreateBrush = &QERApp_CreateBrush;
+ pTable->m_pfnCreateBrushHandle = &QERApp_CreateBrushHandle;
+ pTable->m_pfnDeleteBrushHandle = &QERApp_DeleteBrushHandle;
+ pTable->m_pfnCommitBrushHandle = &QERApp_CommitBrushHandleToMap;
+ pTable->m_pfnAddFace = &QERApp_AddFace;
+ pTable->m_pfnAddFaceData = &QERApp_AddFaceData;
+ pTable->m_pfnGetFaceData = &QERApp_GetFaceData;
+ pTable->m_pfnGetFaceCount = &QERApp_GetFaceCount;
+ pTable->m_pfnSetFaceData = &QERApp_SetFaceData;
+ pTable->m_pfnDeleteFace = &QERApp_DeleteFace;
+ pTable->m_pfnTextureBrush = &QERApp_TextureBrush;
+ pTable->m_pfnBuildBrush = &QERApp_BuildBrush; // PGM
+ pTable->m_pfnSelectBrush = &QERApp_SelectBrush; // PGM
+ pTable->m_pfnDeselectBrush = &QERApp_DeselectBrush; // PGM
+ pTable->m_pfnDeselectAllBrushes = &QERApp_DeselectAllBrushes; // PGM
+ pTable->m_pfnDeleteSelection = &QERApp_DeleteSelection;
+ pTable->m_pfnGetPoints = &QERApp_GetPoints;
+ pTable->m_pfnSysMsg = &QERApp_SysMsg;
+ pTable->m_pfnInfoMsg = &QERApp_InfoMsg;
+ pTable->m_pfnHideInfoMsg = &QERApp_HideInfoMsg;
+ pTable->m_pfnPositionView = &QERApp_PositionView; // PGM
+ pTable->m_pfnSelectedBrushCount = &QERApp_SelectedBrushCount;
+ pTable->m_pfnAllocateSelectedBrushHandles = &QERApp_AllocateSelectedBrushHandles;
+ pTable->m_pfnReleaseSelectedBrushHandles = &QERApp_ReleaseSelectedBrushHandles;
+ pTable->m_pfnGetSelectedBrushHandle = &QERApp_GetSelectedBrushHandle;
+ pTable->m_pfnActiveBrushCount = &QERApp_ActiveBrushCount;
+ pTable->m_pfnAllocateActiveBrushHandles = &QERApp_AllocateActiveBrushHandles;
+ pTable->m_pfnReleaseActiveBrushHandles = &QERApp_ReleaseActiveBrushHandles;
+ pTable->m_pfnGetActiveBrushHandle = &QERApp_GetActiveBrushHandle;
+ pTable->m_pfnTextureCount = &QERApp_TextureCount;
+ pTable->m_pfnGetTexture = &QERApp_GetTexture;
+ pTable->m_pfnGetCurrentTexture = &QERApp_GetCurrentTexture;
+ pTable->m_pfnSetCurrentTexture = &QERApp_SetCurrentTexture;
+ pTable->m_pfnGetEClassCount = &QERApp_GetEClassCount;
+ pTable->m_pfnGetEClass = &QERApp_GetEClass;
+ pTable->m_pfnResetPlugins = &QERApp_ResetPlugins;
+ }
+ // end of v1.00
+ if (pTable->m_fVersion >= 1.5f)
+ {
+ // v1.50 starts
+ pTable->m_pfnLoadTextureRGBA = &QERApp_LoadTextureRGBA;
+ // end of v1.50
+ }
+ if (pTable->m_fVersion >= 1.7f)
+ {
+ pTable->m_pfnGetEntityCount = &QERApp_GetEntityCount;
+ pTable->m_pfnGetEntityHandle = &QERApp_GetEntityHandle;
+ pTable->m_pfnGetEntityKeyValList = &QERApp_GetEntityKeyValList;
+ pTable->m_pfnAllocateEpair = &QERApp_AllocateEpair;
+ pTable->m_pfnSetEntityKeyValList = &QERApp_SetEntityKeyValList;
+ pTable->m_pfnAllocateEntityBrushHandles = &QERApp_AllocateEntityBrushHandles;
+ pTable->m_pfnReleaseEntityBrushHandles = &QERApp_ReleaseEntityBrushHandles;
+ pTable->m_pfnGetEntityBrushHandle = &QERApp_GetEntityBrushHandle;
+ pTable->m_pfnCreateEntityHandle = &QERApp_CreateEntityHandle;
+ pTable->m_pfnCommitBrushHandleToEntity = &QERApp_CommitBrushHandleToEntity;
+ pTable->m_pfnCommitEntityHandleToMap = &QERApp_CommitEntityHandleToMap;
+ pTable->m_pfnSetScreenUpdate = &QERApp_SetScreenUpdate;
+ pTable->m_pfnSysUpdateWindows = &Sys_UpdateWindows;
+ pTable->m_pfnBuildBrush2 = &QERApp_BuildBrush2;
+ pTable->m_pfnReadProjectKey = &QERApp_ReadProjectKey;
+ pTable->m_pfnScanFileForEClass = &QERApp_ScanFileForEClass;
+ pTable->m_pfnRequestInterface = &QERApp_RequestInterface;
+ pTable->m_pfnErrorMsg = &QERApp_ErrorMsg;
+ pTable->m_pfnLoadFile = &QERApp_LoadFile;
+ pTable->m_pfnExpandReletivePath = &QERApp_ExpandReletivePath;
+ pTable->m_pfnQE_ConvertDOSToUnixName = &QE_ConvertDOSToUnixName;
+ pTable->m_pfnHasShader = &QERApp_HasShader;
+ pTable->m_pfnTexture_LoadSkin = &Texture_LoadSkin;
+ pTable->m_pfnRadiantFree = &QERApp_RadiantFree;
+ pTable->m_pfnGetGamePath = &QERApp_GetGamePath;
+ pTable->m_pfnGetQERPath = &QERApp_GetQERPath;
+ // patches
+ pTable->m_pfnAllocateActivePatchHandles = &QERApp_AllocateActivePatchHandles;
+ pTable->m_pfnAllocateSelectedPatchHandles = &QERApp_AllocateSelectedPatchHandles;
+ pTable->m_pfnReleasePatchHandles = &QERApp_ReleasePatchHandles;
+ pTable->m_pfnGetPatchData = &QERApp_GetPatchData;
+ pTable->m_pfnDeletePatch = &QERApp_DeletePatch;
+ pTable->m_pfnCreatePatchHandle = &QERApp_CreatePatchHandle;
+ pTable->m_pfnCommitPatchHandleToMap = &QERApp_CommitPatchHandleToMap;
+ }
+ return true;
+ }
+ else
+ {
+ Sys_Printf("Unable to load %s because the function tables are not the same size\n", pPlug->getVersionStr());
+ }
+ return false;
+}
+
+CPlugIn * CPlugInManager::PluginForModule(HMODULE hPlug)
+{
+ int i;
+ for( i=0; i!=m_PlugIns.GetSize(); i++ )
+ {
+ if ( reinterpret_cast<CPlugIn *>(m_PlugIns[i])->GetDLLModule() == hPlug )
+ return reinterpret_cast<CPlugIn *>(m_PlugIns[i]);
+ }
+ return NULL;
+}
+
diff --git a/q3radiant/PlugInManager.h b/q3radiant/PlugInManager.h
new file mode 100755
index 0000000..1b77e94
--- /dev/null
+++ b/q3radiant/PlugInManager.h
@@ -0,0 +1,100 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PlugInManager.h: interface for the CPlugInManager class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PLUGINMANAGER_H__CFB18412_55FE_11D2_B082_00AA00A410FC__INCLUDED_)
+#define AFX_PLUGINMANAGER_H__CFB18412_55FE_11D2_B082_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#include "plugin.h"
+
+class CPlugInManager
+{
+private:
+ CObArray m_PlugIns;
+ CPtrArray m_BrushHandles;
+ CPtrArray m_SelectedBrushHandles;
+ CPtrArray m_ActiveBrushHandles;
+
+ CPlugIn *m_pTexturePlug;
+ CPlugIn *m_pSurfaceListPlug;
+
+ // v1.70
+ // brushes of the current entity ( see m_SelectedBrushHandles and m_ActiveBrushHandles )
+ CPtrArray m_EntityBrushHandles;
+ // allocated entities, not commited yet ( see m_BrushHandles )
+ CPtrArray m_EntityHandles;
+
+ // tells in which array to look when given a patch index
+ enum EPatchesMode { EActivePatches, ESelectedPatches, EAllocatedPatches } PatchesMode;
+ // patches handles (brush_t*)
+ CPtrArray m_PatchesHandles;
+ // plugin-allocated patches, not commited yet (patchMesh_t*)
+ CPtrArray m_PluginPatches;
+
+public:
+ CPlugIn * PluginForModule( HMODULE hPlug );
+ CPtrArray& GetActiveHandles() {return m_ActiveBrushHandles; };
+ CPtrArray& GetSelectedHandles() {return m_SelectedBrushHandles; };
+ CPtrArray& GetPluginPatches() {return m_PluginPatches; };
+ brush_t* FindBrushHandle(void *vp);
+ patchMesh_t* FindPatchHandle(int index);
+ int CreatePatchHandle();
+ int AllocateActivePatchHandles();
+ int AllocateSelectedPatchHandles();
+ void CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName);
+ void ReleasePatchesHandles() { m_PatchesHandles.RemoveAll(); m_PluginPatches.RemoveAll(); }
+ void AddFaceToBrushHandle(void *vp, vec3_t v1, vec3_t v2, vec3_t v3);
+ void CommitBrushHandleToMap(void *vp);
+ void DeleteBrushHandle(LPVOID vp);
+ LPVOID CreateBrushHandle();
+ void Dispatch(int n, const char *p);
+ void Cleanup();
+ void Init(const char* pPath);
+ CPlugInManager();
+ virtual ~CPlugInManager();
+
+ // the texture manager front ends the single load
+ // addins (texture, model, map formats.. etc.)
+ _QERTextureInfo* GetTextureInfo();
+ void LoadTexture(const char *pFilename);
+
+ LPVOID GetSurfaceFlags();
+
+ // v1.70
+ CPtrArray& GetEntityBrushHandles() {return m_EntityBrushHandles; };
+ CPtrArray& GetEntityHandles() {return m_EntityHandles; };
+ // the vpBrush needs to be in m_BrushHandles
+ void CommitBrushHandleToEntity( LPVOID vpBrush, LPVOID vpEntity );
+ // the vpEntity needs to be in m_EntityHandles
+ void CommitEntityHandleToMap( LPVOID vpEntity );
+
+protected:
+ int FillFuncTable(CPlugIn *pPlug); // PGM
+};
+
+#endif // !defined(AFX_PLUGINMANAGER_H__CFB18412_55FE_11D2_B082_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/PluginEntities.cpp b/q3radiant/PluginEntities.cpp
new file mode 100755
index 0000000..fb2d972
--- /dev/null
+++ b/q3radiant/PluginEntities.cpp
@@ -0,0 +1,101 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:17:34 $
+// $Log: PluginEntities.cpp,v $
+// Revision 1.1.1.4 2000/01/18 00:17:34 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:42 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:11 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:34 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:38 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:34 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:34 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:46 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.1 1999/11/03 20:38:01 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+//
+// DESCRIPTION:
+// implementation of IPluginEntities specific interface
+//
+
+#include "stdafx.h"
+#include "io.h"
+
+// is Eclass_InitForModelDirectory
+int WINAPI QERApp_EClassScanDir( char *path, HMODULE hPlug )
+{
+ struct _finddata_t fileinfo;
+ int handle;
+ char temp[ _MAX_PATH ];
+ char filebase[ _MAX_PATH ];
+ char filename[ _MAX_PATH ];
+ char *s;
+ eclass_t *e;
+ QE_ConvertDOSToUnixName( temp, path );
+ strcpy (filebase, path);
+ s = filebase + strlen(filebase)-1;
+ while (*s != '\\' && *s != '/' && s!=filebase)
+ s--;
+ *s = 0;
+ handle = _findfirst (path, &fileinfo);
+ if (handle != -1)
+ {
+ do
+ {
+ sprintf (filename, "%s\\%s", filebase, fileinfo.name);
+ Eclass_ScanFile (filename);
+
+ if (eclass_found)
+ {
+ e = eclass_e;
+ e->modelpath = strdup( fileinfo.name );
+ e->nShowFlags |= ECLASS_PLUGINENTITY;
+ e->hPlug = hPlug;
+ }
+ } while (_findnext( handle, &fileinfo ) != -1);
+
+ _findclose (handle);
+ }
+ return 0;
+}
diff --git a/q3radiant/PrefsDlg.cpp b/q3radiant/PrefsDlg.cpp
new file mode 100755
index 0000000..df67f1f
--- /dev/null
+++ b/q3radiant/PrefsDlg.cpp
@@ -0,0 +1,578 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// PrefsDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "PrefsDlg.h"
+#include "shlobj.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define PREF_SECTION "Prefs"
+#define INTERNAL_SECTION "Internals"
+#define MOUSE_KEY "MouseButtons"
+#define WINDOW_KEY "QE4StyleWindows"
+#define LAYOUT_KEY "WindowLayout"
+#define Q2_KEY "Quake2Dir"
+#define RUNQ2_KEY "RunQuake2Run"
+#define TLOCK_KEY "TextureLock"
+#define RLOCK_KEY "RotateLock"
+#define LOADLAST_KEY "LoadLast"
+#define LOADLASTMAP_KEY "LoadLastMap"
+#define LASTPROJ_KEY "LastProject"
+#define LASTMAP_KEY "LastMap"
+#define RUN_KEY "RunBefore"
+#define _3DFX_KEY "Use3Dfx"
+#define FACE_KEY "NewFaceGrab"
+#define BSP_KEY "InternalBSP"
+#define RCLICK_KEY "NewRightClick"
+#define VERTEX_KEY "NewVertex"
+#define AUTOSAVE_KEY "Autosave"
+#define AUTOSAVETIME_KEY "AutosaveMinutes"
+#define PAK_KEY "UsePAK"
+#define NEWAPPLY_KEY "ApplyDismissesSurface"
+#define HACK_KEY "Gatewayescapehack"
+#define TEXTURE_KEY "NewTextureWindowStuff"
+#define TINYBRUSH_KEY "CleanTinyBrushes"
+#define TINYSIZE_KEY "CleanTinyBrusheSize"
+#define SNAPSHOT_KEY "Snapshots"
+#define PAKFILE_KEY "PAKFile"
+#define STATUS_KEY "StatusPointSize"
+#define MOVESPEED_KEY "MoveSpeed"
+#define ANGLESPEED_KEY "AngleSpeed"
+#define SETGAME_KEY "UseSetGame"
+#define CAMXYUPDATE_KEY "CamXYUpdate"
+#define LIGHTDRAW_KEY "NewLightStyle"
+#define WHATGAME_KEY "WhichGame"
+#define CUBICCLIP_KEY "CubicClipping"
+#define CUBICSCALE_KEY "CubicScale"
+#define ALTEDGE_KEY "ALTEdgeDrag"
+#define TEXTUREBAR_KEY "UseTextureBar"
+#define FACECOLORS_KEY "FaceColors"
+#define QE4PAINT_KEY "QE4Paint"
+#define SNAPT_KEY "SnapT"
+#define XZVIS_KEY "XZVIS"
+#define YZVIS_KEY "YZVIS"
+#define ZVIS_KEY "ZVIS"
+#define SIZEPAINT_KEY "SizePainting"
+#define DLLENTITIES_KEY "DLLEntities"
+#define WIDETOOLBAR_KEY "WideToolBar"
+#define NOCLAMP_KEY "NoClamp"
+#define PREFAB_KEY "PrefabPath"
+#define USERINI_KEY "UserINIPath"
+#define ROTATION_KEY "Rotation"
+#define SGIOPENGL_KEY "SGIOpenGL"
+#define BUGGYICD_KEY "BuggyICD"
+#define HICOLOR_KEY "HiColorTextures"
+#define CHASEMOUSE_KEY "ChaseMouse"
+#define ENTITYSHOW_KEY "EntityShow"
+#define TEXTURESCALE_KEY "TextureScale"
+#define TEXTURESCROLLBAR_KEY "TextureScrollbar"
+#define DISPLAYLISTS_KEY "UseDisplayLists"
+#define NORMALIZECOLORS_KEY "NormalizeColors"
+#define SHADERS_KEY "UseShaders"
+#define SWITCHCLIP_KEY "SwitchClipKey"
+#define SELWHOLEENTS_KEY "SelectWholeEntitiesKey"
+#define TEXTURESUBSET_KEY "UseTextureSubsetLoading"
+#define TEXTUREQUALITY_KEY "TextureQuality"
+#define SHOWSHADERS_KEY "ShowShaders"
+#define SHADERTEST_KEY "ShaderTest"
+#define GLLIGHTING_KEY "UseGLLighting"
+#define LOADSHADERS_KEY "LoadShaders"
+#define NOSTIPPLE_KEY "NoStipple"
+#define UNDOLEVELS_KEY "UndoLevels"
+
+#define MOUSE_DEF 1
+#define WINDOW_DEF 0
+#define Q2_DEF "c:\\quake2\\quake2.exe"
+#define Q3_DEF "c:\\Program Files\\Quake III Arena\\quake3.exe"
+#define PAKFILE_DEF "c:\\quake2\\baseq2\\pak0.pak"
+#define RUNQ2_DEF 0
+#define TLOCK_DEF 1
+#define LOADLAST_DEF 1
+#define RUN_DEF 0
+
+/////////////////////////////////////////////////////////////////////////////
+// CPrefsDlg dialog
+
+
+CPrefsDlg::CPrefsDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CPrefsDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CPrefsDlg)
+ m_strQuake2 = _T("c:\\quake3\\");
+ m_nMouse = 1;
+ m_nView = 0;
+ m_bLoadLast = FALSE;
+ m_bFace = FALSE;
+ m_bInternalBSP = FALSE;
+ m_bRightClick = FALSE;
+ m_bRunQuake = FALSE;
+ m_bSetGame = FALSE;
+ m_bVertex = FALSE;
+ m_bAutoSave = TRUE;
+ m_bNewApplyHandling = FALSE;
+ m_strAutoSave = _T("5");
+ m_bPAK = FALSE;
+ m_bLoadLastMap = FALSE;
+ m_bTextureWindow = FALSE;
+ m_bSnapShots = FALSE;
+ m_fTinySize = 0.5;
+ m_bCleanTiny = FALSE;
+ m_strPAKFile = _T("c:\\quake2\\baseq2\\pak0.pak");
+ m_nStatusSize = 10;
+ m_bCamXYUpdate = FALSE;
+ m_bNewLightDraw = FALSE;
+ m_strPrefabPath = _T("");
+ m_nWhatGame = 0;
+ m_strWhatGame = _T("Quake3");
+ m_bALTEdge = FALSE;
+ m_bTextureBar = FALSE;
+ m_bFaceColors = FALSE;
+ m_bQE4Painting = TRUE;
+ m_bSnapTToGrid = FALSE;
+ m_bXZVis = FALSE;
+ m_bYZVis = FALSE;
+ m_bZVis = FALSE;
+ m_bSizePaint = FALSE;
+ m_bDLLEntities = FALSE;
+ m_bWideToolbar = TRUE;
+ m_bNoClamp = FALSE;
+ m_strUserPath = _T("");
+ m_nRotation = 0;
+ m_bSGIOpenGL = FALSE;
+ m_bBuggyICD = FALSE;
+ m_bHiColorTextures = TRUE;
+ m_bChaseMouse = FALSE;
+ m_bTextureScrollbar = TRUE;
+ m_bDisplayLists = TRUE;
+ m_bShowShaders = FALSE;
+ m_nShader = -1;
+ m_bNoStipple = FALSE;
+ //}}AFX_DATA_INIT
+ //LoadPrefs();
+ m_bSelectCurves = TRUE;
+ m_bSelectTerrain = TRUE;
+ m_nEntityShowState = 0;
+ m_nTextureScale = 2;
+ m_bSwitchClip = FALSE;
+ m_bSelectWholeEntities = TRUE;
+ m_nTextureQuality = 3;
+ m_bShowShaders = TRUE;
+ m_bGLLighting = FALSE;
+ m_nShader = 0;
+ m_nUndoLevels = 64;
+}
+
+
+
+
+void CPrefsDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CPrefsDlg)
+ DDX_Control(pDX, IDC_SPIN_UNDO, m_wndUndoSpin);
+ DDX_Control(pDX, IDC_SPIN_POINTSIZE, m_wndFontSpin);
+ DDX_Control(pDX, IDC_SLIDER_TEXTUREQUALITY, m_wndTexturequality);
+ DDX_Control(pDX, IDC_COMBO_WHATGAME, m_wndWhatGame);
+ DDX_Control(pDX, IDC_SLIDER_CAMSPEED, m_wndCamSpeed);
+ DDX_Control(pDX, IDC_SPIN_AUTOSAVE, m_wndSpin);
+ DDX_Text(pDX, IDC_EDIT_QUAKE2, m_strQuake2);
+ DDX_Radio(pDX, IDC_RADIO_MOUSE, m_nMouse);
+ DDX_Radio(pDX, IDC_RADIO_VIEWTYPE, m_nView);
+ DDX_Check(pDX, IDC_CHECK_LOADLAST, m_bLoadLast);
+ DDX_Check(pDX, IDC_CHECK_FACE, m_bFace);
+ DDX_Check(pDX, IDC_CHECK_INTERNALBSP, m_bInternalBSP);
+ DDX_Check(pDX, IDC_CHECK_RIGHTCLICK, m_bRightClick);
+ DDX_Check(pDX, IDC_CHECK_RUNQUAKE, m_bRunQuake);
+ DDX_Check(pDX, IDC_CHECK_SETGAME, m_bSetGame);
+ DDX_Check(pDX, IDC_CHECK_VERTEX, m_bVertex);
+ DDX_Check(pDX, IDC_CHECK_AUTOSAVE, m_bAutoSave);
+ DDX_Text(pDX, IDC_EDIT_AUTOSAVE, m_strAutoSave);
+ DDX_Check(pDX, IDC_CHECK_PAK, m_bPAK);
+ DDX_Check(pDX, IDC_CHECK_LOADLASTMAP, m_bLoadLastMap);
+ DDX_Check(pDX, IDC_CHECK_TEXTUREWINDOW, m_bTextureWindow);
+ DDX_Check(pDX, IDC_CHECK_SNAPSHOTS, m_bSnapShots);
+ DDX_Text(pDX, IDC_EDIT_PAKFILE, m_strPAKFile);
+ DDX_Text(pDX, IDC_EDIT_STATUSPOINTSIZE, m_nStatusSize);
+ DDV_MinMaxInt(pDX, m_nStatusSize, 2, 14);
+ DDX_Check(pDX, IDC_CHECK_CAMXYUPDATE, m_bCamXYUpdate);
+ DDX_Check(pDX, IDC_CHECK_LIGHTDRAW, m_bNewLightDraw);
+ DDX_Text(pDX, IDC_EDIT_PREFABPATH, m_strPrefabPath);
+ DDX_CBString(pDX, IDC_COMBO_WHATGAME, m_strWhatGame);
+ DDX_Check(pDX, IDC_CHECK_ALTDRAG, m_bALTEdge);
+ DDX_Check(pDX, IDC_CHECK_TEXTURETOOLBAR, m_bTextureBar);
+ DDX_Check(pDX, IDC_CHECK_FACECOLOR, m_bFaceColors);
+ DDX_Check(pDX, IDC_CHECK_QE4PAINTING, m_bQE4Painting);
+ DDX_Check(pDX, IDC_CHECK_SNAPT, m_bSnapTToGrid);
+ DDX_Check(pDX, IDC_CHECK_SIZEPAINT, m_bSizePaint);
+ DDX_Check(pDX, IDC_CHECK_DLLENTITIES, m_bDLLEntities);
+ DDX_Check(pDX, IDC_CHECK_WIDETOOLBAR, m_bWideToolbar);
+ DDX_Check(pDX, IDC_CHECK_NOCLAMP, m_bNoClamp);
+ DDX_Text(pDX, IDC_EDIT_USERPATH, m_strUserPath);
+ DDX_Text(pDX, IDC_EDIT_ROTATION, m_nRotation);
+ DDX_Check(pDX, IDC_CHECK_SGIOPENGL, m_bSGIOpenGL);
+ DDX_Check(pDX, IDC_CHECK_BUGGYICD, m_bBuggyICD);
+ DDX_Check(pDX, IDC_CHECK_HICOLOR, m_bHiColorTextures);
+ DDX_Check(pDX, IDC_CHECK_MOUSECHASE, m_bChaseMouse);
+ DDX_Check(pDX, IDC_CHECK_TEXTURESCROLLBAR, m_bTextureScrollbar);
+ DDX_Check(pDX, IDC_CHECK_DISPLAYLISTS, m_bDisplayLists);
+ DDX_CBIndex(pDX, IDC_COMBO_SHADERS, m_nShader);
+ DDX_Check(pDX, IDC_CHECK_NOSTIPPLE, m_bNoStipple);
+ DDX_Text(pDX, IDC_EDIT_UNDOLEVELS, m_nUndoLevels);
+ DDV_MinMaxInt(pDX, m_nUndoLevels, 1, 64);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CPrefsDlg, CDialog)
+ //{{AFX_MSG_MAP(CPrefsDlg)
+ ON_BN_CLICKED(IDC_BTN_BROWSE, OnBtnBrowse)
+ ON_BN_CLICKED(IDC_BTN_BROWSEPAK, OnBtnBrowsepak)
+ ON_BN_CLICKED(IDC_BTN_BROWSEPREFAB, OnBtnBrowseprefab)
+ ON_BN_CLICKED(IDC_BTN_BROWSEUSERINI, OnBtnBrowseuserini)
+ ON_CBN_SELCHANGE(IDC_COMBO_WHATGAME, OnSelchangeComboWhatgame)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CPrefsDlg message handlers
+
+void CPrefsDlg::OnBtnBrowse()
+{
+ UpdateData(TRUE);
+ CFileDialog dlg(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Executables (*.exe)|*.exe||", this);
+ if (dlg.DoModal() == IDOK)
+ {
+ m_strQuake2 = dlg.GetPathName();
+ UpdateData(FALSE);
+ }
+}
+
+BOOL CPrefsDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ m_wndSpin.SetRange(1,60);
+ m_wndCamSpeed.SetRange(10, 800);
+ m_wndCamSpeed.SetPos(m_nMoveSpeed);
+
+ this->m_wndTexturequality.SetRange(0, 3);
+ this->m_wndTexturequality.SetPos(m_nTextureQuality);
+
+ m_wndFontSpin.SetRange(4,24);
+ m_wndUndoSpin.SetRange(1,64);
+
+ m_wndWhatGame.AddString("Quake2");
+ m_wndWhatGame.AddString("Quake3");
+
+ GetDlgItem(IDC_CHECK_HICOLOR)->EnableWindow(TRUE);
+ GetDlgItem(IDC_CHECK_NOCLAMP)->EnableWindow(TRUE);
+
+ //GetDlgItem(IDC_CHECK_NOCLAMP)->EnableWindow(FALSE);
+
+ m_wndWhatGame.SelectString(-1,m_strWhatGame);
+ if (strstr(m_strWhatGame, "Quake3") != NULL)
+ {
+ GetDlgItem(IDC_EDIT_PAKFILE)->EnableWindow(FALSE);
+ GetDlgItem(IDC_BTN_BROWSEPAK)->EnableWindow(FALSE);
+ GetDlgItem(IDC_CHECK_INTERNALBSP)->EnableWindow(FALSE);
+ }
+ else
+ {
+ GetDlgItem(IDC_EDIT_PAKFILE)->EnableWindow(TRUE);
+ GetDlgItem(IDC_BTN_BROWSEPAK)->EnableWindow(TRUE);
+ GetDlgItem(IDC_CHECK_INTERNALBSP)->EnableWindow(TRUE);
+ }
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CPrefsDlg::OnOK()
+{
+ m_nMoveSpeed = m_wndCamSpeed.GetPos();
+ m_nAngleSpeed = (float)m_nMoveSpeed * 0.50;
+ this->m_nTextureQuality = m_wndTexturequality.GetPos();
+ SavePrefs();
+
+ if (g_pParentWnd)
+ g_pParentWnd->SetGridStatus();
+ Sys_UpdateWindows(W_ALL);
+ Undo_SetMaxSize(m_nUndoLevels);
+ CDialog::OnOK();
+}
+
+void CPrefsDlg::LoadPrefs()
+{
+ CString strBuff;
+ CString strPrefab = g_strAppPath;
+ AddSlash(strPrefab);
+ strPrefab += "Prefabs\\";
+
+ m_nMouse = AfxGetApp()->GetProfileInt(PREF_SECTION, MOUSE_KEY, MOUSE_DEF);
+ if (m_nMouse == 0)
+ m_nMouseButtons = 2;
+ else
+ m_nMouseButtons = 3;
+
+ m_nView = AfxGetApp()->GetProfileInt(PREF_SECTION, WINDOW_KEY, WINDOW_DEF);
+ m_strQuake2 = AfxGetApp()->GetProfileString(PREF_SECTION, Q2_KEY, Q2_DEF);
+ m_bRunQuake = AfxGetApp()->GetProfileInt(PREF_SECTION, RUNQ2_KEY, RUNQ2_DEF);
+ m_bTextureLock = AfxGetApp()->GetProfileInt(PREF_SECTION, TLOCK_KEY, TLOCK_DEF);
+ m_bRotateLock = AfxGetApp()->GetProfileInt(PREF_SECTION, RLOCK_KEY, TLOCK_DEF);
+ m_strLastProject = AfxGetApp()->GetProfileString(PREF_SECTION, LASTPROJ_KEY, "");
+ m_strLastMap = AfxGetApp()->GetProfileString(PREF_SECTION, LASTMAP_KEY, "");
+ m_bLoadLast = AfxGetApp()->GetProfileInt(PREF_SECTION, LOADLAST_KEY, LOADLAST_DEF);
+ m_bRunBefore = AfxGetApp()->GetProfileInt(INTERNAL_SECTION, RUN_KEY, RUN_DEF);
+ //m_b3Dfx = AfxGetApp()->GetProfileInt(PREF_SECTION, _3DFX_KEY, 0);
+ m_bFace = AfxGetApp()->GetProfileInt(PREF_SECTION, FACE_KEY, 1);
+ m_bInternalBSP = AfxGetApp()->GetProfileInt(PREF_SECTION, BSP_KEY, 0);
+ m_bRightClick = AfxGetApp()->GetProfileInt(PREF_SECTION, RCLICK_KEY, 1);
+ m_bVertex = AfxGetApp()->GetProfileInt(PREF_SECTION, VERTEX_KEY, 1);
+ m_bAutoSave = AfxGetApp()->GetProfileInt(PREF_SECTION, AUTOSAVE_KEY, 1);
+ m_bPAK = AfxGetApp()->GetProfileInt(PREF_SECTION, PAK_KEY, 1);
+ m_bNewApplyHandling = AfxGetApp()->GetProfileInt(PREF_SECTION, NEWAPPLY_KEY, 0);
+ m_bLoadLastMap = AfxGetApp()->GetProfileInt(PREF_SECTION, LOADLASTMAP_KEY, 0);
+ m_bGatewayHack = AfxGetApp()->GetProfileInt(PREF_SECTION, HACK_KEY, 0);
+ m_bTextureWindow = AfxGetApp()->GetProfileInt(PREF_SECTION, TEXTURE_KEY, 0);
+ m_bCleanTiny = AfxGetApp()->GetProfileInt(PREF_SECTION, TINYBRUSH_KEY, 0);
+ strBuff = AfxGetApp()->GetProfileString(PREF_SECTION, TINYSIZE_KEY, "0.5");
+ m_fTinySize = atof(strBuff);
+ m_nAutoSave = AfxGetApp()->GetProfileInt(PREF_SECTION, AUTOSAVETIME_KEY, 5);
+ m_strAutoSave.Format("%i", m_nAutoSave);
+ m_bSnapShots = AfxGetApp()->GetProfileInt(PREF_SECTION, SNAPSHOT_KEY, 0);
+ m_strPAKFile = AfxGetApp()->GetProfileString(PREF_SECTION, PAKFILE_KEY, PAKFILE_DEF);
+ m_nStatusSize = AfxGetApp()->GetProfileInt(PREF_SECTION, STATUS_KEY, 10);
+ m_nMoveSpeed = AfxGetApp()->GetProfileInt(PREF_SECTION, MOVESPEED_KEY, 400);
+ m_nAngleSpeed = AfxGetApp()->GetProfileInt(PREF_SECTION, ANGLESPEED_KEY, 300);
+ m_bSetGame = AfxGetApp()->GetProfileInt(PREF_SECTION, SETGAME_KEY, 0);
+ m_bCamXYUpdate = AfxGetApp()->GetProfileInt(PREF_SECTION, CAMXYUPDATE_KEY, 1);
+ m_bNewLightDraw = AfxGetApp()->GetProfileInt(PREF_SECTION, LIGHTDRAW_KEY, 1);
+ m_bCubicClipping = AfxGetApp()->GetProfileInt(PREF_SECTION, CUBICCLIP_KEY, 1);
+ m_nCubicScale = AfxGetApp()->GetProfileInt(PREF_SECTION, CUBICSCALE_KEY, 13);
+ m_bALTEdge = AfxGetApp()->GetProfileInt(PREF_SECTION, ALTEDGE_KEY, 0);
+ m_bTextureBar = AfxGetApp()->GetProfileInt(PREF_SECTION, TEXTUREBAR_KEY, 0);
+ m_strWhatGame = AfxGetApp()->GetProfileString(PREF_SECTION, WHATGAME_KEY, "Quake3");
+ m_bFaceColors = AfxGetApp()->GetProfileInt(PREF_SECTION, FACECOLORS_KEY, 0);
+ m_bQE4Painting = AfxGetApp()->GetProfileInt(PREF_SECTION, QE4PAINT_KEY, 1);
+ m_bSnapTToGrid = AfxGetApp()->GetProfileInt(PREF_SECTION, SNAPT_KEY, 0);
+ m_bXZVis = AfxGetApp()->GetProfileInt(PREF_SECTION, XZVIS_KEY, 0);
+ m_bYZVis = AfxGetApp()->GetProfileInt(PREF_SECTION, YZVIS_KEY, 0);
+ m_bZVis = AfxGetApp()->GetProfileInt(PREF_SECTION, ZVIS_KEY, 1);
+ m_bSizePaint = AfxGetApp()->GetProfileInt(PREF_SECTION, SIZEPAINT_KEY, 0);
+ m_bDLLEntities = AfxGetApp()->GetProfileInt(PREF_SECTION, DLLENTITIES_KEY, 0);
+ m_bWideToolbar = AfxGetApp()->GetProfileInt(PREF_SECTION, WIDETOOLBAR_KEY, 1);
+ m_bNoClamp = AfxGetApp()->GetProfileInt(PREF_SECTION, NOCLAMP_KEY, 0);
+ m_strPrefabPath = AfxGetApp()->GetProfileString(PREF_SECTION, PREFAB_KEY, strPrefab);
+ m_strUserPath = AfxGetApp()->GetProfileString(PREF_SECTION, USERINI_KEY, "");
+ m_nRotation = AfxGetApp()->GetProfileInt(PREF_SECTION, ROTATION_KEY, 45);
+ m_bSGIOpenGL = AfxGetApp()->GetProfileInt(PREF_SECTION, SGIOPENGL_KEY, 0);
+ m_bBuggyICD = AfxGetApp()->GetProfileInt(PREF_SECTION, BUGGYICD_KEY, 0);
+ m_bHiColorTextures = AfxGetApp()->GetProfileInt(PREF_SECTION, HICOLOR_KEY, 1);
+ m_bChaseMouse = AfxGetApp()->GetProfileInt(PREF_SECTION, CHASEMOUSE_KEY, 1);
+ m_nEntityShowState = AfxGetApp()->GetProfileInt(PREF_SECTION, ENTITYSHOW_KEY, 0);
+ m_nTextureScale = AfxGetApp()->GetProfileInt(PREF_SECTION, TEXTURESCALE_KEY, 50);
+ m_bTextureScrollbar = AfxGetApp()->GetProfileInt(PREF_SECTION, TEXTURESCROLLBAR_KEY, TRUE);
+ m_bDisplayLists = AfxGetApp()->GetProfileInt(PREF_SECTION, DISPLAYLISTS_KEY, TRUE);
+ m_bSwitchClip = AfxGetApp()->GetProfileInt(PREF_SECTION, SWITCHCLIP_KEY, TRUE);
+ m_bSelectWholeEntities = AfxGetApp()->GetProfileInt(PREF_SECTION, SELWHOLEENTS_KEY, TRUE);
+ m_nTextureQuality = AfxGetApp()->GetProfileInt(PREF_SECTION, TEXTUREQUALITY_KEY, 6);
+ m_bShowShaders = AfxGetApp()->GetProfileInt(PREF_SECTION, SHOWSHADERS_KEY, TRUE);
+ m_bGLLighting = AfxGetApp()->GetProfileInt(PREF_SECTION, GLLIGHTING_KEY, FALSE);
+ m_nShader = AfxGetApp()->GetProfileInt(PREF_SECTION, LOADSHADERS_KEY, 0);
+ m_bNoStipple = AfxGetApp()->GetProfileInt(PREF_SECTION, NOSTIPPLE_KEY, 0);
+ m_nUndoLevels = AfxGetApp()->GetProfileInt(PREF_SECTION, UNDOLEVELS_KEY, 0);
+
+ if (m_bRunBefore == FALSE)
+ {
+ SetGamePrefs();
+ }
+}
+
+
+void CPrefsDlg::SavePrefs()
+{
+ if (GetSafeHwnd())
+ UpdateData(TRUE);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, MOUSE_KEY, m_nMouse);
+ if (m_nMouse == 0)
+ m_nMouseButtons = 2;
+ else
+ m_nMouseButtons = 3;
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, WINDOW_KEY, m_nView);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, Q2_KEY, m_strQuake2);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, RUNQ2_KEY, m_bRunQuake);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, TLOCK_KEY, m_bTextureLock);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, RLOCK_KEY, m_bRotateLock);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, LOADLAST_KEY, m_bLoadLast);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, LASTPROJ_KEY, m_strLastProject);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, LASTMAP_KEY, m_strLastMap);
+ AfxGetApp()->WriteProfileInt(INTERNAL_SECTION, RUN_KEY, m_bRunBefore);
+ //AfxGetApp()->WriteProfileInt(PREF_SECTION, _3DFX_KEY, m_b3Dfx);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, FACE_KEY, m_bFace);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, BSP_KEY, m_bInternalBSP);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, RCLICK_KEY, m_bRightClick);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, VERTEX_KEY, m_bVertex);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, AUTOSAVE_KEY, m_bAutoSave);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, PAK_KEY, m_bPAK);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, LOADLASTMAP_KEY, m_bLoadLastMap);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, TEXTURE_KEY, m_bTextureWindow);
+ m_nAutoSave = atoi(m_strAutoSave);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, AUTOSAVETIME_KEY, m_nAutoSave);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SNAPSHOT_KEY, m_bSnapShots);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, PAKFILE_KEY, m_strPAKFile);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, STATUS_KEY, m_nStatusSize);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SETGAME_KEY, m_bSetGame);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, CAMXYUPDATE_KEY, m_bCamXYUpdate);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, LIGHTDRAW_KEY, m_bNewLightDraw);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, MOVESPEED_KEY, m_nMoveSpeed);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, ANGLESPEED_KEY, m_nAngleSpeed);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, CUBICCLIP_KEY, m_bCubicClipping);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, CUBICSCALE_KEY, m_nCubicScale);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, ALTEDGE_KEY, m_bALTEdge);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, TEXTUREBAR_KEY, m_bTextureBar);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, FACECOLORS_KEY, m_bFaceColors);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, WHATGAME_KEY, m_strWhatGame);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, QE4PAINT_KEY, m_bQE4Painting);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SNAPT_KEY, m_bSnapTToGrid);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, XZVIS_KEY, m_bXZVis);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, YZVIS_KEY, m_bYZVis);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, ZVIS_KEY, m_bZVis);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SIZEPAINT_KEY, m_bSizePaint);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, DLLENTITIES_KEY, m_bDLLEntities);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, WIDETOOLBAR_KEY, m_bWideToolbar);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, NOCLAMP_KEY, m_bNoClamp);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, PREFAB_KEY, m_strPrefabPath);
+ AfxGetApp()->WriteProfileString(PREF_SECTION, USERINI_KEY, m_strUserPath);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, ROTATION_KEY, m_nRotation);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SGIOPENGL_KEY, m_bSGIOpenGL);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, BUGGYICD_KEY, m_bBuggyICD);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, HICOLOR_KEY, m_bHiColorTextures);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, CHASEMOUSE_KEY, m_bChaseMouse);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, ENTITYSHOW_KEY, m_nEntityShowState);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, TEXTURESCALE_KEY, m_nTextureScale);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, TEXTURESCROLLBAR_KEY, m_bTextureScrollbar);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, DISPLAYLISTS_KEY, m_bDisplayLists);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SWITCHCLIP_KEY, m_bSwitchClip);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SELWHOLEENTS_KEY, m_bSelectWholeEntities);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, TEXTUREQUALITY_KEY, m_nTextureQuality);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, SHOWSHADERS_KEY, m_bShowShaders);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, GLLIGHTING_KEY, m_bGLLighting);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, LOADSHADERS_KEY, m_nShader);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, NOSTIPPLE_KEY, m_bNoStipple);
+ AfxGetApp()->WriteProfileInt(PREF_SECTION, UNDOLEVELS_KEY, m_nUndoLevels);
+}
+
+
+
+void CPrefsDlg::OnBtnBrowsepak()
+{
+ UpdateData(TRUE);
+ CFileDialog dlg(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "PAK files (*.pak)|*.pak||", this);
+ if (dlg.DoModal() == IDOK)
+ {
+ m_strPAKFile = dlg.GetPathName();
+ UpdateData(FALSE);
+ }
+}
+
+void CPrefsDlg::OnBtnBrowseprefab()
+{
+ UpdateData(TRUE);
+ BROWSEINFO bi;
+ CString strPath;
+ char* p = strPath.GetBuffer(MAX_PATH+1);
+ bi.hwndOwner = GetSafeHwnd();
+ bi.pidlRoot = NULL;
+ bi.pszDisplayName = p;
+ bi.lpszTitle = "Load textures from path";
+ bi.ulFlags = 0;
+ bi.lpfn = NULL;
+ bi.lParam = NULL;
+ bi.iImage = 0;
+ LPITEMIDLIST pidlBrowse;
+ pidlBrowse = SHBrowseForFolder(&bi);
+ if (pidlBrowse)
+ {
+ SHGetPathFromIDList(pidlBrowse, p);
+ strPath.ReleaseBuffer();
+ AddSlash(strPath);
+ m_strPrefabPath = strPath;
+ UpdateData(FALSE);
+ }
+}
+
+void CPrefsDlg::OnBtnBrowseuserini()
+{
+ UpdateData(TRUE);
+ CFileDialog dlg(true, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "INI files (*.ini)|*.ini||", this);
+ if (dlg.DoModal() == IDOK)
+ {
+ m_strUserPath = dlg.GetPathName();
+ UpdateData(FALSE);
+ }
+}
+
+void CPrefsDlg::OnSelchangeComboWhatgame()
+{
+ int n = m_wndWhatGame.GetCurSel();
+ if (n >= 0)
+ {
+ m_wndWhatGame.GetLBText(n, m_strWhatGame);
+ }
+ SetGamePrefs();
+}
+
+void CPrefsDlg::SetGamePrefs()
+{
+ if (strstr(m_strWhatGame, "Quake3") != NULL)
+ {
+ m_bHiColorTextures = TRUE;
+ m_bWideToolbar = TRUE;
+ m_strPAKFile = "PK3 files are loaded from the baseq3 path";
+ m_bInternalBSP = FALSE;
+ if (GetSafeHwnd())
+ {
+ GetDlgItem(IDC_EDIT_PAKFILE)->EnableWindow(FALSE);
+ GetDlgItem(IDC_BTN_BROWSEPAK)->EnableWindow(FALSE);
+ GetDlgItem(IDC_CHECK_INTERNALBSP)->EnableWindow(FALSE);
+ }
+ }
+ else
+ {
+ m_bHiColorTextures = FALSE;
+ m_bWideToolbar = FALSE;
+ m_strPAKFile = PAKFILE_DEF;
+ if (GetSafeHwnd())
+ {
+ GetDlgItem(IDC_EDIT_PAKFILE)->EnableWindow(TRUE);
+ GetDlgItem(IDC_BTN_BROWSEPAK)->EnableWindow(TRUE);
+ GetDlgItem(IDC_CHECK_INTERNALBSP)->EnableWindow(TRUE);
+ }
+ }
+ SavePrefs();
+}
diff --git a/q3radiant/PrefsDlg.h b/q3radiant/PrefsDlg.h
new file mode 100755
index 0000000..892fab9
--- /dev/null
+++ b/q3radiant/PrefsDlg.h
@@ -0,0 +1,161 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_PREFSDLG_H__DC829122_812D_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_PREFSDLG_H__DC829122_812D_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// PrefsDlg.h : header file
+//
+
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CPrefsDlg dialog
+
+#define MAX_TEXTURE_QUALITY 3
+
+class CPrefsDlg : public CDialog
+{
+// Construction
+public:
+ // these mirror what goes in the combo box
+ enum {SHADER_NONE = 0, SHADER_COMMON, SHADER_ALL};
+ void LoadPrefs();
+ void SavePrefs();
+ void SetGamePrefs();
+ CPrefsDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CPrefsDlg)
+ enum { IDD = IDD_DLG_PREFS };
+ CSpinButtonCtrl m_wndUndoSpin;
+ CSpinButtonCtrl m_wndFontSpin;
+ CSliderCtrl m_wndTexturequality;
+ CComboBox m_wndWhatGame;
+ CSliderCtrl m_wndCamSpeed;
+ CSpinButtonCtrl m_wndSpin;
+ CString m_strQuake2;
+ int m_nMouse;
+ int m_nView;
+ BOOL m_bTextureLock;
+ BOOL m_bLoadLast;
+ BOOL m_bRunBefore;
+ CString m_strLastProject;
+ CString m_strLastMap;
+ BOOL m_bFace;
+ BOOL m_bInternalBSP;
+ BOOL m_bRightClick;
+ BOOL m_bRunQuake;
+ BOOL m_bSetGame;
+ BOOL m_bVertex;
+ BOOL m_bAutoSave;
+ BOOL m_bNewApplyHandling;
+ CString m_strAutoSave;
+ BOOL m_bPAK;
+ BOOL m_bLoadLastMap;
+ BOOL m_bGatewayHack;
+ BOOL m_bTextureWindow;
+ BOOL m_bSnapShots;
+ float m_fTinySize;
+ BOOL m_bCleanTiny;
+ CString m_strPAKFile;
+ int m_nStatusSize;
+ BOOL m_bCamXYUpdate;
+ BOOL m_bNewLightDraw;
+ CString m_strPrefabPath;
+ int m_nWhatGame;
+ CString m_strWhatGame;
+ BOOL m_bALTEdge;
+ BOOL m_bTextureBar;
+ BOOL m_bFaceColors;
+ BOOL m_bQE4Painting;
+ BOOL m_bSnapTToGrid;
+ BOOL m_bXZVis;
+ BOOL m_bYZVis;
+ BOOL m_bZVis;
+ BOOL m_bSizePaint;
+ BOOL m_bDLLEntities;
+ BOOL m_bRotateLock;
+ BOOL m_bWideToolbar;
+ BOOL m_bNoClamp;
+ CString m_strUserPath;
+ int m_nRotation;
+ BOOL m_bSGIOpenGL;
+ BOOL m_bBuggyICD;
+ BOOL m_bHiColorTextures;
+ BOOL m_bChaseMouse;
+ BOOL m_bTextureScrollbar;
+ BOOL m_bDisplayLists;
+ BOOL m_bShowShaders;
+ int m_nShader;
+ BOOL m_bNoStipple;
+ int m_nUndoLevels;
+ //}}AFX_DATA
+ int m_nMouseButtons;
+ int m_nAngleSpeed;
+ int m_nMoveSpeed;
+ int m_nAutoSave;
+ bool m_bCubicClipping;
+ int m_nCubicScale;
+ BOOL m_bSelectCurves;
+ BOOL m_bSelectTerrain;
+ int m_nEntityShowState;
+ int m_nTextureScale;
+ BOOL m_bNormalizeColors;
+ BOOL m_bSwitchClip;
+ BOOL m_bSelectWholeEntities;
+ int m_nTextureQuality;
+ BOOL m_bGLLighting;
+
+ // brush primitive mode
+ //++timo moved into g_qeglobals
+// BOOL m_bBrushPrimitMode;
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CPrefsDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CPrefsDlg)
+ afx_msg void OnBtnBrowse();
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ afx_msg void OnBtnBrowsepak();
+ afx_msg void OnBtnBrowseprefab();
+ afx_msg void OnBtnBrowseuserini();
+ afx_msg void OnSelchangeComboWhatgame();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PREFSDLG_H__DC829122_812D_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/QE3.CPP b/q3radiant/QE3.CPP
new file mode 100755
index 0000000..691977d
--- /dev/null
+++ b/q3radiant/QE3.CPP
@@ -0,0 +1,751 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+#include "PrefsDlg.h"
+#include <direct.h>
+#include <sys\stat.h>
+
+QEGlobals_t g_qeglobals;
+
+void WINAPI QE_CheckOpenGLForErrors(void)
+{
+ CString strMsg;
+ int i = qglGetError();
+ if (i != GL_NO_ERROR)
+ {
+ if (i == GL_OUT_OF_MEMORY)
+ {
+ //strMsg.Format("OpenGL out of memory error %s\nDo you wish to save before exiting?", qgluErrorString((GLenum)i));
+ if (MessageBox(g_qeglobals.d_hwndMain, strMsg, "Q3Radiant Error", MB_YESNO) == IDYES)
+ {
+ Map_SaveFile(NULL, false);
+ }
+ exit(1);
+ }
+ else
+ {
+ //strMsg.Format("Warning: OpenGL Error %s\n ", qgluErrorString((GLenum)i));
+ Sys_Printf (strMsg.GetBuffer(0));
+ }
+ }
+}
+
+
+char *ExpandReletivePath (char *p)
+{
+ static char temp[1024];
+ char *base;
+
+ if (!p || !p[0])
+ return NULL;
+ if (p[0] == '/' || p[0] == '\\')
+ return p;
+
+ base = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ sprintf (temp, "%s/%s", base, p);
+ return temp;
+}
+
+char *copystring (char *s)
+{
+ char *b;
+ b = (char*)malloc(strlen(s)+1);
+ strcpy (b,s);
+ return b;
+}
+
+
+bool DoesFileExist(const char* pBuff, long& lSize)
+{
+ CFile file;
+ if (file.Open(pBuff, CFile::modeRead | CFile::shareDenyNone))
+ {
+ lSize += file.GetLength();
+ file.Close();
+ return true;
+ }
+ return false;
+}
+
+
+void Map_Snapshot()
+{
+ CString strMsg;
+ // we need to do the following
+ // 1. make sure the snapshot directory exists (create it if it doesn't)
+ // 2. find out what the lastest save is based on number
+ // 3. inc that and save the map
+ CString strOrgPath, strOrgFile;
+ ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
+ AddSlash(strOrgPath);
+ strOrgPath += "snapshots";
+ bool bGo = true;
+ struct _stat Stat;
+ if (_stat(strOrgPath, &Stat) == -1)
+ {
+ bGo = (_mkdir(strOrgPath) != -1);
+ }
+ AddSlash(strOrgPath);
+ if (bGo)
+ {
+ int nCount = 0;
+ long lSize = 0;
+ CString strNewPath = strOrgPath;
+ strNewPath += strOrgFile;
+ CString strFile;
+ while (bGo)
+ {
+ strFile.Format("%s.%i", strNewPath, nCount);
+ bGo = DoesFileExist(strFile, lSize);
+ nCount++;
+ }
+ // strFile has the next available slot
+ Map_SaveFile(strFile.GetBuffer(0), false);
+ Sys_SetTitle (currentmap);
+ if (lSize > 12 * 1024 * 1024) // total size of saves > 4 mb
+ {
+ Sys_Printf("The snapshot files in the [%s] directory total more than 4 megabytes. You might consider cleaning the directory up.", strOrgPath);
+ }
+ }
+ else
+ {
+ strMsg.Format("Snapshot save failed.. unabled to create directory\n%s", strOrgPath);
+ g_pParentWnd->MessageBox(strMsg);
+ }
+}
+/*
+===============
+QE_CheckAutoSave
+
+If five minutes have passed since making a change
+and the map hasn't been saved, save it out.
+===============
+*/
+
+
+void QE_CheckAutoSave( void )
+{
+ static clock_t s_start;
+ clock_t now;
+
+ now = clock();
+
+ if ( modified != 1 || !s_start)
+ {
+ s_start = now;
+ return;
+ }
+
+ if ( now - s_start > ( CLOCKS_PER_SEC * 60 * g_PrefsDlg.m_nAutoSave))
+ {
+
+ if (g_PrefsDlg.m_bAutoSave)
+ {
+ CString strMsg = g_PrefsDlg.m_bSnapShots ? "Autosaving snapshot..." : "Autosaving...";
+ Sys_Printf(strMsg.GetBuffer(0));
+ Sys_Printf("\n");
+ Sys_Status (strMsg.GetBuffer(0),0);
+
+ // only snapshot if not working on a default map
+ if (g_PrefsDlg.m_bSnapShots && stricmp(currentmap, "unnamed.map") != 0)
+ {
+ Map_Snapshot();
+ }
+ else
+ {
+ Map_SaveFile (ValueForKey(g_qeglobals.d_project_entity, "autosave"), false);
+ }
+
+ Sys_Status ("Autosaving...Saved.", 0 );
+ modified = 2;
+ }
+ else
+ {
+ Sys_Printf ("Autosave skipped...\n");
+ Sys_Status ("Autosave skipped...", 0 );
+ }
+ s_start = now;
+ }
+}
+
+
+int BuildShortPathName(const char* pPath, char* pBuffer, int nBufferLen)
+{
+ char *pFile = NULL;
+ int nResult = GetFullPathName(pPath, nBufferLen, pBuffer, &pFile);
+ nResult = GetShortPathName(pPath, pBuffer, nBufferLen);
+ if (nResult == 0)
+ strcpy(pBuffer, pPath); // Use long filename
+ return nResult;
+}
+
+
+
+const char *g_pPathFixups[]=
+{
+ "basepath",
+ "remotebasepath",
+ "entitypath",
+ "texturepath",
+ "autosave",
+ "mapspath"
+};
+
+const int g_nPathFixupCount = sizeof(g_pPathFixups) / sizeof(const char*);
+
+/*
+===========
+QE_LoadProject
+===========
+*/
+qboolean QE_LoadProject (char *projectfile)
+{
+ char *data;
+
+ Sys_Printf ("QE_LoadProject (%s)\n", projectfile);
+
+ if ( LoadFileNoCrash (projectfile, (void **)&data) == -1)
+ return false;
+
+ g_strProject = projectfile;
+
+ CString strData = data;
+ free(data);
+
+ CString strQ2Path = g_PrefsDlg.m_strQuake2;
+ CString strQ2File;
+ ExtractPath_and_Filename(g_PrefsDlg.m_strQuake2, strQ2Path, strQ2File);
+ AddSlash(strQ2Path);
+
+
+ char* pBuff = new char[1024];
+
+ BuildShortPathName(strQ2Path, pBuff, 1024);
+ FindReplace(strData, "__Q2PATH", pBuff);
+ BuildShortPathName(g_strAppPath, pBuff, 1024);
+ FindReplace(strData, "__QERPATH", pBuff);
+
+ char* pFile;
+ if (GetFullPathName(projectfile, 1024, pBuff, &pFile))
+ {
+ g_PrefsDlg.m_strLastProject = pBuff;
+ BuildShortPathName(g_PrefsDlg.m_strLastProject, pBuff, 1024);
+ g_PrefsDlg.m_strLastProject = pBuff;
+ g_PrefsDlg.SavePrefs();
+
+ ExtractPath_and_Filename(pBuff, strQ2Path, strQ2File);
+ int nLen = strQ2Path.GetLength();
+ if (nLen > 0)
+ {
+ if (strQ2Path[nLen - 1] == '\\')
+ strQ2Path.SetAt(nLen-1,'\0');
+ char* pBuffer = strQ2Path.GetBufferSetLength(_MAX_PATH + 1);
+ int n = strQ2Path.ReverseFind('\\');
+ if (n >=0 )
+ pBuffer[n + 1] = '\0';
+ strQ2Path.ReleaseBuffer();
+ FindReplace(strData, "__QEPROJPATH", strQ2Path);
+ }
+ }
+
+
+ StartTokenParsing (strData.GetBuffer(0));
+ g_qeglobals.d_project_entity = Entity_Parse (true);
+ if (!g_qeglobals.d_project_entity)
+ Error ("Couldn't parse %s", projectfile);
+
+ for (int i = 0; i < g_nPathFixupCount; i++)
+ {
+ char *pPath = ValueForKey (g_qeglobals.d_project_entity, g_pPathFixups[i]);
+ if (pPath[0] != '\\' && pPath[0] != '/')
+ {
+ if (GetFullPathName(pPath, 1024, pBuff, &pFile))
+ {
+ SetKeyValue(g_qeglobals.d_project_entity, g_pPathFixups[i], pBuff);
+ }
+ }
+ }
+
+ delete []pBuff;
+
+ // set here some default project settings you need
+ if ( strlen( ValueForKey( g_qeglobals.d_project_entity, "brush_primit" ) ) == 0 )
+ {
+ SetKeyValue( g_qeglobals.d_project_entity, "brush_primit", "0" );
+ }
+
+ g_qeglobals.m_bBrushPrimitMode = IntForKey( g_qeglobals.d_project_entity, "brush_primit" );
+
+
+ Eclass_InitForSourceDirectory (ValueForKey (g_qeglobals.d_project_entity, "entitypath"));
+ FillClassList(); // list in entity window
+
+ Map_New();
+
+
+ FillTextureMenu();
+ FillBSPMenu();
+
+ return true;
+}
+
+/*
+===========
+QE_SaveProject
+===========
+*/
+//extern char *bsp_commands[256];
+
+qboolean QE_SaveProject (const char* pProjectFile)
+{
+ //char filename[1024];
+ FILE *fp;
+ epair_t *ep;
+
+ //sprintf (filename, "%s\\%s.prj", g_projectdir, g_username);
+
+ if (!(fp = fopen (pProjectFile, "w+")))
+ Error ("Could not open project file!");
+
+ fprintf (fp, "{\n");
+ for (ep = g_qeglobals.d_project_entity->epairs; ep; ep=ep->next)
+ fprintf (fp, "\"%s\" \"%s\"\n", ep->key, ep->value);
+ fprintf (fp, "}\n");
+
+ fclose (fp);
+
+ return TRUE;
+}
+
+
+
+/*
+===========
+QE_KeyDown
+===========
+*/
+#define SPEED_MOVE 32
+#define SPEED_TURN 22.5
+
+
+/*
+===============
+ConnectEntities
+
+Sets target / targetname on the two entities selected
+from the first selected to the secon
+===============
+*/
+void ConnectEntities (void)
+{
+ entity_t *e1, *e2, *e;
+ char *target, *tn;
+ int maxtarg, targetnum;
+ char newtarg[32];
+
+ if (g_qeglobals.d_select_count != 2)
+ {
+ Sys_Status ("Must have two brushes selected.", 0);
+ Sys_Beep ();
+ return;
+ }
+
+ e1 = g_qeglobals.d_select_order[0]->owner;
+ e2 = g_qeglobals.d_select_order[1]->owner;
+
+ if (e1 == world_entity || e2 == world_entity)
+ {
+ Sys_Status ("Can't connect to the world.", 0);
+ Sys_Beep ();
+ return;
+ }
+
+ if (e1 == e2)
+ {
+ Sys_Status ("Brushes are from same entity.", 0);
+ Sys_Beep ();
+ return;
+ }
+
+ target = ValueForKey (e1, "target");
+ if (target && target[0])
+ strcpy (newtarg, target);
+ else
+ {
+ target = ValueForKey (e2, "targetname");
+ if (target && target[0])
+ strcpy (newtarg, target);
+ else
+ {
+ // make a unique target value
+ maxtarg = 0;
+ for (e=entities.next ; e != &entities ; e=e->next)
+ {
+ tn = ValueForKey (e, "targetname");
+ if (tn && tn[0])
+ {
+ targetnum = atoi(tn+1);
+ if (targetnum > maxtarg)
+ maxtarg = targetnum;
+ }
+ }
+ sprintf (newtarg, "t%i", maxtarg+1);
+ }
+ }
+
+ SetKeyValue (e1, "target", newtarg);
+ SetKeyValue (e2, "targetname", newtarg);
+ Sys_UpdateWindows (W_XY | W_CAMERA);
+
+ Select_Deselect();
+ Select_Brush (g_qeglobals.d_select_order[1]);
+}
+
+qboolean QE_SingleBrush (bool bQuiet)
+{
+ if ( (selected_brushes.next == &selected_brushes)
+ || (selected_brushes.next->next != &selected_brushes) )
+ {
+ if (!bQuiet)
+ {
+ Sys_Printf ("Error: you must have a single brush selected\n");
+ }
+ return false;
+ }
+ if (selected_brushes.next->owner->eclass->fixedsize)
+ {
+ if (!bQuiet)
+ {
+ Sys_Printf ("Error: you cannot manipulate fixed size entities\n");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+void QE_Init (void)
+{
+ /*
+ ** initialize variables
+ */
+ g_qeglobals.d_gridsize = 8;
+ g_qeglobals.d_showgrid = true;
+
+ /*
+ ** other stuff
+ */
+ Texture_Init (true);
+ //Cam_Init ();
+ //XY_Init ();
+ Z_Init ();
+ Terrain_Init();
+}
+
+void WINAPI QE_ConvertDOSToUnixName( char *dst, const char *src )
+{
+ while ( *src )
+ {
+ if ( *src == '\\' )
+ *dst = '/';
+ else
+ *dst = *src;
+ dst++; src++;
+ }
+ *dst = 0;
+}
+
+int g_numbrushes, g_numentities;
+
+void QE_CountBrushesAndUpdateStatusBar( void )
+{
+ static int s_lastbrushcount, s_lastentitycount;
+ static qboolean s_didonce;
+
+ //entity_t *e;
+ brush_t *b, *next;
+
+ g_numbrushes = 0;
+ g_numentities = 0;
+
+ if ( active_brushes.next != NULL )
+ {
+ for ( b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next)
+ {
+ next = b->next;
+ if (b->brush_faces )
+ {
+ if ( !b->owner->eclass->fixedsize)
+ g_numbrushes++;
+ else
+ g_numentities++;
+ }
+ }
+ }
+/*
+ if ( entities.next != NULL )
+ {
+ for ( e = entities.next ; e != &entities && g_numentities != MAX_MAP_ENTITIES ; e = e->next)
+ {
+ g_numentities++;
+ }
+ }
+*/
+ if ( ( ( g_numbrushes != s_lastbrushcount ) || ( g_numentities != s_lastentitycount ) ) || ( !s_didonce ) )
+ {
+ Sys_UpdateStatusBar();
+
+ s_lastbrushcount = g_numbrushes;
+ s_lastentitycount = g_numentities;
+ s_didonce = true;
+ }
+}
+
+char com_token[1024];
+qboolean com_eof;
+
+/*
+================
+I_FloatTime
+================
+*/
+double I_FloatTime (void)
+{
+ time_t t;
+
+ time (&t);
+
+ return t;
+#if 0
+// more precise, less portable
+ struct timeval tp;
+ struct timezone tzp;
+ static int secbase;
+
+ gettimeofday(&tp, &tzp);
+
+ if (!secbase)
+ {
+ secbase = tp.tv_sec;
+ return tp.tv_usec/1000000.0;
+ }
+
+ return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
+#endif
+}
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+ int c;
+ int len;
+
+ len = 0;
+ com_token[0] = 0;
+
+ if (!data)
+ return NULL;
+
+// skip whitespace
+skipwhite:
+ while ( (c = *data) <= ' ')
+ {
+ if (c == 0)
+ {
+ com_eof = true;
+ return NULL; // end of file;
+ }
+ data++;
+ }
+
+// skip // comments
+ if (c=='/' && data[1] == '/')
+ {
+ while (*data && *data != '\n')
+ data++;
+ goto skipwhite;
+ }
+
+
+// handle quoted strings specially
+ if (c == '\"')
+ {
+ data++;
+ do
+ {
+ c = *data++;
+ if (c=='\"')
+ {
+ com_token[len] = 0;
+ return data;
+ }
+ com_token[len] = c;
+ len++;
+ } while (1);
+ }
+
+// parse single characters
+ if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+ {
+ com_token[len] = c;
+ len++;
+ com_token[len] = 0;
+ return data+1;
+ }
+
+// parse a regular word
+ do
+ {
+ com_token[len] = c;
+ data++;
+ len++;
+ c = *data;
+ if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+ break;
+ } while (c>32);
+
+ com_token[len] = 0;
+ return data;
+}
+
+
+
+/*
+=============================================================================
+
+ MISC FUNCTIONS
+
+=============================================================================
+*/
+
+
+int argc;
+char *argv[MAX_NUM_ARGVS];
+
+/*
+============
+ParseCommandLine
+============
+*/
+void ParseCommandLine (char *lpCmdLine)
+{
+ argc = 1;
+ argv[0] = "programname";
+
+ while (*lpCmdLine && (argc < MAX_NUM_ARGVS))
+ {
+ while (*lpCmdLine && ((*lpCmdLine <= 32) || (*lpCmdLine > 126)))
+ lpCmdLine++;
+
+ if (*lpCmdLine)
+ {
+ argv[argc] = lpCmdLine;
+ argc++;
+
+ while (*lpCmdLine && ((*lpCmdLine > 32) && (*lpCmdLine <= 126)))
+ lpCmdLine++;
+
+ if (*lpCmdLine)
+ {
+ *lpCmdLine = 0;
+ lpCmdLine++;
+ }
+
+ }
+ }
+}
+
+
+
+/*
+=================
+CheckParm
+
+Checks for the given parameter in the program's command line arguments
+Returns the argument number (1 to argc-1) or 0 if not present
+=================
+*/
+int CheckParm (char *check)
+{
+ int i;
+
+ for (i = 1;i<argc;i++)
+ {
+ if ( stricmp(check, argv[i]) )
+ return i;
+ }
+
+ return 0;
+}
+
+
+
+
+/*
+==============
+ParseNum / ParseHex
+==============
+*/
+int ParseHex (char *hex)
+{
+ char *str;
+ int num;
+
+ num = 0;
+ str = hex;
+
+ while (*str)
+ {
+ num <<= 4;
+ if (*str >= '0' && *str <= '9')
+ num += *str-'0';
+ else if (*str >= 'a' && *str <= 'f')
+ num += 10 + *str-'a';
+ else if (*str >= 'A' && *str <= 'F')
+ num += 10 + *str-'A';
+ else
+ Error ("Bad hex number: %s",hex);
+ str++;
+ }
+
+ return num;
+}
+
+
+int ParseNum (char *str)
+{
+ if (str[0] == '$')
+ return ParseHex (str+1);
+ if (str[0] == '0' && str[1] == 'x')
+ return ParseHex (str+2);
+ return atol (str);
+}
+
+
diff --git a/q3radiant/QE3.H b/q3radiant/QE3.H
new file mode 100755
index 0000000..8b78119
--- /dev/null
+++ b/q3radiant/QE3.H
@@ -0,0 +1,669 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __QE3_H__
+#define __QE3_H__
+
+// disable data conversion warnings for gl
+#pragma warning(disable : 4244) // MIPS
+#pragma warning(disable : 4136) // X86
+#pragma warning(disable : 4051) // ALPHA
+
+#include <windows.h>
+
+extern "C"
+{
+#include "qgl.h"
+}
+
+#include <math.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+// this define to use HTREEITEM and MFC stuff in the headers
+#define QERTYPES_USE_MFC
+#include "qertypes.h"
+#include "../libs/cmdlib.h"
+#include "mathlib.h"
+#include "parse.h"
+#include "lbmlib.h"
+
+#include <commctrl.h>
+#include "afxres.h"
+#include "resource.h"
+
+#include "qedefs.h"
+
+#include "qfiles.h"
+
+#include "textures.h"
+#include "brush.h"
+#include "entity.h"
+#include "map.h"
+#include "select.h"
+#include "splines/splines.h"
+
+#include "camera.h"
+#include "xy.h"
+#include "z.h"
+#include "mru.h"
+
+#include "undo.h"
+
+#include "terrain.h"
+
+// the dec offsetof macro doesn't work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
+
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+double I_FloatTime (void);
+
+void Error (char *error, ...);
+void Warning (char *error, ...);
+int CheckParm (char *check);
+void ParseCommandLine (char *lpCmdLine);
+
+
+int ParseNum (char *str);
+
+
+char *COM_Parse (char *data);
+
+extern char com_token[1024];
+extern qboolean com_eof;
+
+#define MAX_NUM_ARGVS 32
+extern int argc;
+extern char *argv[MAX_NUM_ARGVS];
+
+
+typedef struct
+{
+ int p1, p2;
+ face_t *f1, *f2;
+} pedge_t;
+
+typedef struct
+{
+ int iSize;
+ int iTexMenu; // nearest, linear, etc
+ float fGamma; // gamma for textures
+ char szProject[256]; // last project loaded
+ vec3_t colors[COLOR_LAST];
+ qboolean show_names;
+ qboolean show_coordinates;
+ int exclude;
+ int m_nTextureTweak;
+} SavedInfo_t;
+
+//
+// system functions
+//
+// TTimo NOTE: WINAPI funcs can be accessed by plugins
+void Sys_UpdateStatusBar( void );
+void WINAPI Sys_UpdateWindows (int bits);
+void Sys_Beep (void);
+void Sys_ClearPrintf (void);
+void Sys_Printf (char *text, ...);
+double Sys_DoubleTime (void);
+void Sys_GetCursorPos (int *x, int *y);
+void Sys_SetCursorPos (int x, int y);
+void Sys_SetTitle (char *text);
+void Sys_BeginWait (void);
+void Sys_EndWait (void);
+void Sys_Status(const char *psz, int part);
+
+/*
+** most of the QE globals are stored in this structure
+*/
+typedef struct
+{
+ qboolean d_showgrid;
+ int d_gridsize;
+
+ int d_num_entities;
+
+ entity_t *d_project_entity;
+
+ float d_new_brush_bottom_z,
+ d_new_brush_top_z;
+
+ HINSTANCE d_hInstance;
+
+ HGLRC d_hglrcBase;
+ HDC d_hdcBase;
+
+ HWND d_hwndMain;
+ HWND d_hwndCamera;
+ HWND d_hwndEdit;
+ HWND d_hwndEntity;
+ HWND d_hwndTexture;
+ HWND d_hwndXY;
+ HWND d_hwndZ;
+ HWND d_hwndStatus;
+ HWND d_hwndGroup;
+ HWND d_hwndMedia;
+
+ vec3_t d_points[MAX_POINTS];
+ int d_numpoints;
+ pedge_t d_edges[MAX_EDGES];
+ int d_numedges;
+
+ // terrain variables
+ float d_terrainBrushSize;
+ terrainnoise_t d_terrainNoiseType;
+ terrainfalloff_t d_terrainFalloff;
+ terrainbrush_t d_terrainBrush;
+ int d_terrainWidth;
+ int d_terrainHeight;
+
+ terrainVert_t *d_terrapoints[MAX_TERRA_POINTS];
+ int d_numterrapoints;
+
+
+ int d_num_move_points;
+ float *d_move_points[4096];
+
+ qtexture_t *d_qtextures;
+
+ texturewin_t d_texturewin;
+
+ int d_pointfile_display_list;
+
+ xy_t d_xyOld;
+
+ LPMRUMENU d_lpMruMenu;
+
+ SavedInfo_t d_savedinfo;
+
+ int d_workcount;
+
+ // connect entities uses the last two brushes selected
+ int d_select_count;
+ brush_t *d_select_order[2];
+ vec3_t d_select_translate; // for dragging w/o making new display lists
+ select_t d_select_mode;
+ idPointListInterface *selectObject; //
+
+ int d_font_list;
+
+ int d_parsed_brushes;
+
+ qboolean show_blocks;
+
+ // Timo
+ // tells if we are internally using brush primitive (texture coordinates and map format)
+ // this is a shortcut for IntForKey( g_qeglobals.d_project_entity, "brush_primit" )
+ // NOTE: must keep the two ones in sync
+ BOOL m_bBrushPrimitMode;
+
+ // used while importing brush data from file or memory buffer
+ // tells if conversion between map format and internal preferences ( m_bBrushPrimitMode ) is needed
+ qboolean bNeedConvert;
+ qboolean bOldBrushes;
+ qboolean bPrimitBrushes;
+
+ vec3_t d_vAreaTL;
+ vec3_t d_vAreaBR;
+
+ // tells if we are using .INI files for prefs instead of registry
+ qboolean use_ini;
+ // even in .INI mode we use the registry for all void* prefs
+ char use_ini_registry[64];
+
+ //Timo
+ // tells we have surface properties plugin
+ qboolean bSurfacePropertiesPlugin;
+ // tells we are using a BSP frontend plugin
+ qboolean bBSPFrontendPlugin;
+
+ qboolean dontDrawSelectedOutlines;
+
+} QEGlobals_t;
+
+//void *qmalloc (size_t size);
+char *copystring (char *s);
+char *ExpandReletivePath (char *p);
+
+void Pointfile_Delete (void);
+void WINAPI Pointfile_Check (void);
+void Pointfile_Next (void);
+void Pointfile_Prev (void);
+void Pointfile_Clear (void);
+void Pointfile_Draw( void );
+void Pointfile_Load( void );
+
+//
+// drag.c
+//
+void Drag_Begin (int x, int y, int buttons,
+ vec3_t xaxis, vec3_t yaxis,
+ vec3_t origin, vec3_t dir);
+void Drag_MouseMoved (int x, int y, int buttons);
+void Drag_MouseUp (int nButtons = 0);
+
+//
+// csg.c
+//
+void CSG_MakeHollow (void);
+void CSG_Subtract (void);
+void CSG_Merge (void);
+
+//
+// vertsel.c
+//
+
+void SetupVertexSelection (void);
+void SelectEdgeByRay (vec3_t org, vec3_t dir);
+void SelectVertexByRay (vec3_t org, vec3_t dir);
+
+void ConnectEntities (void);
+
+extern int update_bits;
+
+extern int screen_width;
+extern int screen_height;
+
+extern HANDLE bsp_process;
+extern HANDLE g_hBSPOutput;
+extern HANDLE g_hBSPInput;
+
+
+char *TranslateString (char *buf);
+
+void ProjectDialog (void);
+
+void FillTextureMenu (CStringArray* pArray = NULL);
+void FillBSPMenu (void);
+
+BOOL CALLBACK Win_Dialog (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+);
+
+
+//
+// win_cam.c
+//
+void WCam_Create (HINSTANCE hInstance);
+
+
+//
+// win_xy.c
+//
+void WXY_Create (HINSTANCE hInstance);
+
+//
+// win_z.c
+//
+void WZ_Create (HINSTANCE hInstance);
+
+//
+// win_ent.c
+//
+
+
+//
+// win_main.c
+//
+void Main_Create (HINSTANCE hInstance);
+extern BOOL SaveWindowState(HWND hWnd, const char *pszName);
+extern BOOL LoadWindowState(HWND hWnd, const char *pszName);
+
+extern BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize);
+extern BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize);
+
+//
+// entityw.c
+//
+BOOL CreateEntityWindow(HINSTANCE hInstance);
+void FillClassList (void);
+BOOL UpdateEntitySel(eclass_t *pec);
+void SetInspectorMode(int iType);
+int DrawTexControls(HWND hWnd);
+void SetSpawnFlags(void);
+void GetSpawnFlags(void);
+void SetKeyValuePairs(bool bClearMD3 = false);
+extern void BuildGammaTable(float g);
+BOOL GetSelectAllCriteria(CString &strKey, CString &strVal);
+
+
+// win_dlg.c
+
+void DoGamma(void);
+void DoFind(void);
+void DoRotate(void);
+void DoSides(bool bCone = false, bool bSphere = false, bool bTorus = false);
+void DoAbout(void);
+void DoSurface();
+
+/*
+** QE function declarations
+*/
+void QE_CheckAutoSave( void );
+void WINAPI QE_ConvertDOSToUnixName( char *dst, const char *src );
+void QE_CountBrushesAndUpdateStatusBar( void );
+void WINAPI QE_CheckOpenGLForErrors(void);
+void QE_ExpandBspString (char *bspaction, char *out, char *mapname, bool useTemps);
+void QE_Init (void);
+qboolean QE_KeyDown (int key, int nFlags = 0);
+qboolean QE_LoadProject (char *projectfile);
+qboolean QE_SingleBrush (bool bQuiet = false);
+
+
+// sys stuff
+void Sys_MarkMapModified (void);
+
+/*
+** QE Win32 function declarations
+*/
+int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer );
+void QEW_StopGL( HWND hWnd, HGLRC hGLRC, HDC hDC );
+
+/*
+** extern declarations
+*/
+extern QEGlobals_t g_qeglobals;
+
+//++timo clean (moved into qertypes.h)
+//enum VIEWTYPE {YZ, XZ, XY};
+qboolean IsBrushSelected(brush_t* bSel);
+
+// curve brushes
+
+void Curve_MakeCurvedBrush (qboolean negative, qboolean top, qboolean bottom,
+ qboolean s1, qboolean s2, qboolean s3, qboolean s4);
+
+void Curve_Invert (void);
+
+void Curve_AddFakePlanes( brush_t *B );
+void Curve_StripFakePlanes( brush_t *B );
+void Curve_BuildPoints (brush_t *b);
+void Curve_XYDraw (brush_t *b);
+void Curve_CameraDraw (brush_t *b);
+
+void Curve_WriteFile (char *name);
+
+
+// patch stuff
+
+extern bool g_bSameView;
+extern int g_nPatchClickedView;
+bool within(vec3_t vTest, vec3_t vTL, vec3_t vBR);
+
+void Brush_RebuildBrush(brush_t *b, vec3_t vMins, vec3_t vMaxs );
+patchMesh_t* MakeNewPatch();
+brush_t* AddBrushForPatch(patchMesh_t *pm, bool bLinkToWorld = true);
+brush_t* Patch_GenericMesh(int nWidth, int nHeight, int nOrientation = 2, bool bDeleteSource = true, bool bOverride = false);
+void Patch_ReadFile (char *name);
+void Patch_WriteFile (char *name);
+void Patch_BuildPoints (brush_t *b);
+void Patch_Move(patchMesh_t *p, const vec3_t vMove, bool bRebuild = false);
+//++timo had to add a default value for bSnap (see Patch_ApplyMatrix call from Select_ApplyMatrix in select.cpp)
+void Patch_ApplyMatrix(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[3], bool bSnap = false);
+void Patch_EditPatch();
+void Patch_Deselect();
+void Patch_Deselect(patchMesh_t *p);
+void Patch_Delete(patchMesh_t *p);
+int Patch_MemorySize(patchMesh_t *p);
+void Patch_Select(patchMesh_t *p);
+void Patch_Scale(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuilt = true);
+void Patch_Cleanup();
+void Patch_SetView(int n);
+void Patch_SetTexture(patchMesh_t *p, texdef_t *tex_def, IPluginTexdef* pPlugTexdef = NULL);
+void Patch_BrushToMesh(bool bCone = false, bool bBevel = false, bool bEndcap = false, bool bSquare = false, int nHeight = 3);
+bool Patch_DragScale(patchMesh_t *p, vec3_t vAmt, vec3_t vMove);
+void Patch_ReadBuffer(char* pBuff, bool bSelect = false);
+void Patch_WriteFile (CMemFile* pMemFile);
+void Patch_UpdateSelected(vec3_t vMove);
+void Patch_AddRow(patchMesh_t *p);
+brush_t* Patch_Parse(bool bOld);
+void Patch_Write (patchMesh_t *p, FILE *f);
+void Patch_Write (patchMesh_t *p, CMemFile *file);
+void Patch_AdjustColumns(patchMesh_t *p, int nCols);
+void Patch_AdjustRows(patchMesh_t *p, int nRows);
+void Patch_AdjustSelected(bool bInsert, bool bColumn, bool bFlag);
+patchMesh_t* Patch_Duplicate(patchMesh_t *pFrom);
+void Patch_RotateTexture(patchMesh_t *p, float fAngle);
+void Patch_ScaleTexture(patchMesh_t *p, float fx, float fy, bool bFixup = true);
+void Patch_ShiftTexture(patchMesh_t *p, float fx, float fy);
+void Patch_DrawCam(patchMesh_t *p);
+void Patch_DrawXY(patchMesh_t *p);
+void Patch_InsertColumn(patchMesh_t *p, bool bAdd);
+void Patch_InsertRow(patchMesh_t *p, bool bAdd);
+void Patch_RemoveRow(patchMesh_t *p, bool bFirst);
+void Patch_RemoveColumn(patchMesh_t *p, bool bFirst);
+void Patch_ToggleInverted();
+void Patch_Restore(patchMesh_t *p);
+void Patch_Save(patchMesh_t *p);
+void Patch_SetTextureInfo(texdef_t* pt);
+void Patch_NaturalTexturing();
+void Patch_ResetTexturing(float fx, float fy);
+void Patch_FitTexturing();
+void Patch_BendToggle();
+void Patch_StartInsDel();
+void Patch_BendHandleTAB();
+void Patch_BendHandleENTER();
+void Patch_SelectBendNormal();
+void Patch_SelectBendAxis();
+bool WINAPI OnlyPatchesSelected();
+bool WINAPI AnyPatchesSelected();
+patchMesh_t* SinglePatchSelected();
+void Patch_CapCurrent(bool bInvertedBevel = false, bool bInvertedEndcap = false);
+void Patch_DisperseRows();
+void Patch_DisperseColumns();
+void Patch_NaturalizeSelected(bool bCap = false, bool bCycleCap = false);
+void Patch_SelectAreaPoints();
+void Patch_InvertTexture(bool bY);
+void Patch_InsDelToggle();
+void Patch_InsDelHandleTAB();
+void Patch_InsDelHandleENTER();
+void Patch_SetOverlays();
+void Patch_ClearOverlays();
+void Patch_Thicken(int nAmount, bool bSeam);
+void Patch_Transpose();
+void Patch_Freeze();
+void Patch_UnFreeze(bool bAll);
+const char* Patch_GetTextureName();
+void Patch_FindReplaceTexture(brush_t *pb, const char *pFind, const char *pReplace, bool bForce);
+void Patch_ReplaceQTexture(brush_t *pb, qtexture_t *pOld, qtexture_t *pNew);
+void Select_SnapToGrid();
+extern bool g_bPatchShowBounds;
+extern bool g_bPatchWireFrame;
+extern bool g_bPatchWeld;
+extern bool g_bPatchDrillDown;
+extern bool g_bPatchInsertMode;
+extern bool g_bPatchBendMode;
+extern vec3_t g_vBendOrigin;
+void Patch_FromTriangle(vec5_t vx, vec5_t vy, vec5_t vz);
+const char* Patch_GetKeyValue(patchMesh_t *p, const char *pKey);
+void Patch_SetEpair(patchMesh_t *p, const char *pKey, const char *pValue);
+
+
+
+// group stuff
+// group_t are loaded / saved through "group_info" entities
+// they hold epairs for group settings and additionnal access info (tree nodes)
+typedef struct group_s
+{
+ struct group_s *next;
+ epair_t *epairs;
+ HTREEITEM itemOwner;
+} group_t;
+
+// NOTES: grouping only enabled in brush primitives mode
+// grouping works by naming brushes and setting display properties
+// the group hierarchy is not related with the map hierarchy (entity list, brushes etc.)
+// brushes with no group are under the "world" node (default for all brushes)
+// void Group_GetListFromWorld(CStringArray *pArray);
+void Group_RemoveListFromWorld();
+// void Group_SetListToWorld(CStringArray *pArray);
+// void Group_BuildTree(CTreeCtrl *pTree);
+// void Group_DecomposeTree(CTreeCtrl *pTree);
+// save group_t as "classname" "group_info" things
+void Group_Save(FILE *f);
+// clean the brushes ownerItem, clean the treeview and rebuild everything
+// is usually called when loading a new map, but may be called anytime
+void Group_Init();
+void Group_Add(entity_t *e);
+
+// remove a brush from it's current group, will erase the "group" epair if any, and delete the tree control node
+void Group_RemoveBrush(brush_t *b);
+void Group_AddToWorld(brush_t *b);
+// will remove brush of it's current group if any, and will add it wherever needed according to it's "group" key
+void Group_AddToProperGroup(brush_t *b);
+void Group_AddToSelected(brush_t *b);
+// allocate a new group, set name
+group_t* Group_Alloc(const char *name);
+// we use entities to store information about the groups
+// these entities are not linked into the world, and they have no brushes
+// only loaded / saved in map file
+group_t* Group_ForName(const char *name);
+
+// Timo
+// new brush primitive stuff
+void ComputeAxisBase(vec3_t normal,vec3_t texS,vec3_t texT );
+void FaceToBrushPrimitFace(face_t *f);
+void EmitBrushPrimitTextureCoordinates(face_t *, winding_t *);
+// EmitTextureCoordinates, is old code used for brush to brush primitive conversion
+void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f);
+void BrushPrimit_Parse(brush_t *);
+// compute a fake shift scale rot representation from the texture matrix
+void TexMatToFakeTexCoords( vec_t texMat[2][3], float shift[2], float *rot, float scale[2] );
+void FakeTexCoordsToTexMat( float shift[2], float rot, float scale[2], vec_t texMat[2][3] );
+void ConvertTexMatWithQTexture( brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2 );
+// texture locking
+void Face_MoveTexture_BrushPrimit(face_t *f, vec3_t delta);
+void Select_ShiftTexture_BrushPrimit( face_t *f, int x, int y );
+void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, vec3_t vOrigin );
+// used in CCamWnd::ShiftTexture_BrushPrimit
+void ComputeBest2DVector( vec3_t v, vec3_t X, vec3_t Y, int &x, int &y );
+
+
+//
+// eclass.cpp
+//
+extern qboolean parsing_single;
+extern qboolean eclass_found;
+extern eclass_t *eclass_e;
+void Eclass_ScanFile( char *filename );
+
+// for interfaces, we require main plugin header included
+#include "qerplugin.h"
+
+//
+// SurfaceDlg.cpp and surface properties plugin
+//
+//++timo some patch in/out stuff is in there, needs to be moved out in a dedicated interface
+void WINAPI Patch_Rebuild(patchMesh_t *p);
+#include "isurfaceplugin.h"
+extern _QERPlugSurfaceTable g_SurfaceTable;
+
+//
+// OpenGL interface
+//
+#include "igl.h"
+HGLRC WINAPI QERApp_GetQeglobalsHGLRC();
+void WINAPI QERApp_HookXYGLWindow(IGLWindow* pGLW);
+void WINAPI QERApp_UnHookGLWindow(IGLWindow* pGLW);
+void DrawPluginEntities( VIEWTYPE vt );
+
+//
+// ISelectedFace interface
+//
+#include "ISelectedFace.h"
+int WINAPI QERApp_ISelectedFace_GetTextureNumber();
+int WINAPI QERApp_GetFaceInfo(_QERFaceData *pFaceData, winding_t *pWinding);
+int WINAPI QERApp_SetFaceInfo(_QERFaceData *pFaceData);
+void WINAPI QERApp_GetTextureSize( int Size[2] );
+
+//
+// IEpairs interface
+//
+#include "IEpairs.h"
+#include "EpairsWrapper.h"
+
+//
+// IPluginEntities interface
+//
+#include "IPluginEntities.h"
+int WINAPI QERApp_EClassScanDir( char *dir, HMODULE plugID );
+
+//
+// ShaderInfo.cpp
+//
+#include "ShaderInfo.h"
+
+//
+// TexWnd.cpp
+//
+CShaderInfo* hasShader(const char *pName);
+
+//
+// IScripLib interface
+// GetToken, UnGetToken, etc.
+#include "IScriplib.h"
+extern FILE *g_File;
+void WINAPI QERApp_MapPrintf_FILE( char *text, ... );
+
+//
+// ISurfacePlugin interface
+//
+void WINAPI QERApp_GetTwoSelectedPatch( patchMesh_t **p1, patchMesh_t **p2 );
+
+//
+// IBSPFrontend interface
+//
+#include "IBSPFrontend.h"
+extern _QERPlugBSPFrontendTable g_BSPFrontendTable;
+extern CStringArray g_BSPFrontendCommands;
+
+//
+// IMessaging interface
+#include "IMessaging.h"
+#include "Messaging.h"
+void WINAPI QERApp_HookWindow(IWindowListener* pListen);
+void WINAPI QERApp_UnHookWindow(IWindowListener* pListen);
+IXYWndWrapper* WINAPI QERApp_GetXYWndWrapper();
+void WINAPI QERApp_HookListener(IListener* pListen, int Msg);
+int WINAPI QERApp_UnHookListener(IListener* pListen);
+void DispatchRadiantMsg( int Msg );
+// dispatch for IWindowListener entities
+void DispatchOnMouseMove(UINT nFlags, int x, int y);
+bool DispatchOnLButtonDown(UINT nFlags, int x, int y);
+bool DispatchOnLButtonUp(UINT nFlags, int x, int y);
+
+//
+// IShaders interface
+CShaderInfo* SetNameShaderInfo(qtexture_t* q, const char* pPath, const char* pName);
+qtexture_t* Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char* pPath, int nFlags, int nContents, int nValue );
+#include "IShaders.h"
+qtexture_t* WINAPI QERApp_TryTextureForName(const char* name);
+
+
+
+#endif
diff --git a/q3radiant/QEDEFS.H b/q3radiant/QEDEFS.H
new file mode 100755
index 0000000..355787d
--- /dev/null
+++ b/q3radiant/QEDEFS.H
@@ -0,0 +1,164 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __QEDEFS_H__
+#define __QEDEFS_H__
+
+#define QE_VERSION 0x0501
+
+#define QE3_STYLE (WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_CHILD)
+#define QE3_STYLE2 (WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MINIMIZEBOX | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU)
+#define QE3_CHILDSTYLE (WS_OVERLAPPED | WS_MINIMIZEBOX | WS_THICKFRAME | WS_CAPTION | WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MAXIMIZEBOX)
+
+#define QE3_SPLITTER_STYLE (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
+
+
+
+#define QE_AUTOSAVE_INTERVAL 5 // number of minutes between autosaves
+
+#define _3DFXCAMERA_WINDOW_CLASS "Q3DFXCamera"
+#define CAMERA_WINDOW_CLASS "QCamera"
+#define XY_WINDOW_CLASS "QXY"
+#define Z_WINDOW_CLASS "QZ"
+#define ENT_WINDOW_CLASS "QENT"
+#define TEXTURE_WINDOW_CLASS "QTEX"
+
+#define ZWIN_WIDTH 40
+#define CWIN_SIZE (0.4)
+
+#define MAX_EDGES 512
+//#define MAX_POINTS 1024
+#define MAX_POINTS 2048
+
+#define MAX_TERRA_POINTS 4096
+
+#define CMD_TEXTUREWAD 60000
+#define CMD_BSPCOMMAND 61000
+
+#define PITCH 0
+#define YAW 1
+#define ROLL 2
+
+#define QE_TIMER0 1
+
+#define PLANE_X 0
+#define PLANE_Y 1
+#define PLANE_Z 2
+#define PLANE_ANYX 3
+#define PLANE_ANYY 4
+#define PLANE_ANYZ 5
+
+#define ON_EPSILON 0.01
+
+#define KEY_FORWARD 1
+#define KEY_BACK 2
+#define KEY_TURNLEFT 4
+#define KEY_TURNRIGHT 8
+#define KEY_LEFT 16
+#define KEY_RIGHT 32
+#define KEY_LOOKUP 64
+#define KEY_LOOKDOWN 128
+#define KEY_UP 256
+#define KEY_DOWN 512
+
+// xy.c
+#define EXCLUDE_LIGHTS 0x01
+#define EXCLUDE_ENT 0x02
+#define EXCLUDE_PATHS 0x04
+#define EXCLUDE_WATER 0x08
+#define EXCLUDE_WORLD 0x10
+#define EXCLUDE_CLIP 0x20
+#define EXCLUDE_DETAIL 0x40
+#define EXCLUDE_CURVES 0x80
+#define INCLUDE_EASY 0x100
+#define INCLUDE_NORMAL 0x200
+#define INCLUDE_HARD 0x400
+#define INCLUDE_DEATHMATCH 0x800
+#define EXCLUDE_HINT 0x1000
+#define EXCLUDE_CAULK 0x2000
+#define EXCLUDE_ANGLES 0x4000
+#define EXCLUDE_TERRAIN 0x8000
+
+
+//
+// menu indexes for modifying menus
+//
+#define MENU_VIEW 2
+#define MENU_BSP 4
+#define MENU_TEXTURE 6
+#define MENU_PLUGIN 11
+
+
+// odd things not in windows header...
+#define VK_COMMA 188
+#define VK_PERIOD 190
+
+/*
+** window bits
+*/
+//++timo moved to qertypes.h
+// clean
+/*
+#define W_CAMERA 0x0001
+#define W_XY 0x0002
+#define W_XY_OVERLAY 0x0004
+#define W_Z 0x0008
+#define W_TEXTURE 0x0010
+#define W_Z_OVERLAY 0x0020
+#define W_CONSOLE 0x0040
+#define W_ENTITY 0x0080
+#define W_CAMERA_IFON 0x0100
+#define W_XZ 0x0200 //--| only used for patch vertex manip stuff
+#define W_YZ 0x0400 //--|
+#define W_ALL 0xFFFFFFFF
+*/
+
+#define COLOR_TEXTUREBACK 0
+#define COLOR_GRIDBACK 1
+#define COLOR_GRIDMINOR 2
+#define COLOR_GRIDMAJOR 3
+#define COLOR_CAMERABACK 4
+#define COLOR_ENTITY 5
+#define COLOR_GRIDBLOCK 6
+#define COLOR_GRIDTEXT 7
+#define COLOR_BRUSHES 8
+#define COLOR_SELBRUSHES 9
+#define COLOR_CLIPPER 10
+#define COLOR_VIEWNAME 11
+#define COLOR_LAST 12
+
+// classes
+#define ENTITY_WIREFRAME 0x00001
+#define ENTITY_SKIN_MODEL 0x00010
+#define ENTITY_SELECTED_ONLY 0x00100
+#define ENTITY_BOXED 0x01000
+
+// menu settings
+#define ENTITY_BOX 0x01000
+#define ENTITY_WIRE 0x00001
+#define ENTITY_SELECTED 0x00101
+#define ENTITY_SKINNED 0x00010
+#define ENTITY_SKINNED_BOXED 0x01010
+#define ENTITY_SELECTED_SKIN 0x00110
+
+
+
+#endif
diff --git a/q3radiant/QERTYPES.H b/q3radiant/QERTYPES.H
new file mode 100755
index 0000000..eeb99c1
--- /dev/null
+++ b/q3radiant/QERTYPES.H
@@ -0,0 +1,454 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// qertypes.h
+//
+// common types
+// merged from brush.h, etc. for plugin support
+//
+#ifndef _QERTYPE_H
+#define _QERTYPE_H
+
+#ifndef __BYTEBOOL__
+#define __BYTEBOOL__
+typedef boolean qboolean;
+//typedef unsigned char byte;
+#endif
+
+#define MAXPOINTS 16
+
+typedef float vec_t;
+typedef vec_t vec2_t[2];
+typedef vec_t vec3_t[3];
+
+#include "splines/math_vector.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+#endif
+
+class texdef_t
+{
+public:
+ texdef_t()
+ {
+ name = new char[1];
+ name[0] = '\0';
+ }
+ ~texdef_t()
+ {
+ delete []name;
+ name = NULL;
+ }
+
+ const char *Name( void )
+ {
+ if ( name ) {
+ return name;
+ }
+
+ return "";
+ }
+
+ void SetName(const char *p)
+ {
+ if (name)
+ {
+ delete []name;
+ }
+ if (p)
+ {
+ name = strcpy(new char[strlen(p)+1], p);
+ }
+ else
+ {
+ name = new char[1];
+ name[0] = '\0';
+ }
+ }
+
+ texdef_t& operator =(const texdef_t& rhs)
+ {
+ if (&rhs != this)
+ {
+ SetName(rhs.name);
+ shift[0] = rhs.shift[0];
+ shift[1] = rhs.shift[1];
+ rotate = rhs.rotate;
+ scale[0] = rhs.scale[0];
+ scale[1] = rhs.scale[1];
+ contents = rhs.contents;
+ flags = rhs.flags;
+ value = rhs.value;
+ }
+ return *this;
+ }
+ //char name[128];
+ char *name;
+ float shift[2];
+ float rotate;
+ float scale[2];
+ int contents;
+ int flags;
+ int value;
+};
+
+// Timo
+// new brush primitive texdef
+typedef struct brushprimit_texdef_s
+{
+ vec_t coords[2][3];
+} brushprimit_texdef_t;
+
+class texturewin_t
+{
+public:
+ texturewin_t()
+ {
+ }
+ ~texturewin_t()
+ {
+ }
+ int width, height;
+ int originy;
+ // add brushprimit_texdef_t for brush primitive coordinates storage
+ brushprimit_texdef_t brushprimit_texdef;
+ int m_nTotalHeight;
+ // surface plugin, must be casted to a IPluginTexdef*
+ void* pTexdef;
+ texdef_t texdef;
+};
+
+#define QER_TRANS 0x00000001
+#define QER_NOCARVE 0x00000002
+
+typedef struct qtexture_s
+{
+ struct qtexture_s *next;
+ char name[64]; // includes partial directory and extension
+ int width, height;
+ int contents;
+ int flags;
+ int value;
+ int texture_number; // gl bind number
+
+ // name of the .shader file
+ char shadername[1024]; // old shader stuff
+ qboolean bFromShader; // created from a shader
+ float fTrans; // amount of transparency
+ int nShaderFlags; // qer_ shader flags
+ vec3_t color; // for flat shade mode
+ qboolean inuse; // true = is present on the level
+
+ // cast this one to an IPluginQTexture if you are using it
+ // NOTE: casting can be done with a GETPLUGINQTEXTURE defined in isurfaceplugin.h
+ // TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginQTexture *pPluginQTexture } kind of thing ?
+ void *pData;
+
+ //++timo FIXME: this is the actual filename of the texture
+ // this will be removed after shader code cleanup
+ char filename[64];
+
+} qtexture_t;
+
+// NOTE: don't trust this definition!
+// you should read float points[..][5]
+// see NewWinding definition
+#define MAX_POINTS_ON_WINDING 64
+typedef struct
+{
+ int numpoints;
+ int maxpoints;
+ float points[8][5]; // variable sized
+} winding_t;
+
+typedef struct
+{
+ vec3_t normal;
+ double dist;
+ int type;
+} plane_t;
+
+//++timo texdef and brushprimit_texdef are static
+// TODO : do dynamic ?
+typedef struct face_s
+{
+ struct face_s *next;
+ struct face_s *original; //used for vertex movement
+ vec3_t planepts[3];
+ texdef_t texdef;
+ plane_t plane;
+
+ winding_t *face_winding;
+
+ vec3_t d_color;
+ qtexture_t *d_texture;
+
+ // Timo new brush primit texdef
+ brushprimit_texdef_t brushprimit_texdef;
+
+ // cast this one to an IPluginTexdef if you are using it
+ // NOTE: casting can be done with a GETPLUGINTEXDEF defined in isurfaceplugin.h
+ // TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginTexdef *pPluginTexdef } kind of thing ?
+ void *pData;
+} face_t;
+
+typedef struct {
+ vec3_t xyz;
+ float sideST[2];
+ float capST[2];
+} curveVertex_t;
+
+typedef struct {
+ curveVertex_t v[2];
+} sideVertex_t;
+
+
+#define MIN_PATCH_WIDTH 3
+#define MIN_PATCH_HEIGHT 3
+
+#define MAX_PATCH_WIDTH 16
+#define MAX_PATCH_HEIGHT 16
+
+// patch type info
+// type in lower 16 bits, flags in upper
+// endcaps directly follow this patch in the list
+
+// types
+#define PATCH_GENERIC 0x00000000 // generic flat patch
+#define PATCH_CYLINDER 0x00000001 // cylinder
+#define PATCH_BEVEL 0x00000002 // bevel
+#define PATCH_ENDCAP 0x00000004 // endcap
+#define PATCH_HEMISPHERE 0x00000008 // hemisphere
+#define PATCH_CONE 0x00000010 // cone
+#define PATCH_TRIANGLE 0x00000020 // simple tri, assumes 3x3 patch
+
+// behaviour styles
+#define PATCH_CAP 0x00001000 // flat patch applied as a cap
+#define PATCH_SEAM 0x00002000 // flat patch applied as a seam
+#define PATCH_THICK 0x00004000 // patch applied as a thick portion
+
+// styles
+#define PATCH_BEZIER 0x00000000 // default bezier
+#define PATCH_BSPLINE 0x10000000 // bspline
+
+#define PATCH_TYPEMASK 0x00000fff //
+#define PATCH_BTYPEMASK 0x0000f000 //
+#define PATCH_STYLEMASK 0xffff0000 //
+
+typedef struct {
+ vec3_t xyz;
+ float st[2];
+ float lightmap[2];
+ vec3_t normal;
+} drawVert_t;
+
+// used in brush primitive AND entities
+typedef struct epair_s
+{
+ struct epair_s *next;
+ char *key;
+ char *value;
+} epair_t;
+
+struct brush_s;
+typedef struct brush_s brush_t;
+
+typedef struct {
+ int width, height; // in control points, not patches
+ int contents, flags, value, type;
+ qtexture_t *d_texture;
+ drawVert_t ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
+ brush_t *pSymbiot;
+ qboolean bSelected;
+ qboolean bOverlay;
+ qboolean bDirty;
+ int nListID;
+ epair_t *epairs;
+ // cast this one to an IPluginTexdef if you are using it
+ // NOTE: casting can be done with a GETPLUGINTEXDEF defined in isurfaceplugin.h
+ // TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginTexdef *pPluginTexdef } kind of thing ?
+ void *pData;
+} patchMesh_t;
+
+typedef struct {
+ int index;
+ qtexture_t *texture;
+ texdef_t texdef;
+} terrainFace_t;
+
+typedef struct {
+ float height;
+ float scale;
+ terrainFace_t tri;
+ vec4_t rgba;
+ vec3_t normal;
+ vec3_t xyz;
+} terrainVert_t;
+
+#define MAX_TERRAIN_TEXTURES 128
+typedef struct {
+ int width, height;
+
+ vec3_t mins, maxs;
+ vec3_t origin;
+ float scale_x;
+ float scale_y;
+
+ int numtextures;
+ qtexture_t *textures[ MAX_TERRAIN_TEXTURES ];
+
+ terrainVert_t *heightmap; // width * height
+
+ epair_t *epairs;
+
+ brush_s *pSymbiot;
+ bool bSelected;
+ bool bDirty;
+ int nListID;
+} terrainMesh_t;
+
+typedef struct brush_s
+{
+ struct brush_s *prev, *next; // links in active/selected
+ struct brush_s *oprev, *onext; // links in entity
+ struct entity_s *owner;
+ vec3_t mins, maxs;
+ face_t *brush_faces;
+
+ qboolean bModelFailed;
+ //
+ // curve brush extensions
+ // all are derived from brush_faces
+ qboolean patchBrush;
+ qboolean hiddenBrush;
+ qboolean terrainBrush;
+
+ //int nPatchID;
+
+ patchMesh_t *pPatch;
+ terrainMesh_t *pTerrain;
+
+ struct entity_s *pUndoOwner;
+
+ int undoId; //undo ID
+ int redoId; //redo ID
+ int ownerId; //entityId of the owner entity for undo
+
+ // TTimo: HTREEITEM is MFC, some plugins really don't like it
+#ifdef QERTYPES_USE_MFC
+ int numberId; // brush number
+ HTREEITEM itemOwner; // owner for grouping
+#else
+ int numberId;
+ DWORD itemOwner;
+#endif
+
+ // brush primitive only
+ epair_t *epairs;
+
+} brush_t;
+
+
+#define MAX_FLAGS 8
+
+
+typedef struct trimodel_t
+{
+ vec3_t v[3];
+ float st[3][2];
+} trimodel;
+
+typedef struct entitymodel_t
+{
+ struct entitymodel_t *pNext;
+ int nTriCount;
+ trimodel *pTriList;
+ int nTextureBind;
+ int nSkinWidth;
+ int nSkinHeight;
+ int nModelPosition;
+} entitymodel;
+
+
+// eclass show flags
+
+#define ECLASS_LIGHT 0x00000001
+#define ECLASS_ANGLE 0x00000002
+#define ECLASS_PATH 0x00000004
+#define ECLASS_MISCMODEL 0x00000008
+#define ECLASS_PLUGINENTITY 0x00000010
+
+typedef struct eclass_s
+{
+ struct eclass_s *next;
+ char *name;
+ qboolean fixedsize;
+ qboolean unknown; // wasn't found in source
+ vec3_t mins, maxs;
+ vec3_t color;
+ texdef_t texdef;
+ char *comments;
+ char flagnames[MAX_FLAGS][32];
+
+/*
+ int nTriCount;
+ trimodel *pTriList;
+ int nTextureBind;
+ int nSkinWidth, nSkinHeight;
+*/
+ entitymodel *model;
+ char *modelpath;
+ char *skinpath;
+ int nFrame;
+ unsigned int nShowFlags;
+
+ HMODULE hPlug;
+} eclass_t;
+
+extern eclass_t *eclass;
+
+/*
+** window bits
+*/
+#define W_CAMERA 0x0001
+#define W_XY 0x0002
+#define W_XY_OVERLAY 0x0004
+#define W_Z 0x0008
+#define W_TEXTURE 0x0010
+#define W_Z_OVERLAY 0x0020
+#define W_CONSOLE 0x0040
+#define W_ENTITY 0x0080
+#define W_CAMERA_IFON 0x0100
+#define W_XZ 0x0200 //--| only used for patch vertex manip stuff
+#define W_YZ 0x0400 //--|
+#define W_GROUP 0x0800
+#define W_MEDIA 0x1000
+#define W_ALL 0xFFFFFFFF
+
+// used in some Drawing routines
+enum VIEWTYPE {YZ, XZ, XY};
+
+enum terrainnoise_t { NOISE_NONE, NOISE_PLUS, NOISE_PLUSMINUS };
+enum terrainbrush_t { TERRAIN_BRUSH_CIRCLE, TERRAIN_BRUSH_SQUARE };
+enum terrainfalloff_t { TERRAIN_FALLOFF_LINEAR, TERRAIN_FALLOFF_CURVED };
+
+#endif \ No newline at end of file
diff --git a/q3radiant/QFILES.H b/q3radiant/QFILES.H
new file mode 100755
index 0000000..5043d93
--- /dev/null
+++ b/q3radiant/QFILES.H
@@ -0,0 +1,481 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+========================================================================
+
+.MD2 triangle model file format
+
+========================================================================
+*/
+
+#define IDALIASHEADER (('2'<<24)+('P'<<16)+('D'<<8)+'I')
+#define ALIAS_VERSION 8
+
+#define MAX_TRIANGLES 4096
+#define MAX_VERTS 2048
+#define MAX_FRAMES 512
+#define MAX_MD2SKINS 32
+#define MAX_SKINNAME 64
+
+typedef struct
+{
+ short s;
+ short t;
+} dstvert_t;
+
+typedef struct
+{
+ short index_xyz[3];
+ short index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+ byte v[3]; // scaled byte to fit in frame mins/maxs
+ byte lightnormalindex;
+} dtrivertx_t;
+
+typedef struct
+{
+ float scale[3]; // multiply byte verts by this
+ float translate[3]; // then add this
+ char name[16]; // frame name from grabbing
+ dtrivertx_t verts[1]; // variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+ int ident;
+ int version;
+
+ int skinwidth;
+ int skinheight;
+ int framesize; // byte size of each frame
+
+ int num_skins;
+ int num_xyz;
+ int num_st; // greater than num_xyz for seams
+ int num_tris;
+ int num_glcmds; // dwords in strip/fan command list
+ int num_frames;
+
+ int ofs_skins; // each skin is a MAX_SKINNAME string
+ int ofs_st; // byte offset from start for stverts
+ int ofs_tris; // offset for dtriangles
+ int ofs_frames; // offset for first frame
+ int ofs_glcmds;
+ int ofs_end; // end of file
+
+} dmdl_t;
+
+#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
+#define MAX_QPATH 64 // max length of a quake game pathname
+#define MD3_XYZ_SCALE (1.0/64)
+
+typedef struct {
+ int ident;
+ int version;
+
+ char name[MAX_QPATH]; // model name
+
+ int flags;
+
+ int numFrames;
+ int numTags;
+ int numSurfaces;
+
+ int numSkins;
+
+ int ofsFrames; // offset for first frame
+ int ofsTags; // numFrames * numTags
+ int ofsSurfaces; // first surface, others follow
+
+ int ofsEnd; // end of file
+} md3Header_t;
+
+typedef struct {
+ int ident; //
+
+ char name[MAX_QPATH]; // polyset name
+
+ int flags;
+ int numFrames; // all surfaces in a model should have the same
+
+ int numShaders; // all surfaces in a model should have the same
+ int numVerts;
+
+ int numTriangles;
+ int ofsTriangles;
+
+ int ofsShaders; // offset from start of md3Surface_t
+ int ofsSt; // texture coords are common for all frames
+ int ofsXyzNormals; // numVerts * numFrames
+
+ int ofsEnd; // next surface follows
+
+} md3Surface_t;
+
+typedef struct {
+ char name[MAX_QPATH];
+ int shaderIndex; // for in-game use
+} md3Shader_t;
+
+typedef struct {
+ int indexes[3];
+} md3Triangle_t;
+
+typedef struct {
+ float st[2];
+} md3St_t;
+
+typedef struct {
+ short xyz[3];
+ short normal;
+} md3XyzNormal_t;
+
+
+typedef struct
+{
+ float st[2];
+ int nVertIndex;
+} glst_t;
+
+typedef struct
+{
+ int nCount;
+ int ObjectIndex;
+ glst_t GlSt;
+} gl_t;
+
+/*
+========================================================================
+
+.SP2 sprite file format
+
+========================================================================
+*/
+
+#define IDSPRITEHEADER (('2'<<24)+('S'<<16)+('D'<<8)+'I')
+ // little-endian "IDS2"
+#define SPRITE_VERSION 2
+
+typedef struct
+{
+ int width, height;
+ int origin_x, origin_y; // raster coordinates inside pic
+ char name[MAX_SKINNAME]; // name of pcx file
+} dsprframe_t;
+
+typedef struct {
+ int ident;
+ int version;
+ int numframes;
+ dsprframe_t frames[1]; // variable sized
+} dsprite_t;
+
+/*
+==============================================================================
+
+ .WAL texture file format
+
+==============================================================================
+*/
+
+
+#define MIPLEVELS 4
+typedef struct miptex_s
+{
+ char name[32];
+ unsigned width, height;
+ unsigned offsets[MIPLEVELS]; // four mip maps stored
+ char animname[32]; // next frame in animation chain
+ int flags;
+ int contents;
+ int value;
+} miptex_t;
+
+
+
+/*
+==============================================================================
+
+ .BSP file format
+
+==============================================================================
+*/
+
+#define IDBSPHEADER (('P'<<24)+('S'<<16)+('B'<<8)+'I')
+ // little-endian "IBSP"
+
+#define BSPVERSION 36
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define MAX_MAP_MODELS 1024
+#define MAX_MAP_BRUSHES 8192
+#define MAX_MAP_ENTITIES 2048
+#define MAX_MAP_ENTSTRING 0x20000
+#define MAX_MAP_TEXINFO 8192
+
+#define MAX_MAP_PLANES 65536
+#define MAX_MAP_NODES 65536
+#define MAX_MAP_BRUSHSIDES 65536
+#define MAX_MAP_LEAFS 65536
+#define MAX_MAP_VERTS 65536
+#define MAX_MAP_FACES 65536
+#define MAX_MAP_LEAFFACES 65536
+#define MAX_MAP_LEAFBRUSHES 65536
+#define MAX_MAP_PORTALS 65536
+#define MAX_MAP_EDGES 128000
+#define MAX_MAP_SURFEDGES 256000
+#define MAX_MAP_LIGHTING 0x200000
+#define MAX_MAP_VISIBILITY 0x100000
+
+#define MAX_WORLD_COORD ( 128*1024 )
+#define MIN_WORLD_COORD ( -128*1024 )
+#define WORLD_SIZE ( MAX_WORLD_COORD - MIN_WORLD_COORD )
+
+#define MAX_BRUSH_SIZE ( WORLD_SIZE )
+
+// key / value pair sizes
+
+#define MAX_KEY 32
+#define MAX_VALUE 1024
+
+//=============================================================================
+
+typedef struct
+{
+ int fileofs, filelen;
+} lump_t;
+
+#define LUMP_ENTITIES 0
+#define LUMP_PLANES 1
+#define LUMP_VERTEXES 2
+#define LUMP_VISIBILITY 3
+#define LUMP_NODES 4
+#define LUMP_TEXINFO 5
+#define LUMP_FACES 6
+#define LUMP_LIGHTING 7
+#define LUMP_LEAFS 8
+#define LUMP_LEAFFACES 9
+#define LUMP_LEAFBRUSHES 10
+#define LUMP_EDGES 11
+#define LUMP_SURFEDGES 12
+#define LUMP_MODELS 13
+#define LUMP_BRUSHES 14
+#define LUMP_BRUSHSIDES 15
+#define LUMP_POP 16
+
+#define HEADER_LUMPS 17
+
+typedef struct
+{
+ int ident;
+ int version;
+ lump_t lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+ float mins[3], maxs[3];
+ float origin[3]; // for sounds or lights
+ int headnode;
+ int firstface, numfaces; // submodels just draw faces
+ // without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+ float point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define PLANE_X 0
+#define PLANE_Y 1
+#define PLANE_Z 2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define PLANE_ANYX 3
+#define PLANE_ANYY 4
+#define PLANE_ANYZ 5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+ float normal[3];
+ float dist;
+ int type; // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// lower bits are stronger, and will eat weaker brushes completely
+#define CONTENTS_SOLID 1 // an eye is never valid in a solid
+#define CONTENTS_WINDOW 2 // translucent, but not watery
+#define CONTENTS_AUX 4
+#define CONTENTS_LAVA 8
+#define CONTENTS_SLIME 16
+#define CONTENTS_WATER 32
+#define CONTENTS_MIST 64
+#define LAST_VISIBLE_CONTENTS 64
+
+// remaining contents are non-visible, and don't eat brushes
+#define CONTENTS_PLAYERCLIP 0x10000
+#define CONTENTS_MONSTERCLIP 0x20000
+
+// currents can be added to any other contents, and may be mixed
+#define CONTENTS_CURRENT_0 0x40000
+#define CONTENTS_CURRENT_90 0x80000
+#define CONTENTS_CURRENT_180 0x100000
+#define CONTENTS_CURRENT_270 0x200000
+#define CONTENTS_CURRENT_UP 0x400000
+#define CONTENTS_CURRENT_DOWN 0x800000
+
+#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
+
+#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
+#define CONTENTS_DEADMONSTER 0x4000000 // corpse
+#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
+#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
+#define CONTENTS_LADDER 0x20000000 // ladder
+#define CONTENTS_NEGATIVE_CURVE 0x40000000 // reverse inside / outside
+
+#define CONTENTS_KEEP (CONTENTS_DETAIL | CONTENTS_NEGATIVE_CURVE)
+
+
+typedef struct
+{
+ int planenum;
+ int children[2]; // negative numbers are -(leafs+1), not nodes
+ short mins[3]; // for frustom culling
+ short maxs[3];
+ unsigned short firstface;
+ unsigned short numfaces; // counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+ float vecs[2][4]; // [s/t][xyz offset]
+ int flags; // miptex flags + overrides
+ int value; // light emission, etc
+ char texture[32]; // texture name (textures/*.wal)
+ int nexttexinfo; // for animations, -1 = end of chain
+} texinfo_t;
+
+
+#define SURF_LIGHT 0x1 // value will hold the light strength
+
+#define SURF_SLICK 0x2 // effects game physics
+
+#define SURF_SKY 0x4 // don't draw, but add to skybox
+#define SURF_WARP 0x8 // turbulent water warp
+#define SURF_TRANS33 0x10
+#define SURF_TRANS66 0x20
+#define SURF_FLOWING 0x40 // scroll towards angle
+#define SURF_NODRAW 0x80 // don't bother referencing the texture
+
+#define SURF_PATCH 0x20000000
+#define SURF_CURVE_FAKE 0x40000000
+#define SURF_CURVE 0x80000000
+#define SURF_KEEP (SURF_CURVE | SURF_CURVE_FAKE | SURF_PATCH)
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+ unsigned short v[2]; // vertex numbers
+} dedge_t;
+
+#define MAXLIGHTMAPS 4
+typedef struct
+{
+ unsigned short planenum;
+ short side;
+
+ int firstedge; // we must support > 64k edges
+ short numedges;
+ short texinfo;
+
+// lighting info
+ byte styles[MAXLIGHTMAPS];
+ int lightofs; // start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+ int contents; // OR of all brushes (not needed?)
+
+ int pvsofs; // -1 = no info
+ int phsofs; // -1 = no info
+
+ short mins[3]; // for frustum culling
+ short maxs[3];
+
+ unsigned short firstleafface;
+ unsigned short numleaffaces;
+
+ unsigned short firstleafbrush;
+ unsigned short numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+ unsigned short planenum; // facing out of the leaf
+ short texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+ int firstside;
+ int numsides;
+ int contents;
+} dbrush_t;
+
+#define ANGLE_UP -1
+#define ANGLE_DOWN -2
+
diff --git a/q3radiant/QGL.H b/q3radiant/QGL.H
new file mode 100755
index 0000000..c16de65
--- /dev/null
+++ b/q3radiant/QGL.H
@@ -0,0 +1,456 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+/*
+** QGL.H
+*/
+
+#ifndef __QGL_H__
+#define __QGL_H__
+
+#ifdef _WIN32
+# include <windows.h>
+#endif
+
+#include <gl/gl.h>
+#include <gl/glu.h>
+
+int QGL_Init( const char *dllname, const char* pGluName );
+void QGL_Shutdown();
+
+#ifndef APIENTRY
+# define APIENTRY
+#endif
+
+extern void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+extern void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+extern GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+extern void ( APIENTRY * qglArrayElement )(GLint i);
+extern void ( APIENTRY * qglBegin )(GLenum mode);
+extern void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+extern void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+extern void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+extern void ( APIENTRY * qglCallList )(GLuint list);
+extern void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+extern void ( APIENTRY * qglClear )(GLbitfield mask);
+extern void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+extern void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+extern void ( APIENTRY * qglClearDepth )(GLclampd depth);
+extern void ( APIENTRY * qglClearIndex )(GLfloat c);
+extern void ( APIENTRY * qglClearStencil )(GLint s);
+extern void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+extern void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+extern void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+extern void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+extern void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+extern void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+extern void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+extern void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+extern void ( APIENTRY * qglColor3iv )(const GLint *v);
+extern void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+extern void ( APIENTRY * qglColor3sv )(const GLshort *v);
+extern void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+extern void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+extern void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+extern void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+extern void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+extern void ( APIENTRY * qglColor3usv )(const GLushort *v);
+extern void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+extern void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+extern void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+extern void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+extern void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+extern void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+extern void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+extern void ( APIENTRY * qglColor4iv )(const GLint *v);
+extern void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+extern void ( APIENTRY * qglColor4sv )(const GLshort *v);
+extern void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+extern void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+extern void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+extern void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+extern void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+extern void ( APIENTRY * qglColor4usv )(const GLushort *v);
+extern void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+extern void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+extern void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+extern void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+extern void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+extern void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+extern void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+extern void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+extern void ( APIENTRY * qglCullFace )(GLenum mode);
+extern void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+extern void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+extern void ( APIENTRY * qglDepthFunc )(GLenum func);
+extern void ( APIENTRY * qglDepthMask )(GLboolean flag);
+extern void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+extern void ( APIENTRY * qglDisable )(GLenum cap);
+extern void ( APIENTRY * qglDisableClientState )(GLenum array);
+extern void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+extern void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+extern void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+extern void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+extern void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+extern void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+extern void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+extern void ( APIENTRY * qglEnable )(GLenum cap);
+extern void ( APIENTRY * qglEnableClientState )(GLenum array);
+extern void ( APIENTRY * qglEnd )(void);
+extern void ( APIENTRY * qglEndList )(void);
+extern void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+extern void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+extern void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+extern void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+extern void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+extern void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+extern void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+extern void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+extern void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+extern void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+extern void ( APIENTRY * qglEvalPoint1 )(GLint i);
+extern void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+extern void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+extern void ( APIENTRY * qglFinish )(void);
+extern void ( APIENTRY * qglFlush )(void);
+extern void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+extern void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglFrontFace )(GLenum mode);
+extern void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+extern GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+extern void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+extern void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+extern void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+extern void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+extern GLenum ( APIENTRY * qglGetError )(void);
+extern void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+extern void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+extern void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+extern void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+extern void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+extern void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+extern void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+extern void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+extern void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+extern void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+extern void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+extern const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+extern void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+extern void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+extern void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+extern void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+extern void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+extern void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+extern void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+extern void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+extern void ( APIENTRY * qglIndexMask )(GLuint mask);
+extern void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+extern void ( APIENTRY * qglIndexd )(GLdouble c);
+extern void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+extern void ( APIENTRY * qglIndexf )(GLfloat c);
+extern void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+extern void ( APIENTRY * qglIndexi )(GLint c);
+extern void ( APIENTRY * qglIndexiv )(const GLint *c);
+extern void ( APIENTRY * qglIndexs )(GLshort c);
+extern void ( APIENTRY * qglIndexsv )(const GLshort *c);
+extern void ( APIENTRY * qglIndexub )(GLubyte c);
+extern void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+extern void ( APIENTRY * qglInitNames )(void);
+extern void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+extern GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+extern GLboolean ( APIENTRY * qglIsList )(GLuint list);
+extern GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+extern void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+extern void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+extern void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+extern void ( APIENTRY * qglLineWidth )(GLfloat width);
+extern void ( APIENTRY * qglListBase )(GLuint base);
+extern void ( APIENTRY * qglLoadIdentity )(void);
+extern void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+extern void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+extern void ( APIENTRY * qglLoadName )(GLuint name);
+extern void ( APIENTRY * qglLogicOp )(GLenum opcode);
+extern void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+extern void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+extern void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+extern void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+extern void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+extern void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+extern void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+extern void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+extern void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+extern void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglMatrixMode )(GLenum mode);
+extern void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+extern void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+extern void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+extern void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+extern void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+extern void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+extern void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+extern void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+extern void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+extern void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+extern void ( APIENTRY * qglNormal3iv )(const GLint *v);
+extern void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+extern void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+extern void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+extern void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+extern void ( APIENTRY * qglPassThrough )(GLfloat token);
+extern void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+extern void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+extern void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+extern void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+extern void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+extern void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+extern void ( APIENTRY * qglPointSize )(GLfloat size);
+extern void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+extern void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+extern void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+extern void ( APIENTRY * qglPopAttrib )(void);
+extern void ( APIENTRY * qglPopClientAttrib )(void);
+extern void ( APIENTRY * qglPopMatrix )(void);
+extern void ( APIENTRY * qglPopName )(void);
+extern void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+extern void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+extern void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+extern void ( APIENTRY * qglPushMatrix )(void);
+extern void ( APIENTRY * qglPushName )(GLuint name);
+extern void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+extern void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+extern void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+extern void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+extern void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+extern void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+extern void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+extern void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+extern void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+extern void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+extern void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+extern void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+extern void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+extern void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+extern void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+extern void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+extern void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+extern void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+extern void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+extern void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+extern void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+extern void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+extern void ( APIENTRY * qglReadBuffer )(GLenum mode);
+extern void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+extern void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+extern void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+extern void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+extern void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+extern void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+extern void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+extern void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+extern void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+extern GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+extern void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+extern void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+extern void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+extern void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+extern void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+extern void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+extern void ( APIENTRY * qglShadeModel )(GLenum mode);
+extern void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+extern void ( APIENTRY * qglStencilMask )(GLuint mask);
+extern void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+extern void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+extern void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+extern void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+extern void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+extern void ( APIENTRY * qglTexCoord1i )(GLint s);
+extern void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+extern void ( APIENTRY * qglTexCoord1s )(GLshort s);
+extern void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+extern void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+extern void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+extern void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+extern void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+extern void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+extern void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+extern void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+extern void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+extern void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+extern void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+extern void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+extern void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+extern void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+extern void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+extern void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+extern void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+extern void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+extern void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+extern void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+extern void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+extern void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+extern void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+extern void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+extern void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+extern void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+extern void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+extern void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+extern void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+extern void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+extern void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+extern void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+extern void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+extern void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+extern void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+extern void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+extern void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+extern void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+extern void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+extern void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+extern void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+extern void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+extern void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+extern void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+extern void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+extern void ( APIENTRY * qglVertex2iv )(const GLint *v);
+extern void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+extern void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+extern void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+extern void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+extern void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+extern void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+extern void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+extern void ( APIENTRY * qglVertex3iv )(const GLint *v);
+extern void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+extern void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+extern void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+extern void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+extern void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+extern void ( APIENTRY * qglVertex4iv )(const GLint *v);
+extern void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+extern void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+extern void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+extern void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+extern void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+extern void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+extern void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+
+extern void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+extern void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+
+#ifdef _WIN32
+
+extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+extern int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+extern int ( WINAPI * qwglGetPixelFormat)(HDC);
+extern BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+extern BOOL ( WINAPI * qwglSwapBuffers)(HDC);
+
+extern BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
+extern HGLRC ( WINAPI * qwglCreateContext)(HDC);
+extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
+extern BOOL ( WINAPI * qwglDeleteContext)(HGLRC);
+extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
+extern HDC ( WINAPI * qwglGetCurrentDC)(VOID);
+extern PROC ( WINAPI * qwglGetProcAddress)(LPCSTR);
+extern BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
+extern BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
+extern BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
+
+extern BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
+ FLOAT, int, LPGLYPHMETRICSFLOAT);
+
+extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
+ LPLAYERPLANEDESCRIPTOR);
+extern int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
+ CONST COLORREF *);
+extern int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
+ COLORREF *);
+extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
+extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
+
+extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
+
+extern BOOL ( WINAPI * qwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue );
+extern BOOL ( WINAPI * qwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue );
+
+#endif
+
+// glu stuff.. radiant only uses a couple
+extern int (APIENTRY* qgluBuild2DMipmaps) (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, const void *data);
+extern void (APIENTRY* qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+extern void (APIENTRY* qgluLookAt)(
+ GLdouble eyex,
+ GLdouble eyey,
+ GLdouble eyez,
+ GLdouble centerx,
+ GLdouble centery,
+ GLdouble centerz,
+ GLdouble upx,
+ GLdouble upy,
+ GLdouble upz);
+
+
+// end of glu stuff
+
+
+/*
+** extension constants
+*/
+#define GL_POINT_SIZE_MIN_EXT 0x8126
+#define GL_POINT_SIZE_MAX_EXT 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define GL_DISTANCE_ATTENUATION_EXT 0x8129
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+
+#define GL_TEXTURE0_SGIS 0x835E
+#define GL_TEXTURE1_SGIS 0x835F
+
+#endif
diff --git a/q3radiant/QGL_WIN.C b/q3radiant/QGL_WIN.C
new file mode 100755
index 0000000..d2690c6
--- /dev/null
+++ b/q3radiant/QGL_WIN.C
@@ -0,0 +1,1230 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+/*
+** QGL_WIN.C
+**
+** This file implements the operating system binding of GL to QGL function
+** pointers. When doing a port of Quake2 you must implement the following
+** two functions:
+**
+** QGL_Init() - loads libraries, assigns function pointers, etc.
+** QGL_Shutdown() - unloads libraries, NULLs function pointers
+*/
+#include "qgl.h"
+#include <float.h>
+
+HMODULE g_hGLDLL;
+HMODULE g_hGLUDLL;
+
+# pragma warning (disable : 4113 4133 4047 )
+
+int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+int ( WINAPI * qwglGetPixelFormat)(HDC);
+BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+BOOL ( WINAPI * qwglSwapBuffers)(HDC);
+
+BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
+HGLRC ( WINAPI * qwglCreateContext)(HDC);
+HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
+BOOL ( WINAPI * qwglDeleteContext)(HGLRC);
+HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
+HDC ( WINAPI * qwglGetCurrentDC)(VOID);
+PROC ( WINAPI * qwglGetProcAddress)(LPCSTR);
+BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
+BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
+BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
+
+BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
+ FLOAT, int, LPGLYPHMETRICSFLOAT);
+
+BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
+ LPLAYERPLANEDESCRIPTOR);
+int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
+ CONST COLORREF *);
+int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
+ COLORREF *);
+BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
+BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
+
+void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+void ( APIENTRY * qglArrayElement )(GLint i);
+void ( APIENTRY * qglBegin )(GLenum mode);
+void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+void ( APIENTRY * qglCallList )(GLuint list);
+void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+void ( APIENTRY * qglClear )(GLbitfield mask);
+void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void ( APIENTRY * qglClearDepth )(GLclampd depth);
+void ( APIENTRY * qglClearIndex )(GLfloat c);
+void ( APIENTRY * qglClearStencil )(GLint s);
+void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+void ( APIENTRY * qglColor3iv )(const GLint *v);
+void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+void ( APIENTRY * qglColor3sv )(const GLshort *v);
+void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+void ( APIENTRY * qglColor3usv )(const GLushort *v);
+void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+void ( APIENTRY * qglColor4iv )(const GLint *v);
+void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+void ( APIENTRY * qglColor4sv )(const GLshort *v);
+void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+void ( APIENTRY * qglColor4usv )(const GLushort *v);
+void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglCullFace )(GLenum mode);
+void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+void ( APIENTRY * qglDepthFunc )(GLenum func);
+void ( APIENTRY * qglDepthMask )(GLboolean flag);
+void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+void ( APIENTRY * qglDisable )(GLenum cap);
+void ( APIENTRY * qglDisableClientState )(GLenum array);
+void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+void ( APIENTRY * qglEnable )(GLenum cap);
+void ( APIENTRY * qglEnableClientState )(GLenum array);
+void ( APIENTRY * qglEnd )(void);
+void ( APIENTRY * qglEndList )(void);
+void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+void ( APIENTRY * qglEvalPoint1 )(GLint i);
+void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+void ( APIENTRY * qglFinish )(void);
+void ( APIENTRY * qglFlush )(void);
+void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglFrontFace )(GLenum mode);
+void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+GLenum ( APIENTRY * qglGetError )(void);
+void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+void ( APIENTRY * qglIndexMask )(GLuint mask);
+void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglIndexd )(GLdouble c);
+void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+void ( APIENTRY * qglIndexf )(GLfloat c);
+void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+void ( APIENTRY * qglIndexi )(GLint c);
+void ( APIENTRY * qglIndexiv )(const GLint *c);
+void ( APIENTRY * qglIndexs )(GLshort c);
+void ( APIENTRY * qglIndexsv )(const GLshort *c);
+void ( APIENTRY * qglIndexub )(GLubyte c);
+void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+void ( APIENTRY * qglInitNames )(void);
+void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+GLboolean ( APIENTRY * qglIsList )(GLuint list);
+GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+void ( APIENTRY * qglLineWidth )(GLfloat width);
+void ( APIENTRY * qglListBase )(GLuint base);
+void ( APIENTRY * qglLoadIdentity )(void);
+void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglLoadName )(GLuint name);
+void ( APIENTRY * qglLogicOp )(GLenum opcode);
+void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+void ( APIENTRY * qglMatrixMode )(GLenum mode);
+void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+void ( APIENTRY * qglNormal3iv )(const GLint *v);
+void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+void ( APIENTRY * qglPassThrough )(GLfloat token);
+void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+void ( APIENTRY * qglPointSize )(GLfloat size);
+void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+void ( APIENTRY * qglPopAttrib )(void);
+void ( APIENTRY * qglPopClientAttrib )(void);
+void ( APIENTRY * qglPopMatrix )(void);
+void ( APIENTRY * qglPopName )(void);
+void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushMatrix )(void);
+void ( APIENTRY * qglPushName )(GLuint name);
+void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+void ( APIENTRY * qglReadBuffer )(GLenum mode);
+void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+void ( APIENTRY * qglShadeModel )(GLenum mode);
+void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+void ( APIENTRY * qglStencilMask )(GLuint mask);
+void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord1i )(GLint s);
+void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord1s )(GLshort s);
+void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+void ( APIENTRY * qglVertex2iv )(const GLint *v);
+void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglVertex3iv )(const GLint *v);
+void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglVertex4iv )(const GLint *v);
+void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
+BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * );
+BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *, const unsigned char * );
+void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+
+
+// glu stuff
+void (APIENTRY * qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+int (APIENTRY * qgluBuild2DMipmaps) (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type, const void *data);
+// added for plugins
+void (APIENTRY * qgluLookAt)(
+ GLdouble eyex,
+ GLdouble eyey,
+ GLdouble eyez,
+ GLdouble centerx,
+ GLdouble centery,
+ GLdouble centerz,
+ GLdouble upx,
+ GLdouble upy,
+ GLdouble upz);
+
+
+/*
+** QGL_Shutdown
+**
+** Unloads the specified DLL then nulls out all the proc pointers.
+*/
+void QGL_Shutdown()
+{
+ if (g_hGLDLL)
+ {
+ FreeLibrary(g_hGLDLL);
+ g_hGLDLL = NULL;
+ }
+ if (g_hGLUDLL)
+ {
+ FreeLibrary(g_hGLUDLL);
+ g_hGLUDLL = NULL;
+ }
+
+
+ qglAccum = NULL;
+ qglAlphaFunc = NULL;
+ qglAreTexturesResident = NULL;
+ qglArrayElement = NULL;
+ qglBegin = NULL;
+ qglBindTexture = NULL;
+ qglBitmap = NULL;
+ qglBlendFunc = NULL;
+ qglCallList = NULL;
+ qglCallLists = NULL;
+ qglClear = NULL;
+ qglClearAccum = NULL;
+ qglClearColor = NULL;
+ qglClearDepth = NULL;
+ qglClearIndex = NULL;
+ qglClearStencil = NULL;
+ qglClipPlane = NULL;
+ qglColor3b = NULL;
+ qglColor3bv = NULL;
+ qglColor3d = NULL;
+ qglColor3dv = NULL;
+ qglColor3f = NULL;
+ qglColor3fv = NULL;
+ qglColor3i = NULL;
+ qglColor3iv = NULL;
+ qglColor3s = NULL;
+ qglColor3sv = NULL;
+ qglColor3ub = NULL;
+ qglColor3ubv = NULL;
+ qglColor3ui = NULL;
+ qglColor3uiv = NULL;
+ qglColor3us = NULL;
+ qglColor3usv = NULL;
+ qglColor4b = NULL;
+ qglColor4bv = NULL;
+ qglColor4d = NULL;
+ qglColor4dv = NULL;
+ qglColor4f = NULL;
+ qglColor4fv = NULL;
+ qglColor4i = NULL;
+ qglColor4iv = NULL;
+ qglColor4s = NULL;
+ qglColor4sv = NULL;
+ qglColor4ub = NULL;
+ qglColor4ubv = NULL;
+ qglColor4ui = NULL;
+ qglColor4uiv = NULL;
+ qglColor4us = NULL;
+ qglColor4usv = NULL;
+ qglColorMask = NULL;
+ qglColorMaterial = NULL;
+ qglColorPointer = NULL;
+ qglCopyPixels = NULL;
+ qglCopyTexImage1D = NULL;
+ qglCopyTexImage2D = NULL;
+ qglCopyTexSubImage1D = NULL;
+ qglCopyTexSubImage2D = NULL;
+ qglCullFace = NULL;
+ qglDeleteLists = NULL;
+ qglDeleteTextures = NULL;
+ qglDepthFunc = NULL;
+ qglDepthMask = NULL;
+ qglDepthRange = NULL;
+ qglDisable = NULL;
+ qglDisableClientState = NULL;
+ qglDrawArrays = NULL;
+ qglDrawBuffer = NULL;
+ qglDrawElements = NULL;
+ qglDrawPixels = NULL;
+ qglEdgeFlag = NULL;
+ qglEdgeFlagPointer = NULL;
+ qglEdgeFlagv = NULL;
+ qglEnable = NULL;
+ qglEnableClientState = NULL;
+ qglEnd = NULL;
+ qglEndList = NULL;
+ qglEvalCoord1d = NULL;
+ qglEvalCoord1dv = NULL;
+ qglEvalCoord1f = NULL;
+ qglEvalCoord1fv = NULL;
+ qglEvalCoord2d = NULL;
+ qglEvalCoord2dv = NULL;
+ qglEvalCoord2f = NULL;
+ qglEvalCoord2fv = NULL;
+ qglEvalMesh1 = NULL;
+ qglEvalMesh2 = NULL;
+ qglEvalPoint1 = NULL;
+ qglEvalPoint2 = NULL;
+ qglFeedbackBuffer = NULL;
+ qglFinish = NULL;
+ qglFlush = NULL;
+ qglFogf = NULL;
+ qglFogfv = NULL;
+ qglFogi = NULL;
+ qglFogiv = NULL;
+ qglFrontFace = NULL;
+ qglFrustum = NULL;
+ qglGenLists = NULL;
+ qglGenTextures = NULL;
+ qglGetBooleanv = NULL;
+ qglGetClipPlane = NULL;
+ qglGetDoublev = NULL;
+ qglGetError = NULL;
+ qglGetFloatv = NULL;
+ qglGetIntegerv = NULL;
+ qglGetLightfv = NULL;
+ qglGetLightiv = NULL;
+ qglGetMapdv = NULL;
+ qglGetMapfv = NULL;
+ qglGetMapiv = NULL;
+ qglGetMaterialfv = NULL;
+ qglGetMaterialiv = NULL;
+ qglGetPixelMapfv = NULL;
+ qglGetPixelMapuiv = NULL;
+ qglGetPixelMapusv = NULL;
+ qglGetPointerv = NULL;
+ qglGetPolygonStipple = NULL;
+ qglGetString = NULL;
+ qglGetTexEnvfv = NULL;
+ qglGetTexEnviv = NULL;
+ qglGetTexGendv = NULL;
+ qglGetTexGenfv = NULL;
+ qglGetTexGeniv = NULL;
+ qglGetTexImage = NULL;
+ qglGetTexLevelParameterfv = NULL;
+ qglGetTexLevelParameteriv = NULL;
+ qglGetTexParameterfv = NULL;
+ qglGetTexParameteriv = NULL;
+ qglHint = NULL;
+ qglIndexMask = NULL;
+ qglIndexPointer = NULL;
+ qglIndexd = NULL;
+ qglIndexdv = NULL;
+ qglIndexf = NULL;
+ qglIndexfv = NULL;
+ qglIndexi = NULL;
+ qglIndexiv = NULL;
+ qglIndexs = NULL;
+ qglIndexsv = NULL;
+ qglIndexub = NULL;
+ qglIndexubv = NULL;
+ qglInitNames = NULL;
+ qglInterleavedArrays = NULL;
+ qglIsEnabled = NULL;
+ qglIsList = NULL;
+ qglIsTexture = NULL;
+ qglLightModelf = NULL;
+ qglLightModelfv = NULL;
+ qglLightModeli = NULL;
+ qglLightModeliv = NULL;
+ qglLightf = NULL;
+ qglLightfv = NULL;
+ qglLighti = NULL;
+ qglLightiv = NULL;
+ qglLineStipple = NULL;
+ qglLineWidth = NULL;
+ qglListBase = NULL;
+ qglLoadIdentity = NULL;
+ qglLoadMatrixd = NULL;
+ qglLoadMatrixf = NULL;
+ qglLoadName = NULL;
+ qglLogicOp = NULL;
+ qglMap1d = NULL;
+ qglMap1f = NULL;
+ qglMap2d = NULL;
+ qglMap2f = NULL;
+ qglMapGrid1d = NULL;
+ qglMapGrid1f = NULL;
+ qglMapGrid2d = NULL;
+ qglMapGrid2f = NULL;
+ qglMaterialf = NULL;
+ qglMaterialfv = NULL;
+ qglMateriali = NULL;
+ qglMaterialiv = NULL;
+ qglMatrixMode = NULL;
+ qglMultMatrixd = NULL;
+ qglMultMatrixf = NULL;
+ qglNewList = NULL;
+ qglNormal3b = NULL;
+ qglNormal3bv = NULL;
+ qglNormal3d = NULL;
+ qglNormal3dv = NULL;
+ qglNormal3f = NULL;
+ qglNormal3fv = NULL;
+ qglNormal3i = NULL;
+ qglNormal3iv = NULL;
+ qglNormal3s = NULL;
+ qglNormal3sv = NULL;
+ qglNormalPointer = NULL;
+ qglOrtho = NULL;
+ qglPassThrough = NULL;
+ qglPixelMapfv = NULL;
+ qglPixelMapuiv = NULL;
+ qglPixelMapusv = NULL;
+ qglPixelStoref = NULL;
+ qglPixelStorei = NULL;
+ qglPixelTransferf = NULL;
+ qglPixelTransferi = NULL;
+ qglPixelZoom = NULL;
+ qglPointSize = NULL;
+ qglPolygonMode = NULL;
+ qglPolygonOffset = NULL;
+ qglPolygonStipple = NULL;
+ qglPopAttrib = NULL;
+ qglPopClientAttrib = NULL;
+ qglPopMatrix = NULL;
+ qglPopName = NULL;
+ qglPrioritizeTextures = NULL;
+ qglPushAttrib = NULL;
+ qglPushClientAttrib = NULL;
+ qglPushMatrix = NULL;
+ qglPushName = NULL;
+ qglRasterPos2d = NULL;
+ qglRasterPos2dv = NULL;
+ qglRasterPos2f = NULL;
+ qglRasterPos2fv = NULL;
+ qglRasterPos2i = NULL;
+ qglRasterPos2iv = NULL;
+ qglRasterPos2s = NULL;
+ qglRasterPos2sv = NULL;
+ qglRasterPos3d = NULL;
+ qglRasterPos3dv = NULL;
+ qglRasterPos3f = NULL;
+ qglRasterPos3fv = NULL;
+ qglRasterPos3i = NULL;
+ qglRasterPos3iv = NULL;
+ qglRasterPos3s = NULL;
+ qglRasterPos3sv = NULL;
+ qglRasterPos4d = NULL;
+ qglRasterPos4dv = NULL;
+ qglRasterPos4f = NULL;
+ qglRasterPos4fv = NULL;
+ qglRasterPos4i = NULL;
+ qglRasterPos4iv = NULL;
+ qglRasterPos4s = NULL;
+ qglRasterPos4sv = NULL;
+ qglReadBuffer = NULL;
+ qglReadPixels = NULL;
+ qglRectd = NULL;
+ qglRectdv = NULL;
+ qglRectf = NULL;
+ qglRectfv = NULL;
+ qglRecti = NULL;
+ qglRectiv = NULL;
+ qglRects = NULL;
+ qglRectsv = NULL;
+ qglRenderMode = NULL;
+ qglRotated = NULL;
+ qglRotatef = NULL;
+ qglScaled = NULL;
+ qglScalef = NULL;
+ qglScissor = NULL;
+ qglSelectBuffer = NULL;
+ qglShadeModel = NULL;
+ qglStencilFunc = NULL;
+ qglStencilMask = NULL;
+ qglStencilOp = NULL;
+ qglTexCoord1d = NULL;
+ qglTexCoord1dv = NULL;
+ qglTexCoord1f = NULL;
+ qglTexCoord1fv = NULL;
+ qglTexCoord1i = NULL;
+ qglTexCoord1iv = NULL;
+ qglTexCoord1s = NULL;
+ qglTexCoord1sv = NULL;
+ qglTexCoord2d = NULL;
+ qglTexCoord2dv = NULL;
+ qglTexCoord2f = NULL;
+ qglTexCoord2fv = NULL;
+ qglTexCoord2i = NULL;
+ qglTexCoord2iv = NULL;
+ qglTexCoord2s = NULL;
+ qglTexCoord2sv = NULL;
+ qglTexCoord3d = NULL;
+ qglTexCoord3dv = NULL;
+ qglTexCoord3f = NULL;
+ qglTexCoord3fv = NULL;
+ qglTexCoord3i = NULL;
+ qglTexCoord3iv = NULL;
+ qglTexCoord3s = NULL;
+ qglTexCoord3sv = NULL;
+ qglTexCoord4d = NULL;
+ qglTexCoord4dv = NULL;
+ qglTexCoord4f = NULL;
+ qglTexCoord4fv = NULL;
+ qglTexCoord4i = NULL;
+ qglTexCoord4iv = NULL;
+ qglTexCoord4s = NULL;
+ qglTexCoord4sv = NULL;
+ qglTexCoordPointer = NULL;
+ qglTexEnvf = NULL;
+ qglTexEnvfv = NULL;
+ qglTexEnvi = NULL;
+ qglTexEnviv = NULL;
+ qglTexGend = NULL;
+ qglTexGendv = NULL;
+ qglTexGenf = NULL;
+ qglTexGenfv = NULL;
+ qglTexGeni = NULL;
+ qglTexGeniv = NULL;
+ qglTexImage1D = NULL;
+ qglTexImage2D = NULL;
+ qglTexParameterf = NULL;
+ qglTexParameterfv = NULL;
+ qglTexParameteri = NULL;
+ qglTexParameteriv = NULL;
+ qglTexSubImage1D = NULL;
+ qglTexSubImage2D = NULL;
+ qglTranslated = NULL;
+ qglTranslatef = NULL;
+ qglVertex2d = NULL;
+ qglVertex2dv = NULL;
+ qglVertex2f = NULL;
+ qglVertex2fv = NULL;
+ qglVertex2i = NULL;
+ qglVertex2iv = NULL;
+ qglVertex2s = NULL;
+ qglVertex2sv = NULL;
+ qglVertex3d = NULL;
+ qglVertex3dv = NULL;
+ qglVertex3f = NULL;
+ qglVertex3fv = NULL;
+ qglVertex3i = NULL;
+ qglVertex3iv = NULL;
+ qglVertex3s = NULL;
+ qglVertex3sv = NULL;
+ qglVertex4d = NULL;
+ qglVertex4dv = NULL;
+ qglVertex4f = NULL;
+ qglVertex4fv = NULL;
+ qglVertex4i = NULL;
+ qglVertex4iv = NULL;
+ qglVertex4s = NULL;
+ qglVertex4sv = NULL;
+ qglVertexPointer = NULL;
+ qglViewport = NULL;
+
+ qwglCopyContext = NULL;
+ qwglCreateContext = NULL;
+ qwglCreateLayerContext = NULL;
+ qwglDeleteContext = NULL;
+ qwglDescribeLayerPlane = NULL;
+ qwglGetCurrentContext = NULL;
+ qwglGetCurrentDC = NULL;
+ qwglGetLayerPaletteEntries = NULL;
+ qwglGetProcAddress = NULL;
+ qwglMakeCurrent = NULL;
+ qwglRealizeLayerPalette = NULL;
+ qwglSetLayerPaletteEntries = NULL;
+ qwglShareLists = NULL;
+ qwglSwapLayerBuffers = NULL;
+ qwglUseFontBitmaps = NULL;
+ qwglUseFontOutlines = NULL;
+
+ qwglChoosePixelFormat = NULL;
+ qwglDescribePixelFormat = NULL;
+ qwglGetPixelFormat = NULL;
+ qwglSetPixelFormat = NULL;
+ qwglSwapBuffers = NULL;
+
+ qwglSwapIntervalEXT = NULL;
+
+ qwglGetDeviceGammaRampEXT = NULL;
+ qwglSetDeviceGammaRampEXT = NULL;
+
+ qgluPerspective = NULL;
+ qgluBuild2DMipmaps = NULL;
+
+ qgluLookAt = NULL;
+}
+
+# define GPA(h, a ) GetProcAddress( h, a )
+
+/*
+** QGL_Init
+**
+** This is responsible for binding our qgl function pointers to
+** the appropriate GL stuff. In Windows this means doing a
+** LoadLibrary and a bunch of calls to GetProcAddress. On other
+** operating systems we need to do the right thing, whatever that
+** might be.
+**
+*/
+int QGL_Init(const char *dllname, const char* pGluName )
+{
+
+ g_hGLDLL = LoadLibrary(dllname);
+ if (g_hGLDLL == NULL)
+ {
+ return 0;
+ }
+
+ g_hGLUDLL = LoadLibrary(pGluName);
+ if (g_hGLUDLL == NULL)
+ {
+ FreeLibrary(g_hGLDLL);
+ g_hGLDLL = NULL;
+ return 0;
+ }
+
+
+ qgluPerspective = GPA(g_hGLUDLL, "gluPerspective");
+ qgluBuild2DMipmaps = GPA(g_hGLUDLL, "gluBuild2DMipmaps");
+ // added for plugins
+ qgluLookAt = GPA(g_hGLUDLL, "gluLookAt" );
+
+ qglAccum = GPA(g_hGLDLL, "glAccum" );
+ qglAlphaFunc = GPA(g_hGLDLL, "glAlphaFunc" );
+ qglAreTexturesResident = GPA(g_hGLDLL, "glAreTexturesResident" );
+ qglArrayElement = GPA(g_hGLDLL, "glArrayElement" );
+ qglBegin = GPA(g_hGLDLL, "glBegin" );
+ qglBindTexture = GPA(g_hGLDLL, "glBindTexture" );
+ qglBitmap = GPA(g_hGLDLL, "glBitmap" );
+ qglBlendFunc = GPA(g_hGLDLL, "glBlendFunc" );
+ qglCallList = GPA(g_hGLDLL, "glCallList" );
+ qglCallLists = GPA(g_hGLDLL, "glCallLists" );
+ qglClear = GPA(g_hGLDLL, "glClear" );
+ qglClearAccum = GPA(g_hGLDLL, "glClearAccum" );
+ qglClearColor = GPA(g_hGLDLL, "glClearColor" );
+ qglClearDepth = GPA(g_hGLDLL, "glClearDepth" );
+ qglClearIndex = GPA(g_hGLDLL, "glClearIndex" );
+ qglClearStencil = GPA(g_hGLDLL, "glClearStencil" );
+ qglClipPlane = GPA(g_hGLDLL, "glClipPlane" );
+ qglColor3b = GPA(g_hGLDLL, "glColor3b" );
+ qglColor3bv = GPA(g_hGLDLL, "glColor3bv" );
+ qglColor3d = GPA(g_hGLDLL, "glColor3d" );
+ qglColor3dv = GPA(g_hGLDLL, "glColor3dv" );
+ qglColor3f = GPA(g_hGLDLL, "glColor3f" );
+ qglColor3fv = GPA(g_hGLDLL, "glColor3fv" );
+ qglColor3i = GPA(g_hGLDLL, "glColor3i" );
+ qglColor3iv = GPA(g_hGLDLL, "glColor3iv" );
+ qglColor3s = GPA(g_hGLDLL, "glColor3s" );
+ qglColor3sv = GPA(g_hGLDLL, "glColor3sv" );
+ qglColor3ub = GPA(g_hGLDLL, "glColor3ub" );
+ qglColor3ubv = GPA(g_hGLDLL, "glColor3ubv" );
+ qglColor3ui = GPA(g_hGLDLL, "glColor3ui" );
+ qglColor3uiv = GPA(g_hGLDLL, "glColor3uiv" );
+ qglColor3us = GPA(g_hGLDLL, "glColor3us" );
+ qglColor3usv = GPA(g_hGLDLL, "glColor3usv" );
+ qglColor4b = GPA(g_hGLDLL, "glColor4b" );
+ qglColor4bv = GPA(g_hGLDLL, "glColor4bv" );
+ qglColor4d = GPA(g_hGLDLL, "glColor4d" );
+ qglColor4dv = GPA(g_hGLDLL, "glColor4dv" );
+ qglColor4f = GPA(g_hGLDLL, "glColor4f" );
+ qglColor4fv = GPA(g_hGLDLL, "glColor4fv" );
+ qglColor4i = GPA(g_hGLDLL, "glColor4i" );
+ qglColor4iv = GPA(g_hGLDLL, "glColor4iv" );
+ qglColor4s = GPA(g_hGLDLL, "glColor4s" );
+ qglColor4sv = GPA(g_hGLDLL, "glColor4sv" );
+ qglColor4ub = GPA(g_hGLDLL, "glColor4ub" );
+ qglColor4ubv = GPA(g_hGLDLL, "glColor4ubv" );
+ qglColor4ui = GPA(g_hGLDLL, "glColor4ui" );
+ qglColor4uiv = GPA(g_hGLDLL, "glColor4uiv" );
+ qglColor4us = GPA(g_hGLDLL, "glColor4us" );
+ qglColor4usv = GPA(g_hGLDLL, "glColor4usv" );
+ qglColorMask = GPA(g_hGLDLL, "glColorMask" );
+ qglColorMaterial = GPA(g_hGLDLL, "glColorMaterial" );
+ qglColorPointer = GPA(g_hGLDLL, "glColorPointer" );
+ qglCopyPixels = GPA(g_hGLDLL, "glCopyPixels" );
+ qglCopyTexImage1D = GPA(g_hGLDLL, "glCopyTexImage1D" );
+ qglCopyTexImage2D = GPA(g_hGLDLL, "glCopyTexImage2D" );
+ qglCopyTexSubImage1D = GPA(g_hGLDLL, "glCopyTexSubImage1D" );
+ qglCopyTexSubImage2D = GPA(g_hGLDLL, "glCopyTexSubImage2D" );
+ qglCullFace = GPA(g_hGLDLL, "glCullFace" );
+ qglDeleteLists = GPA(g_hGLDLL, "glDeleteLists" );
+ qglDeleteTextures = GPA(g_hGLDLL, "glDeleteTextures" );
+ qglDepthFunc = GPA(g_hGLDLL, "glDepthFunc" );
+ qglDepthMask = GPA(g_hGLDLL, "glDepthMask" );
+ qglDepthRange = GPA(g_hGLDLL, "glDepthRange" );
+ qglDisable = GPA(g_hGLDLL, "glDisable" );
+ qglDisableClientState = GPA(g_hGLDLL, "glDisableClientState" );
+ qglDrawArrays = GPA(g_hGLDLL, "glDrawArrays" );
+ qglDrawBuffer = GPA(g_hGLDLL, "glDrawBuffer" );
+ qglDrawElements = GPA(g_hGLDLL, "glDrawElements" );
+ qglDrawPixels = GPA(g_hGLDLL, "glDrawPixels" );
+ qglEdgeFlag = GPA(g_hGLDLL, "glEdgeFlag" );
+ qglEdgeFlagPointer = GPA(g_hGLDLL, "glEdgeFlagPointer" );
+ qglEdgeFlagv = GPA(g_hGLDLL, "glEdgeFlagv" );
+ qglEnable = GPA(g_hGLDLL, "glEnable" );
+ qglEnableClientState = GPA(g_hGLDLL, "glEnableClientState" );
+ qglEnd = GPA(g_hGLDLL, "glEnd" );
+ qglEndList = GPA(g_hGLDLL, "glEndList" );
+ qglEvalCoord1d = GPA(g_hGLDLL, "glEvalCoord1d" );
+ qglEvalCoord1dv = GPA(g_hGLDLL, "glEvalCoord1dv" );
+ qglEvalCoord1f = GPA(g_hGLDLL, "glEvalCoord1f" );
+ qglEvalCoord1fv = GPA(g_hGLDLL, "glEvalCoord1fv" );
+ qglEvalCoord2d = GPA(g_hGLDLL, "glEvalCoord2d" );
+ qglEvalCoord2dv = GPA(g_hGLDLL, "glEvalCoord2dv" );
+ qglEvalCoord2f = GPA(g_hGLDLL, "glEvalCoord2f" );
+ qglEvalCoord2fv = GPA(g_hGLDLL, "glEvalCoord2fv" );
+ qglEvalMesh1 = GPA(g_hGLDLL, "glEvalMesh1" );
+ qglEvalMesh2 = GPA(g_hGLDLL, "glEvalMesh2" );
+ qglEvalPoint1 = GPA(g_hGLDLL, "glEvalPoint1" );
+ qglEvalPoint2 = GPA(g_hGLDLL, "glEvalPoint2" );
+ qglFeedbackBuffer = GPA(g_hGLDLL, "glFeedbackBuffer" );
+ qglFinish = GPA(g_hGLDLL, "glFinish" );
+ qglFlush = GPA(g_hGLDLL, "glFlush" );
+ qglFogf = GPA(g_hGLDLL, "glFogf" );
+ qglFogfv = GPA(g_hGLDLL, "glFogfv" );
+ qglFogi = GPA(g_hGLDLL, "glFogi" );
+ qglFogiv = GPA(g_hGLDLL, "glFogiv" );
+ qglFrontFace = GPA(g_hGLDLL, "glFrontFace" );
+ qglFrustum = GPA(g_hGLDLL, "glFrustum" );
+ qglGenLists = GPA(g_hGLDLL, "glGenLists" );
+ qglGenTextures = GPA(g_hGLDLL, "glGenTextures" );
+ qglGetBooleanv = GPA(g_hGLDLL, "glGetBooleanv" );
+ qglGetClipPlane = GPA(g_hGLDLL, "glGetClipPlane" );
+ qglGetDoublev = GPA(g_hGLDLL, "glGetDoublev" );
+ qglGetError = GPA(g_hGLDLL, "glGetError" );
+ qglGetFloatv = GPA(g_hGLDLL, "glGetFloatv" );
+ qglGetIntegerv = GPA(g_hGLDLL, "glGetIntegerv" );
+ qglGetLightfv = GPA(g_hGLDLL, "glGetLightfv" );
+ qglGetLightiv = GPA(g_hGLDLL, "glGetLightiv" );
+ qglGetMapdv = GPA(g_hGLDLL, "glGetMapdv" );
+ qglGetMapfv = GPA(g_hGLDLL, "glGetMapfv" );
+ qglGetMapiv = GPA(g_hGLDLL, "glGetMapiv" );
+ qglGetMaterialfv = GPA(g_hGLDLL, "glGetMaterialfv" );
+ qglGetMaterialiv = GPA(g_hGLDLL, "glGetMaterialiv" );
+ qglGetPixelMapfv = GPA(g_hGLDLL, "glGetPixelMapfv" );
+ qglGetPixelMapuiv = GPA(g_hGLDLL, "glGetPixelMapuiv" );
+ qglGetPixelMapusv = GPA(g_hGLDLL, "glGetPixelMapusv" );
+ qglGetPointerv = GPA(g_hGLDLL, "glGetPointerv" );
+ qglGetPolygonStipple = GPA(g_hGLDLL, "glGetPolygonStipple" );
+ qglGetString = GPA(g_hGLDLL, "glGetString" );
+ qglGetTexEnvfv = GPA(g_hGLDLL, "glGetTexEnvfv" );
+ qglGetTexEnviv = GPA(g_hGLDLL, "glGetTexEnviv" );
+ qglGetTexGendv = GPA(g_hGLDLL, "glGetTexGendv" );
+ qglGetTexGenfv = GPA(g_hGLDLL, "glGetTexGenfv" );
+ qglGetTexGeniv = GPA(g_hGLDLL, "glGetTexGeniv" );
+ qglGetTexImage = GPA(g_hGLDLL, "glGetTexImage" );
+ qglGetTexLevelParameterfv = GPA(g_hGLDLL, "glGetLevelParameterfv" );
+ qglGetTexLevelParameteriv = GPA(g_hGLDLL, "glGetLevelParameteriv" );
+ qglGetTexParameterfv = GPA(g_hGLDLL, "glGetTexParameterfv" );
+ qglGetTexParameteriv = GPA(g_hGLDLL, "glGetTexParameteriv" );
+ qglHint = GPA(g_hGLDLL, "glHint" );
+ qglIndexMask = GPA(g_hGLDLL, "glIndexMask" );
+ qglIndexPointer = GPA(g_hGLDLL, "glIndexPointer" );
+ qglIndexd = GPA(g_hGLDLL, "glIndexd" );
+ qglIndexdv = GPA(g_hGLDLL, "glIndexdv" );
+ qglIndexf = GPA(g_hGLDLL, "glIndexf" );
+ qglIndexfv = GPA(g_hGLDLL, "glIndexfv" );
+ qglIndexi = GPA(g_hGLDLL, "glIndexi" );
+ qglIndexiv = GPA(g_hGLDLL, "glIndexiv" );
+ qglIndexs = GPA(g_hGLDLL, "glIndexs" );
+ qglIndexsv = GPA(g_hGLDLL, "glIndexsv" );
+ qglIndexub = GPA(g_hGLDLL, "glIndexub" );
+ qglIndexubv = GPA(g_hGLDLL, "glIndexubv" );
+ qglInitNames = GPA(g_hGLDLL, "glInitNames" );
+ qglInterleavedArrays = GPA(g_hGLDLL, "glInterleavedArrays" );
+ qglIsEnabled = GPA(g_hGLDLL, "glIsEnabled" );
+ qglIsList = GPA(g_hGLDLL, "glIsList" );
+ qglIsTexture = GPA(g_hGLDLL, "glIsTexture" );
+ qglLightModelf = GPA(g_hGLDLL, "glLightModelf" );
+ qglLightModelfv = GPA(g_hGLDLL, "glLightModelfv" );
+ qglLightModeli = GPA(g_hGLDLL, "glLightModeli" );
+ qglLightModeliv = GPA(g_hGLDLL, "glLightModeliv" );
+ qglLightf = GPA(g_hGLDLL, "glLightf" );
+ qglLightfv = GPA(g_hGLDLL, "glLightfv" );
+ qglLighti = GPA(g_hGLDLL, "glLighti" );
+ qglLightiv = GPA(g_hGLDLL, "glLightiv" );
+ qglLineStipple = GPA(g_hGLDLL, "glLineStipple" );
+ qglLineWidth = GPA(g_hGLDLL, "glLineWidth" );
+ qglListBase = GPA(g_hGLDLL, "glListBase" );
+ qglLoadIdentity = GPA(g_hGLDLL, "glLoadIdentity" );
+ qglLoadMatrixd = GPA(g_hGLDLL, "glLoadMatrixd" );
+ qglLoadMatrixf = GPA(g_hGLDLL, "glLoadMatrixf" );
+ qglLoadName = GPA(g_hGLDLL, "glLoadName" );
+ qglLogicOp = GPA(g_hGLDLL, "glLogicOp" );
+ qglMap1d = GPA(g_hGLDLL, "glMap1d" );
+ qglMap1f = GPA(g_hGLDLL, "glMap1f" );
+ qglMap2d = GPA(g_hGLDLL, "glMap2d" );
+ qglMap2f = GPA(g_hGLDLL, "glMap2f" );
+ qglMapGrid1d = GPA(g_hGLDLL, "glMapGrid1d" );
+ qglMapGrid1f = GPA(g_hGLDLL, "glMapGrid1f" );
+ qglMapGrid2d = GPA(g_hGLDLL, "glMapGrid2d" );
+ qglMapGrid2f = GPA(g_hGLDLL, "glMapGrid2f" );
+ qglMaterialf = GPA(g_hGLDLL, "glMaterialf" );
+ qglMaterialfv = GPA(g_hGLDLL, "glMaterialfv" );
+ qglMateriali = GPA(g_hGLDLL, "glMateriali" );
+ qglMaterialiv = GPA(g_hGLDLL, "glMaterialiv" );
+ qglMatrixMode = GPA(g_hGLDLL, "glMatrixMode" );
+ qglMultMatrixd = GPA(g_hGLDLL, "glMultMatrixd" );
+ qglMultMatrixf = GPA(g_hGLDLL, "glMultMatrixf" );
+ qglNewList = GPA(g_hGLDLL, "glNewList" );
+ qglNormal3b = GPA(g_hGLDLL, "glNormal3b" );
+ qglNormal3bv = GPA(g_hGLDLL, "glNormal3bv" );
+ qglNormal3d = GPA(g_hGLDLL, "glNormal3d" );
+ qglNormal3dv = GPA(g_hGLDLL, "glNormal3dv" );
+ qglNormal3f = GPA(g_hGLDLL, "glNormal3f" );
+ qglNormal3fv = GPA(g_hGLDLL, "glNormal3fv" );
+ qglNormal3i = GPA(g_hGLDLL, "glNormal3i" );
+ qglNormal3iv = GPA(g_hGLDLL, "glNormal3iv" );
+ qglNormal3s = GPA(g_hGLDLL, "glNormal3s" );
+ qglNormal3sv = GPA(g_hGLDLL, "glNormal3sv" );
+ qglNormalPointer = GPA(g_hGLDLL, "glNormalPointer" );
+ qglOrtho = GPA(g_hGLDLL, "glOrtho" );
+ qglPassThrough = GPA(g_hGLDLL, "glPassThrough" );
+ qglPixelMapfv = GPA(g_hGLDLL, "glPixelMapfv" );
+ qglPixelMapuiv = GPA(g_hGLDLL, "glPixelMapuiv" );
+ qglPixelMapusv = GPA(g_hGLDLL, "glPixelMapusv" );
+ qglPixelStoref = GPA(g_hGLDLL, "glPixelStoref" );
+ qglPixelStorei = GPA(g_hGLDLL, "glPixelStorei" );
+ qglPixelTransferf = GPA(g_hGLDLL, "glPixelTransferf" );
+ qglPixelTransferi = GPA(g_hGLDLL, "glPixelTransferi" );
+ qglPixelZoom = GPA(g_hGLDLL, "glPixelZoom" );
+ qglPointSize = GPA(g_hGLDLL, "glPointSize" );
+ qglPolygonMode = GPA(g_hGLDLL, "glPolygonMode" );
+ qglPolygonOffset = GPA(g_hGLDLL, "glPolygonOffset" );
+ qglPolygonStipple = GPA(g_hGLDLL, "glPolygonStipple" );
+ qglPopAttrib = GPA(g_hGLDLL, "glPopAttrib" );
+ qglPopClientAttrib = GPA(g_hGLDLL, "glPopClientAttrib" );
+ qglPopMatrix = GPA(g_hGLDLL, "glPopMatrix" );
+ qglPopName = GPA(g_hGLDLL, "glPopName" );
+ qglPrioritizeTextures = GPA(g_hGLDLL, "glPrioritizeTextures" );
+ qglPushAttrib = GPA(g_hGLDLL, "glPushAttrib" );
+ qglPushClientAttrib = GPA(g_hGLDLL, "glPushClientAttrib" );
+ qglPushMatrix = GPA(g_hGLDLL, "glPushMatrix" );
+ qglPushName = GPA(g_hGLDLL, "glPushName" );
+ qglRasterPos2d = GPA(g_hGLDLL, "glRasterPos2d" );
+ qglRasterPos2dv = GPA(g_hGLDLL, "glRasterPos2dv" );
+ qglRasterPos2f = GPA(g_hGLDLL, "glRasterPos2f" );
+ qglRasterPos2fv = GPA(g_hGLDLL, "glRasterPos2fv" );
+ qglRasterPos2i = GPA(g_hGLDLL, "glRasterPos2i" );
+ qglRasterPos2iv = GPA(g_hGLDLL, "glRasterPos2iv" );
+ qglRasterPos2s = GPA(g_hGLDLL, "glRasterPos2s" );
+ qglRasterPos2sv = GPA(g_hGLDLL, "glRasterPos2sv" );
+ qglRasterPos3d = GPA(g_hGLDLL, "glRasterPos3d" );
+ qglRasterPos3dv = GPA(g_hGLDLL, "glRasterPos3dv" );
+ qglRasterPos3f = GPA(g_hGLDLL, "glRasterPos3f" );
+ qglRasterPos3fv = GPA(g_hGLDLL, "glRasterPos3fv" );
+ qglRasterPos3i = GPA(g_hGLDLL, "glRasterPos3i" );
+ qglRasterPos3iv = GPA(g_hGLDLL, "glRasterPos3iv" );
+ qglRasterPos3s = GPA(g_hGLDLL, "glRasterPos3s" );
+ qglRasterPos3sv = GPA(g_hGLDLL, "glRasterPos3sv" );
+ qglRasterPos4d = GPA(g_hGLDLL, "glRasterPos4d" );
+ qglRasterPos4dv = GPA(g_hGLDLL, "glRasterPos4dv" );
+ qglRasterPos4f = GPA(g_hGLDLL, "glRasterPos4f" );
+ qglRasterPos4fv = GPA(g_hGLDLL, "glRasterPos4fv" );
+ qglRasterPos4i = GPA(g_hGLDLL, "glRasterPos4i" );
+ qglRasterPos4iv = GPA(g_hGLDLL, "glRasterPos4iv" );
+ qglRasterPos4s = GPA(g_hGLDLL, "glRasterPos4s" );
+ qglRasterPos4sv = GPA(g_hGLDLL, "glRasterPos4sv" );
+ qglReadBuffer = GPA(g_hGLDLL, "glReadBuffer" );
+ qglReadPixels = GPA(g_hGLDLL, "glReadPixels" );
+ qglRectd = GPA(g_hGLDLL, "glRectd" );
+ qglRectdv = GPA(g_hGLDLL, "glRectdv" );
+ qglRectf = GPA(g_hGLDLL, "glRectf" );
+ qglRectfv = GPA(g_hGLDLL, "glRectfv" );
+ qglRecti = GPA(g_hGLDLL, "glRecti" );
+ qglRectiv = GPA(g_hGLDLL, "glRectiv" );
+ qglRects = GPA(g_hGLDLL, "glRects" );
+ qglRectsv = GPA(g_hGLDLL, "glRectsv" );
+ qglRenderMode = GPA(g_hGLDLL, "glRenderMode" );
+ qglRotated = GPA(g_hGLDLL, "glRotated" );
+ qglRotatef = GPA(g_hGLDLL, "glRotatef" );
+ qglScaled = GPA(g_hGLDLL, "glScaled" );
+ qglScalef = GPA(g_hGLDLL, "glScalef" );
+ qglScissor = GPA(g_hGLDLL, "glScissor" );
+ qglSelectBuffer = GPA(g_hGLDLL, "glSelectBuffer" );
+ qglShadeModel = GPA(g_hGLDLL, "glShadeModel" );
+ qglStencilFunc = GPA(g_hGLDLL, "glStencilFunc" );
+ qglStencilMask = GPA(g_hGLDLL, "glStencilMask" );
+ qglStencilOp = GPA(g_hGLDLL, "glStencilOp" );
+ qglTexCoord1d = GPA(g_hGLDLL, "glTexCoord1d" );
+ qglTexCoord1dv = GPA(g_hGLDLL, "glTexCoord1dv" );
+ qglTexCoord1f = GPA(g_hGLDLL, "glTexCoord1f" );
+ qglTexCoord1fv = GPA(g_hGLDLL, "glTexCoord1fv" );
+ qglTexCoord1i = GPA(g_hGLDLL, "glTexCoord1i" );
+ qglTexCoord1iv = GPA(g_hGLDLL, "glTexCoord1iv" );
+ qglTexCoord1s = GPA(g_hGLDLL, "glTexCoord1s" );
+ qglTexCoord1sv = GPA(g_hGLDLL, "glTexCoord1sv" );
+ qglTexCoord2d = GPA(g_hGLDLL, "glTexCoord2d" );
+ qglTexCoord2dv = GPA(g_hGLDLL, "glTexCoord2dv" );
+ qglTexCoord2f = GPA(g_hGLDLL, "glTexCoord2f" );
+ qglTexCoord2fv = GPA(g_hGLDLL, "glTexCoord2fv" );
+ qglTexCoord2i = GPA(g_hGLDLL, "glTexCoord2i" );
+ qglTexCoord2iv = GPA(g_hGLDLL, "glTexCoord2iv" );
+ qglTexCoord2s = GPA(g_hGLDLL, "glTexCoord2s" );
+ qglTexCoord2sv = GPA(g_hGLDLL, "glTexCoord2sv" );
+ qglTexCoord3d = GPA(g_hGLDLL, "glTexCoord3d" );
+ qglTexCoord3dv = GPA(g_hGLDLL, "glTexCoord3dv" );
+ qglTexCoord3f = GPA(g_hGLDLL, "glTexCoord3f" );
+ qglTexCoord3fv = GPA(g_hGLDLL, "glTexCoord3fv" );
+ qglTexCoord3i = GPA(g_hGLDLL, "glTexCoord3i" );
+ qglTexCoord3iv = GPA(g_hGLDLL, "glTexCoord3iv" );
+ qglTexCoord3s = GPA(g_hGLDLL, "glTexCoord3s" );
+ qglTexCoord3sv = GPA(g_hGLDLL, "glTexCoord3sv" );
+ qglTexCoord4d = GPA(g_hGLDLL, "glTexCoord4d" );
+ qglTexCoord4dv = GPA(g_hGLDLL, "glTexCoord4dv" );
+ qglTexCoord4f = GPA(g_hGLDLL, "glTexCoord4f" );
+ qglTexCoord4fv = GPA(g_hGLDLL, "glTexCoord4fv" );
+ qglTexCoord4i = GPA(g_hGLDLL, "glTexCoord4i" );
+ qglTexCoord4iv = GPA(g_hGLDLL, "glTexCoord4iv" );
+ qglTexCoord4s = GPA(g_hGLDLL, "glTexCoord4s" );
+ qglTexCoord4sv = GPA(g_hGLDLL, "glTexCoord4sv" );
+ qglTexCoordPointer = GPA(g_hGLDLL, "glTexCoordPointer" );
+ qglTexEnvf = GPA(g_hGLDLL, "glTexEnvf" );
+ qglTexEnvfv = GPA(g_hGLDLL, "glTexEnvfv" );
+ qglTexEnvi = GPA(g_hGLDLL, "glTexEnvi" );
+ qglTexEnviv = GPA(g_hGLDLL, "glTexEnviv" );
+ qglTexGend = GPA(g_hGLDLL, "glTexGend" );
+ qglTexGendv = GPA(g_hGLDLL, "glTexGendv" );
+ qglTexGenf = GPA(g_hGLDLL, "glTexGenf" );
+ qglTexGenfv = GPA(g_hGLDLL, "glTexGenfv" );
+ qglTexGeni = GPA(g_hGLDLL, "glTexGeni" );
+ qglTexGeniv = GPA(g_hGLDLL, "glTexGeniv" );
+ qglTexImage1D = GPA(g_hGLDLL, "glTexImage1D" );
+ qglTexImage2D = GPA(g_hGLDLL, "glTexImage2D" );
+ qglTexParameterf = GPA(g_hGLDLL, "glTexParameterf" );
+ qglTexParameterfv = GPA(g_hGLDLL, "glTexParameterfv" );
+ qglTexParameteri = GPA(g_hGLDLL, "glTexParameteri" );
+ qglTexParameteriv = GPA(g_hGLDLL, "glTexParameteriv" );
+ qglTexSubImage1D = GPA(g_hGLDLL, "glTexSubImage1D" );
+ qglTexSubImage2D = GPA(g_hGLDLL, "glTexSubImage2D" );
+ qglTranslated = GPA(g_hGLDLL, "glTranslated" );
+ qglTranslatef = GPA(g_hGLDLL, "glTranslatef" );
+ qglVertex2d = GPA(g_hGLDLL, "glVertex2d" );
+ qglVertex2dv = GPA(g_hGLDLL, "glVertex2dv" );
+ qglVertex2f = GPA(g_hGLDLL, "glVertex2f" );
+ qglVertex2fv = GPA(g_hGLDLL, "glVertex2fv" );
+ qglVertex2i = GPA(g_hGLDLL, "glVertex2i" );
+ qglVertex2iv = GPA(g_hGLDLL, "glVertex2iv" );
+ qglVertex2s = GPA(g_hGLDLL, "glVertex2s" );
+ qglVertex2sv = GPA(g_hGLDLL, "glVertex2sv" );
+ qglVertex3d = GPA(g_hGLDLL, "glVertex3d" );
+ qglVertex3dv = GPA(g_hGLDLL, "glVertex3dv" );
+ qglVertex3f = GPA(g_hGLDLL, "glVertex3f" );
+ qglVertex3fv = GPA(g_hGLDLL, "glVertex3fv" );
+ qglVertex3i = GPA(g_hGLDLL, "glVertex3i" );
+ qglVertex3iv = GPA(g_hGLDLL, "glVertex3iv" );
+ qglVertex3s = GPA(g_hGLDLL, "glVertex3s" );
+ qglVertex3sv = GPA(g_hGLDLL, "glVertex3sv" );
+ qglVertex4d = GPA(g_hGLDLL, "glVertex4d" );
+ qglVertex4dv = GPA(g_hGLDLL, "glVertex4dv" );
+ qglVertex4f = GPA(g_hGLDLL, "glVertex4f" );
+ qglVertex4fv = GPA(g_hGLDLL, "glVertex4fv" );
+ qglVertex4i = GPA(g_hGLDLL, "glVertex4i" );
+ qglVertex4iv = GPA(g_hGLDLL, "glVertex4iv" );
+ qglVertex4s = GPA(g_hGLDLL, "glVertex4s" );
+ qglVertex4sv = GPA(g_hGLDLL, "glVertex4sv" );
+ qglVertexPointer = GPA(g_hGLDLL, "glVertexPointer" );
+ qglViewport = GPA(g_hGLDLL, "glViewport" );
+
+ qwglCopyContext = GPA(g_hGLDLL, "wglCopyContext" );
+ qwglCreateContext = GPA(g_hGLDLL, "wglCreateContext" );
+ qwglCreateLayerContext = GPA(g_hGLDLL, "wglCreateLayerContext" );
+ qwglDeleteContext = GPA(g_hGLDLL, "wglDeleteContext" );
+ qwglDescribeLayerPlane = GPA(g_hGLDLL, "wglDescribeLayerPlane" );
+ qwglGetCurrentContext = GPA(g_hGLDLL, "wglGetCurrentContext" );
+ qwglGetCurrentDC = GPA(g_hGLDLL, "wglGetCurrentDC" );
+ qwglGetLayerPaletteEntries = GPA(g_hGLDLL, "wglGetLayerPaletteEntries" );
+ qwglGetProcAddress = GPA(g_hGLDLL, "wglGetProcAddress" );
+ qwglMakeCurrent = GPA(g_hGLDLL, "wglMakeCurrent" );
+ qwglRealizeLayerPalette = GPA(g_hGLDLL, "wglRealizeLayerPalette" );
+ qwglSetLayerPaletteEntries = GPA(g_hGLDLL, "wglSetLayerPaletteEntries" );
+ qwglShareLists = GPA(g_hGLDLL, "wglShareLists" );
+ qwglSwapLayerBuffers = GPA(g_hGLDLL, "wglSwapLayerBuffers" );
+ qwglUseFontBitmaps = GPA(g_hGLDLL, "wglUseFontBitmapsA" );
+ qwglUseFontOutlines = GPA(g_hGLDLL, "wglUseFontOutlinesA" );
+
+ qwglChoosePixelFormat = GPA(g_hGLDLL, "wglChoosePixelFormat" );
+ qwglDescribePixelFormat = GPA(g_hGLDLL, "wglDescribePixelFormat" );
+ qwglGetPixelFormat = GPA(g_hGLDLL, "wglGetPixelFormat" );
+ qwglSetPixelFormat = GPA(g_hGLDLL, "wglSetPixelFormat" );
+ qwglSwapBuffers = GPA(g_hGLDLL, "wglSwapBuffers" );
+
+ qwglSwapIntervalEXT = 0;
+ qglPointParameterfEXT = 0;
+ qglPointParameterfvEXT = 0;
+ qglColorTableEXT = 0;
+ qglSelectTextureSGIS = 0;
+ qglMTexCoord2fSGIS = 0;
+
+ return 1;
+}
+
+#pragma warning (default : 4113 4133 4047 )
+
+
+
diff --git a/q3radiant/QGL_WIN.CPP b/q3radiant/QGL_WIN.CPP
new file mode 100755
index 0000000..dfb7687
--- /dev/null
+++ b/q3radiant/QGL_WIN.CPP
@@ -0,0 +1,1520 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+/*
+** QGL_WIN.C
+**
+** This file implements the operating system binding of GL to QGL function
+** pointers. When doing a port of Quake2 you must implement the following
+** two functions:
+**
+** QGL_Init() - loads libraries, assigns function pointers, etc.
+** QGL_Shutdown() - unloads libraries, NULLs function pointers
+*/
+#include "stdafx.h"
+#include <float.h>
+
+HMODULE g_hGLDLL = NULL;
+
+# pragma warning (disable : 4113 4133 4047 )
+
+int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+int ( WINAPI * qwglGetPixelFormat)(HDC);
+BOOL ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+BOOL ( WINAPI * qwglSwapBuffers)(HDC);
+
+BOOL ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
+HGLRC ( WINAPI * qwglCreateContext)(HDC);
+HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
+BOOL ( WINAPI * qwglDeleteContext)(HGLRC);
+HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
+HDC ( WINAPI * qwglGetCurrentDC)(VOID);
+PROC ( WINAPI * qwglGetProcAddress)(LPCSTR);
+BOOL ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
+BOOL ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
+BOOL ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
+
+BOOL ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
+ FLOAT, int, LPGLYPHMETRICSFLOAT);
+
+BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
+ LPLAYERPLANEDESCRIPTOR);
+int ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
+ CONST COLORREF *);
+int ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
+ COLORREF *);
+BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
+BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
+
+void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+void ( APIENTRY * qglArrayElement )(GLint i);
+void ( APIENTRY * qglBegin )(GLenum mode);
+void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+void ( APIENTRY * qglCallList )(GLuint list);
+void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+void ( APIENTRY * qglClear )(GLbitfield mask);
+void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void ( APIENTRY * qglClearDepth )(GLclampd depth);
+void ( APIENTRY * qglClearIndex )(GLfloat c);
+void ( APIENTRY * qglClearStencil )(GLint s);
+void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+void ( APIENTRY * qglColor3iv )(const GLint *v);
+void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+void ( APIENTRY * qglColor3sv )(const GLshort *v);
+void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+void ( APIENTRY * qglColor3usv )(const GLushort *v);
+void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+void ( APIENTRY * qglColor4iv )(const GLint *v);
+void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+void ( APIENTRY * qglColor4sv )(const GLshort *v);
+void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+void ( APIENTRY * qglColor4usv )(const GLushort *v);
+void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglCullFace )(GLenum mode);
+void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+void ( APIENTRY * qglDepthFunc )(GLenum func);
+void ( APIENTRY * qglDepthMask )(GLboolean flag);
+void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+void ( APIENTRY * qglDisable )(GLenum cap);
+void ( APIENTRY * qglDisableClientState )(GLenum array);
+void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+void ( APIENTRY * qglEnable )(GLenum cap);
+void ( APIENTRY * qglEnableClientState )(GLenum array);
+void ( APIENTRY * qglEnd )(void);
+void ( APIENTRY * qglEndList )(void);
+void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+void ( APIENTRY * qglEvalPoint1 )(GLint i);
+void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+void ( APIENTRY * qglFinish )(void);
+void ( APIENTRY * qglFlush )(void);
+void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglFrontFace )(GLenum mode);
+void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+GLenum ( APIENTRY * qglGetError )(void);
+void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+void ( APIENTRY * qglIndexMask )(GLuint mask);
+void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglIndexd )(GLdouble c);
+void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+void ( APIENTRY * qglIndexf )(GLfloat c);
+void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+void ( APIENTRY * qglIndexi )(GLint c);
+void ( APIENTRY * qglIndexiv )(const GLint *c);
+void ( APIENTRY * qglIndexs )(GLshort c);
+void ( APIENTRY * qglIndexsv )(const GLshort *c);
+void ( APIENTRY * qglIndexub )(GLubyte c);
+void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+void ( APIENTRY * qglInitNames )(void);
+void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+GLboolean ( APIENTRY * qglIsList )(GLuint list);
+GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+void ( APIENTRY * qglLineWidth )(GLfloat width);
+void ( APIENTRY * qglListBase )(GLuint base);
+void ( APIENTRY * qglLoadIdentity )(void);
+void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglLoadName )(GLuint name);
+void ( APIENTRY * qglLogicOp )(GLenum opcode);
+void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+void ( APIENTRY * qglMatrixMode )(GLenum mode);
+void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+void ( APIENTRY * qglNormal3iv )(const GLint *v);
+void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+void ( APIENTRY * qglPassThrough )(GLfloat token);
+void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+void ( APIENTRY * qglPointSize )(GLfloat size);
+void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+void ( APIENTRY * qglPopAttrib )(void);
+void ( APIENTRY * qglPopClientAttrib )(void);
+void ( APIENTRY * qglPopMatrix )(void);
+void ( APIENTRY * qglPopName )(void);
+void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushMatrix )(void);
+void ( APIENTRY * qglPushName )(GLuint name);
+void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+void ( APIENTRY * qglReadBuffer )(GLenum mode);
+void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+void ( APIENTRY * qglShadeModel )(GLenum mode);
+void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+void ( APIENTRY * qglStencilMask )(GLuint mask);
+void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord1i )(GLint s);
+void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord1s )(GLshort s);
+void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+void ( APIENTRY * qglVertex2iv )(const GLint *v);
+void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglVertex3iv )(const GLint *v);
+void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglVertex4iv )(const GLint *v);
+void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
+BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * );
+BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *, const unsigned char * );
+void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+
+static void ( APIENTRY * dllAccum )(GLenum op, GLfloat value);
+static void ( APIENTRY * dllAlphaFunc )(GLenum func, GLclampf ref);
+GLboolean ( APIENTRY * dllAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+static void ( APIENTRY * dllArrayElement )(GLint i);
+static void ( APIENTRY * dllBegin )(GLenum mode);
+static void ( APIENTRY * dllBindTexture )(GLenum target, GLuint texture);
+static void ( APIENTRY * dllBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+static void ( APIENTRY * dllBlendFunc )(GLenum sfactor, GLenum dfactor);
+static void ( APIENTRY * dllCallList )(GLuint list);
+static void ( APIENTRY * dllCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+static void ( APIENTRY * dllClear )(GLbitfield mask);
+static void ( APIENTRY * dllClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+static void ( APIENTRY * dllClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+static void ( APIENTRY * dllClearDepth )(GLclampd depth);
+static void ( APIENTRY * dllClearIndex )(GLfloat c);
+static void ( APIENTRY * dllClearStencil )(GLint s);
+static void ( APIENTRY * dllClipPlane )(GLenum plane, const GLdouble *equation);
+static void ( APIENTRY * dllColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+static void ( APIENTRY * dllColor3bv )(const GLbyte *v);
+static void ( APIENTRY * dllColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+static void ( APIENTRY * dllColor3dv )(const GLdouble *v);
+static void ( APIENTRY * dllColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+static void ( APIENTRY * dllColor3fv )(const GLfloat *v);
+static void ( APIENTRY * dllColor3i )(GLint red, GLint green, GLint blue);
+static void ( APIENTRY * dllColor3iv )(const GLint *v);
+static void ( APIENTRY * dllColor3s )(GLshort red, GLshort green, GLshort blue);
+static void ( APIENTRY * dllColor3sv )(const GLshort *v);
+static void ( APIENTRY * dllColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+static void ( APIENTRY * dllColor3ubv )(const GLubyte *v);
+static void ( APIENTRY * dllColor3ui )(GLuint red, GLuint green, GLuint blue);
+static void ( APIENTRY * dllColor3uiv )(const GLuint *v);
+static void ( APIENTRY * dllColor3us )(GLushort red, GLushort green, GLushort blue);
+static void ( APIENTRY * dllColor3usv )(const GLushort *v);
+static void ( APIENTRY * dllColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+static void ( APIENTRY * dllColor4bv )(const GLbyte *v);
+static void ( APIENTRY * dllColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+static void ( APIENTRY * dllColor4dv )(const GLdouble *v);
+static void ( APIENTRY * dllColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+static void ( APIENTRY * dllColor4fv )(const GLfloat *v);
+static void ( APIENTRY * dllColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+static void ( APIENTRY * dllColor4iv )(const GLint *v);
+static void ( APIENTRY * dllColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+static void ( APIENTRY * dllColor4sv )(const GLshort *v);
+static void ( APIENTRY * dllColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+static void ( APIENTRY * dllColor4ubv )(const GLubyte *v);
+static void ( APIENTRY * dllColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+static void ( APIENTRY * dllColor4uiv )(const GLuint *v);
+static void ( APIENTRY * dllColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+static void ( APIENTRY * dllColor4usv )(const GLushort *v);
+static void ( APIENTRY * dllColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+static void ( APIENTRY * dllColorMaterial )(GLenum face, GLenum mode);
+static void ( APIENTRY * dllColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+static void ( APIENTRY * dllCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+static void ( APIENTRY * dllCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+static void ( APIENTRY * dllCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+static void ( APIENTRY * dllCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+static void ( APIENTRY * dllCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+static void ( APIENTRY * dllCullFace )(GLenum mode);
+static void ( APIENTRY * dllDeleteLists )(GLuint list, GLsizei range);
+static void ( APIENTRY * dllDeleteTextures )(GLsizei n, const GLuint *textures);
+static void ( APIENTRY * dllDepthFunc )(GLenum func);
+static void ( APIENTRY * dllDepthMask )(GLboolean flag);
+static void ( APIENTRY * dllDepthRange )(GLclampd zNear, GLclampd zFar);
+static void ( APIENTRY * dllDisable )(GLenum cap);
+static void ( APIENTRY * dllDisableClientState )(GLenum array);
+static void ( APIENTRY * dllDrawArrays )(GLenum mode, GLint first, GLsizei count);
+static void ( APIENTRY * dllDrawBuffer )(GLenum mode);
+static void ( APIENTRY * dllDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+static void ( APIENTRY * dllDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+static void ( APIENTRY * dllEdgeFlag )(GLboolean flag);
+static void ( APIENTRY * dllEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+static void ( APIENTRY * dllEdgeFlagv )(const GLboolean *flag);
+static void ( APIENTRY * dllEnable )(GLenum cap);
+static void ( APIENTRY * dllEnableClientState )(GLenum array);
+static void ( APIENTRY * dllEnd )(void);
+static void ( APIENTRY * dllEndList )(void);
+static void ( APIENTRY * dllEvalCoord1d )(GLdouble u);
+static void ( APIENTRY * dllEvalCoord1dv )(const GLdouble *u);
+static void ( APIENTRY * dllEvalCoord1f )(GLfloat u);
+static void ( APIENTRY * dllEvalCoord1fv )(const GLfloat *u);
+static void ( APIENTRY * dllEvalCoord2d )(GLdouble u, GLdouble v);
+static void ( APIENTRY * dllEvalCoord2dv )(const GLdouble *u);
+static void ( APIENTRY * dllEvalCoord2f )(GLfloat u, GLfloat v);
+static void ( APIENTRY * dllEvalCoord2fv )(const GLfloat *u);
+static void ( APIENTRY * dllEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+static void ( APIENTRY * dllEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+static void ( APIENTRY * dllEvalPoint1 )(GLint i);
+static void ( APIENTRY * dllEvalPoint2 )(GLint i, GLint j);
+static void ( APIENTRY * dllFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+static void ( APIENTRY * dllFinish )(void);
+static void ( APIENTRY * dllFlush )(void);
+static void ( APIENTRY * dllFogf )(GLenum pname, GLfloat param);
+static void ( APIENTRY * dllFogfv )(GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllFogi )(GLenum pname, GLint param);
+static void ( APIENTRY * dllFogiv )(GLenum pname, const GLint *params);
+static void ( APIENTRY * dllFrontFace )(GLenum mode);
+static void ( APIENTRY * dllFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLuint ( APIENTRY * dllGenLists )(GLsizei range);
+static void ( APIENTRY * dllGenTextures )(GLsizei n, GLuint *textures);
+static void ( APIENTRY * dllGetBooleanv )(GLenum pname, GLboolean *params);
+static void ( APIENTRY * dllGetClipPlane )(GLenum plane, GLdouble *equation);
+static void ( APIENTRY * dllGetDoublev )(GLenum pname, GLdouble *params);
+GLenum ( APIENTRY * dllGetError )(void);
+static void ( APIENTRY * dllGetFloatv )(GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetIntegerv )(GLenum pname, GLint *params);
+static void ( APIENTRY * dllGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetLightiv )(GLenum light, GLenum pname, GLint *params);
+static void ( APIENTRY * dllGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+static void ( APIENTRY * dllGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+static void ( APIENTRY * dllGetMapiv )(GLenum target, GLenum query, GLint *v);
+static void ( APIENTRY * dllGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+static void ( APIENTRY * dllGetPixelMapfv )(GLenum map, GLfloat *values);
+static void ( APIENTRY * dllGetPixelMapuiv )(GLenum map, GLuint *values);
+static void ( APIENTRY * dllGetPixelMapusv )(GLenum map, GLushort *values);
+static void ( APIENTRY * dllGetPointerv )(GLenum pname, GLvoid* *params);
+static void ( APIENTRY * dllGetPolygonStipple )(GLubyte *mask);
+const GLubyte * ( APIENTRY * dllGetString )(GLenum name);
+static void ( APIENTRY * dllGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+static void ( APIENTRY * dllGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+static void ( APIENTRY * dllGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+static void ( APIENTRY * dllGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+static void ( APIENTRY * dllGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+static void ( APIENTRY * dllGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+static void ( APIENTRY * dllGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+static void ( APIENTRY * dllHint )(GLenum target, GLenum mode);
+static void ( APIENTRY * dllIndexMask )(GLuint mask);
+static void ( APIENTRY * dllIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+static void ( APIENTRY * dllIndexd )(GLdouble c);
+static void ( APIENTRY * dllIndexdv )(const GLdouble *c);
+static void ( APIENTRY * dllIndexf )(GLfloat c);
+static void ( APIENTRY * dllIndexfv )(const GLfloat *c);
+static void ( APIENTRY * dllIndexi )(GLint c);
+static void ( APIENTRY * dllIndexiv )(const GLint *c);
+static void ( APIENTRY * dllIndexs )(GLshort c);
+static void ( APIENTRY * dllIndexsv )(const GLshort *c);
+static void ( APIENTRY * dllIndexub )(GLubyte c);
+static void ( APIENTRY * dllIndexubv )(const GLubyte *c);
+static void ( APIENTRY * dllInitNames )(void);
+static void ( APIENTRY * dllInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+GLboolean ( APIENTRY * dllIsEnabled )(GLenum cap);
+GLboolean ( APIENTRY * dllIsList )(GLuint list);
+GLboolean ( APIENTRY * dllIsTexture )(GLuint texture);
+static void ( APIENTRY * dllLightModelf )(GLenum pname, GLfloat param);
+static void ( APIENTRY * dllLightModelfv )(GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllLightModeli )(GLenum pname, GLint param);
+static void ( APIENTRY * dllLightModeliv )(GLenum pname, const GLint *params);
+static void ( APIENTRY * dllLightf )(GLenum light, GLenum pname, GLfloat param);
+static void ( APIENTRY * dllLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllLighti )(GLenum light, GLenum pname, GLint param);
+static void ( APIENTRY * dllLightiv )(GLenum light, GLenum pname, const GLint *params);
+static void ( APIENTRY * dllLineStipple )(GLint factor, GLushort pattern);
+static void ( APIENTRY * dllLineWidth )(GLfloat width);
+static void ( APIENTRY * dllListBase )(GLuint base);
+static void ( APIENTRY * dllLoadIdentity )(void);
+static void ( APIENTRY * dllLoadMatrixd )(const GLdouble *m);
+static void ( APIENTRY * dllLoadMatrixf )(const GLfloat *m);
+static void ( APIENTRY * dllLoadName )(GLuint name);
+static void ( APIENTRY * dllLogicOp )(GLenum opcode);
+static void ( APIENTRY * dllMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+static void ( APIENTRY * dllMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+static void ( APIENTRY * dllMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+static void ( APIENTRY * dllMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+static void ( APIENTRY * dllMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+static void ( APIENTRY * dllMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+static void ( APIENTRY * dllMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+static void ( APIENTRY * dllMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+static void ( APIENTRY * dllMaterialf )(GLenum face, GLenum pname, GLfloat param);
+static void ( APIENTRY * dllMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllMateriali )(GLenum face, GLenum pname, GLint param);
+static void ( APIENTRY * dllMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+static void ( APIENTRY * dllMatrixMode )(GLenum mode);
+static void ( APIENTRY * dllMultMatrixd )(const GLdouble *m);
+static void ( APIENTRY * dllMultMatrixf )(const GLfloat *m);
+static void ( APIENTRY * dllNewList )(GLuint list, GLenum mode);
+static void ( APIENTRY * dllNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+static void ( APIENTRY * dllNormal3bv )(const GLbyte *v);
+static void ( APIENTRY * dllNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+static void ( APIENTRY * dllNormal3dv )(const GLdouble *v);
+static void ( APIENTRY * dllNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+static void ( APIENTRY * dllNormal3fv )(const GLfloat *v);
+static void ( APIENTRY * dllNormal3i )(GLint nx, GLint ny, GLint nz);
+static void ( APIENTRY * dllNormal3iv )(const GLint *v);
+static void ( APIENTRY * dllNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+static void ( APIENTRY * dllNormal3sv )(const GLshort *v);
+static void ( APIENTRY * dllNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+static void ( APIENTRY * dllOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+static void ( APIENTRY * dllPassThrough )(GLfloat token);
+static void ( APIENTRY * dllPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+static void ( APIENTRY * dllPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+static void ( APIENTRY * dllPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+static void ( APIENTRY * dllPixelStoref )(GLenum pname, GLfloat param);
+static void ( APIENTRY * dllPixelStorei )(GLenum pname, GLint param);
+static void ( APIENTRY * dllPixelTransferf )(GLenum pname, GLfloat param);
+static void ( APIENTRY * dllPixelTransferi )(GLenum pname, GLint param);
+static void ( APIENTRY * dllPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+static void ( APIENTRY * dllPointSize )(GLfloat size);
+static void ( APIENTRY * dllPolygonMode )(GLenum face, GLenum mode);
+static void ( APIENTRY * dllPolygonOffset )(GLfloat factor, GLfloat units);
+static void ( APIENTRY * dllPolygonStipple )(const GLubyte *mask);
+static void ( APIENTRY * dllPopAttrib )(void);
+static void ( APIENTRY * dllPopClientAttrib )(void);
+static void ( APIENTRY * dllPopMatrix )(void);
+static void ( APIENTRY * dllPopName )(void);
+static void ( APIENTRY * dllPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+static void ( APIENTRY * dllPushAttrib )(GLbitfield mask);
+static void ( APIENTRY * dllPushClientAttrib )(GLbitfield mask);
+static void ( APIENTRY * dllPushMatrix )(void);
+static void ( APIENTRY * dllPushName )(GLuint name);
+static void ( APIENTRY * dllRasterPos2d )(GLdouble x, GLdouble y);
+static void ( APIENTRY * dllRasterPos2dv )(const GLdouble *v);
+static void ( APIENTRY * dllRasterPos2f )(GLfloat x, GLfloat y);
+static void ( APIENTRY * dllRasterPos2fv )(const GLfloat *v);
+static void ( APIENTRY * dllRasterPos2i )(GLint x, GLint y);
+static void ( APIENTRY * dllRasterPos2iv )(const GLint *v);
+static void ( APIENTRY * dllRasterPos2s )(GLshort x, GLshort y);
+static void ( APIENTRY * dllRasterPos2sv )(const GLshort *v);
+static void ( APIENTRY * dllRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+static void ( APIENTRY * dllRasterPos3dv )(const GLdouble *v);
+static void ( APIENTRY * dllRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+static void ( APIENTRY * dllRasterPos3fv )(const GLfloat *v);
+static void ( APIENTRY * dllRasterPos3i )(GLint x, GLint y, GLint z);
+static void ( APIENTRY * dllRasterPos3iv )(const GLint *v);
+static void ( APIENTRY * dllRasterPos3s )(GLshort x, GLshort y, GLshort z);
+static void ( APIENTRY * dllRasterPos3sv )(const GLshort *v);
+static void ( APIENTRY * dllRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+static void ( APIENTRY * dllRasterPos4dv )(const GLdouble *v);
+static void ( APIENTRY * dllRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+static void ( APIENTRY * dllRasterPos4fv )(const GLfloat *v);
+static void ( APIENTRY * dllRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+static void ( APIENTRY * dllRasterPos4iv )(const GLint *v);
+static void ( APIENTRY * dllRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+static void ( APIENTRY * dllRasterPos4sv )(const GLshort *v);
+static void ( APIENTRY * dllReadBuffer )(GLenum mode);
+static void ( APIENTRY * dllReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+static void ( APIENTRY * dllRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+static void ( APIENTRY * dllRectdv )(const GLdouble *v1, const GLdouble *v2);
+static void ( APIENTRY * dllRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+static void ( APIENTRY * dllRectfv )(const GLfloat *v1, const GLfloat *v2);
+static void ( APIENTRY * dllRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+static void ( APIENTRY * dllRectiv )(const GLint *v1, const GLint *v2);
+static void ( APIENTRY * dllRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+static void ( APIENTRY * dllRectsv )(const GLshort *v1, const GLshort *v2);
+GLint ( APIENTRY * dllRenderMode )(GLenum mode);
+static void ( APIENTRY * dllRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+static void ( APIENTRY * dllRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+static void ( APIENTRY * dllScaled )(GLdouble x, GLdouble y, GLdouble z);
+static void ( APIENTRY * dllScalef )(GLfloat x, GLfloat y, GLfloat z);
+static void ( APIENTRY * dllScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+static void ( APIENTRY * dllSelectBuffer )(GLsizei size, GLuint *buffer);
+static void ( APIENTRY * dllShadeModel )(GLenum mode);
+static void ( APIENTRY * dllStencilFunc )(GLenum func, GLint ref, GLuint mask);
+static void ( APIENTRY * dllStencilMask )(GLuint mask);
+static void ( APIENTRY * dllStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+static void ( APIENTRY * dllTexCoord1d )(GLdouble s);
+static void ( APIENTRY * dllTexCoord1dv )(const GLdouble *v);
+static void ( APIENTRY * dllTexCoord1f )(GLfloat s);
+static void ( APIENTRY * dllTexCoord1fv )(const GLfloat *v);
+static void ( APIENTRY * dllTexCoord1i )(GLint s);
+static void ( APIENTRY * dllTexCoord1iv )(const GLint *v);
+static void ( APIENTRY * dllTexCoord1s )(GLshort s);
+static void ( APIENTRY * dllTexCoord1sv )(const GLshort *v);
+static void ( APIENTRY * dllTexCoord2d )(GLdouble s, GLdouble t);
+static void ( APIENTRY * dllTexCoord2dv )(const GLdouble *v);
+static void ( APIENTRY * dllTexCoord2f )(GLfloat s, GLfloat t);
+static void ( APIENTRY * dllTexCoord2fv )(const GLfloat *v);
+static void ( APIENTRY * dllTexCoord2i )(GLint s, GLint t);
+static void ( APIENTRY * dllTexCoord2iv )(const GLint *v);
+static void ( APIENTRY * dllTexCoord2s )(GLshort s, GLshort t);
+static void ( APIENTRY * dllTexCoord2sv )(const GLshort *v);
+static void ( APIENTRY * dllTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+static void ( APIENTRY * dllTexCoord3dv )(const GLdouble *v);
+static void ( APIENTRY * dllTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+static void ( APIENTRY * dllTexCoord3fv )(const GLfloat *v);
+static void ( APIENTRY * dllTexCoord3i )(GLint s, GLint t, GLint r);
+static void ( APIENTRY * dllTexCoord3iv )(const GLint *v);
+static void ( APIENTRY * dllTexCoord3s )(GLshort s, GLshort t, GLshort r);
+static void ( APIENTRY * dllTexCoord3sv )(const GLshort *v);
+static void ( APIENTRY * dllTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+static void ( APIENTRY * dllTexCoord4dv )(const GLdouble *v);
+static void ( APIENTRY * dllTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+static void ( APIENTRY * dllTexCoord4fv )(const GLfloat *v);
+static void ( APIENTRY * dllTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+static void ( APIENTRY * dllTexCoord4iv )(const GLint *v);
+static void ( APIENTRY * dllTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+static void ( APIENTRY * dllTexCoord4sv )(const GLshort *v);
+static void ( APIENTRY * dllTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+static void ( APIENTRY * dllTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+static void ( APIENTRY * dllTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllTexEnvi )(GLenum target, GLenum pname, GLint param);
+static void ( APIENTRY * dllTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+static void ( APIENTRY * dllTexGend )(GLenum coord, GLenum pname, GLdouble param);
+static void ( APIENTRY * dllTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+static void ( APIENTRY * dllTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+static void ( APIENTRY * dllTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllTexGeni )(GLenum coord, GLenum pname, GLint param);
+static void ( APIENTRY * dllTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+static void ( APIENTRY * dllTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+static void ( APIENTRY * dllTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+static void ( APIENTRY * dllTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+static void ( APIENTRY * dllTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+static void ( APIENTRY * dllTexParameteri )(GLenum target, GLenum pname, GLint param);
+static void ( APIENTRY * dllTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+static void ( APIENTRY * dllTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+static void ( APIENTRY * dllTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+static void ( APIENTRY * dllTranslated )(GLdouble x, GLdouble y, GLdouble z);
+static void ( APIENTRY * dllTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+static void ( APIENTRY * dllVertex2d )(GLdouble x, GLdouble y);
+static void ( APIENTRY * dllVertex2dv )(const GLdouble *v);
+static void ( APIENTRY * dllVertex2f )(GLfloat x, GLfloat y);
+static void ( APIENTRY * dllVertex2fv )(const GLfloat *v);
+static void ( APIENTRY * dllVertex2i )(GLint x, GLint y);
+static void ( APIENTRY * dllVertex2iv )(const GLint *v);
+static void ( APIENTRY * dllVertex2s )(GLshort x, GLshort y);
+static void ( APIENTRY * dllVertex2sv )(const GLshort *v);
+static void ( APIENTRY * dllVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+static void ( APIENTRY * dllVertex3dv )(const GLdouble *v);
+static void ( APIENTRY * dllVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+static void ( APIENTRY * dllVertex3fv )(const GLfloat *v);
+static void ( APIENTRY * dllVertex3i )(GLint x, GLint y, GLint z);
+static void ( APIENTRY * dllVertex3iv )(const GLint *v);
+static void ( APIENTRY * dllVertex3s )(GLshort x, GLshort y, GLshort z);
+static void ( APIENTRY * dllVertex3sv )(const GLshort *v);
+static void ( APIENTRY * dllVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+static void ( APIENTRY * dllVertex4dv )(const GLdouble *v);
+static void ( APIENTRY * dllVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+static void ( APIENTRY * dllVertex4fv )(const GLfloat *v);
+static void ( APIENTRY * dllVertex4i )(GLint x, GLint y, GLint z, GLint w);
+static void ( APIENTRY * dllVertex4iv )(const GLint *v);
+static void ( APIENTRY * dllVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+static void ( APIENTRY * dllVertex4sv )(const GLshort *v);
+static void ( APIENTRY * dllVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+static void ( APIENTRY * dllViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+/*
+** QGL_Shutdown
+**
+** Unloads the specified DLL then nulls out all the proc pointers.
+*/
+void QGL_Shutdown( void )
+{
+ if (g_hGLDLL)
+ {
+ ::FreeLibrary(g_hGLDLL);
+ g_hGLDLL = NULL;
+ }
+
+ qglAccum = NULL;
+ qglAlphaFunc = NULL;
+ qglAreTexturesResident = NULL;
+ qglArrayElement = NULL;
+ qglBegin = NULL;
+ qglBindTexture = NULL;
+ qglBitmap = NULL;
+ qglBlendFunc = NULL;
+ qglCallList = NULL;
+ qglCallLists = NULL;
+ qglClear = NULL;
+ qglClearAccum = NULL;
+ qglClearColor = NULL;
+ qglClearDepth = NULL;
+ qglClearIndex = NULL;
+ qglClearStencil = NULL;
+ qglClipPlane = NULL;
+ qglColor3b = NULL;
+ qglColor3bv = NULL;
+ qglColor3d = NULL;
+ qglColor3dv = NULL;
+ qglColor3f = NULL;
+ qglColor3fv = NULL;
+ qglColor3i = NULL;
+ qglColor3iv = NULL;
+ qglColor3s = NULL;
+ qglColor3sv = NULL;
+ qglColor3ub = NULL;
+ qglColor3ubv = NULL;
+ qglColor3ui = NULL;
+ qglColor3uiv = NULL;
+ qglColor3us = NULL;
+ qglColor3usv = NULL;
+ qglColor4b = NULL;
+ qglColor4bv = NULL;
+ qglColor4d = NULL;
+ qglColor4dv = NULL;
+ qglColor4f = NULL;
+ qglColor4fv = NULL;
+ qglColor4i = NULL;
+ qglColor4iv = NULL;
+ qglColor4s = NULL;
+ qglColor4sv = NULL;
+ qglColor4ub = NULL;
+ qglColor4ubv = NULL;
+ qglColor4ui = NULL;
+ qglColor4uiv = NULL;
+ qglColor4us = NULL;
+ qglColor4usv = NULL;
+ qglColorMask = NULL;
+ qglColorMaterial = NULL;
+ qglColorPointer = NULL;
+ qglCopyPixels = NULL;
+ qglCopyTexImage1D = NULL;
+ qglCopyTexImage2D = NULL;
+ qglCopyTexSubImage1D = NULL;
+ qglCopyTexSubImage2D = NULL;
+ qglCullFace = NULL;
+ qglDeleteLists = NULL;
+ qglDeleteTextures = NULL;
+ qglDepthFunc = NULL;
+ qglDepthMask = NULL;
+ qglDepthRange = NULL;
+ qglDisable = NULL;
+ qglDisableClientState = NULL;
+ qglDrawArrays = NULL;
+ qglDrawBuffer = NULL;
+ qglDrawElements = NULL;
+ qglDrawPixels = NULL;
+ qglEdgeFlag = NULL;
+ qglEdgeFlagPointer = NULL;
+ qglEdgeFlagv = NULL;
+ qglEnable = NULL;
+ qglEnableClientState = NULL;
+ qglEnd = NULL;
+ qglEndList = NULL;
+ qglEvalCoord1d = NULL;
+ qglEvalCoord1dv = NULL;
+ qglEvalCoord1f = NULL;
+ qglEvalCoord1fv = NULL;
+ qglEvalCoord2d = NULL;
+ qglEvalCoord2dv = NULL;
+ qglEvalCoord2f = NULL;
+ qglEvalCoord2fv = NULL;
+ qglEvalMesh1 = NULL;
+ qglEvalMesh2 = NULL;
+ qglEvalPoint1 = NULL;
+ qglEvalPoint2 = NULL;
+ qglFeedbackBuffer = NULL;
+ qglFinish = NULL;
+ qglFlush = NULL;
+ qglFogf = NULL;
+ qglFogfv = NULL;
+ qglFogi = NULL;
+ qglFogiv = NULL;
+ qglFrontFace = NULL;
+ qglFrustum = NULL;
+ qglGenLists = NULL;
+ qglGenTextures = NULL;
+ qglGetBooleanv = NULL;
+ qglGetClipPlane = NULL;
+ qglGetDoublev = NULL;
+ qglGetError = NULL;
+ qglGetFloatv = NULL;
+ qglGetIntegerv = NULL;
+ qglGetLightfv = NULL;
+ qglGetLightiv = NULL;
+ qglGetMapdv = NULL;
+ qglGetMapfv = NULL;
+ qglGetMapiv = NULL;
+ qglGetMaterialfv = NULL;
+ qglGetMaterialiv = NULL;
+ qglGetPixelMapfv = NULL;
+ qglGetPixelMapuiv = NULL;
+ qglGetPixelMapusv = NULL;
+ qglGetPointerv = NULL;
+ qglGetPolygonStipple = NULL;
+ qglGetString = NULL;
+ qglGetTexEnvfv = NULL;
+ qglGetTexEnviv = NULL;
+ qglGetTexGendv = NULL;
+ qglGetTexGenfv = NULL;
+ qglGetTexGeniv = NULL;
+ qglGetTexImage = NULL;
+ qglGetTexLevelParameterfv = NULL;
+ qglGetTexLevelParameteriv = NULL;
+ qglGetTexParameterfv = NULL;
+ qglGetTexParameteriv = NULL;
+ qglHint = NULL;
+ qglIndexMask = NULL;
+ qglIndexPointer = NULL;
+ qglIndexd = NULL;
+ qglIndexdv = NULL;
+ qglIndexf = NULL;
+ qglIndexfv = NULL;
+ qglIndexi = NULL;
+ qglIndexiv = NULL;
+ qglIndexs = NULL;
+ qglIndexsv = NULL;
+ qglIndexub = NULL;
+ qglIndexubv = NULL;
+ qglInitNames = NULL;
+ qglInterleavedArrays = NULL;
+ qglIsEnabled = NULL;
+ qglIsList = NULL;
+ qglIsTexture = NULL;
+ qglLightModelf = NULL;
+ qglLightModelfv = NULL;
+ qglLightModeli = NULL;
+ qglLightModeliv = NULL;
+ qglLightf = NULL;
+ qglLightfv = NULL;
+ qglLighti = NULL;
+ qglLightiv = NULL;
+ qglLineStipple = NULL;
+ qglLineWidth = NULL;
+ qglListBase = NULL;
+ qglLoadIdentity = NULL;
+ qglLoadMatrixd = NULL;
+ qglLoadMatrixf = NULL;
+ qglLoadName = NULL;
+ qglLogicOp = NULL;
+ qglMap1d = NULL;
+ qglMap1f = NULL;
+ qglMap2d = NULL;
+ qglMap2f = NULL;
+ qglMapGrid1d = NULL;
+ qglMapGrid1f = NULL;
+ qglMapGrid2d = NULL;
+ qglMapGrid2f = NULL;
+ qglMaterialf = NULL;
+ qglMaterialfv = NULL;
+ qglMateriali = NULL;
+ qglMaterialiv = NULL;
+ qglMatrixMode = NULL;
+ qglMultMatrixd = NULL;
+ qglMultMatrixf = NULL;
+ qglNewList = NULL;
+ qglNormal3b = NULL;
+ qglNormal3bv = NULL;
+ qglNormal3d = NULL;
+ qglNormal3dv = NULL;
+ qglNormal3f = NULL;
+ qglNormal3fv = NULL;
+ qglNormal3i = NULL;
+ qglNormal3iv = NULL;
+ qglNormal3s = NULL;
+ qglNormal3sv = NULL;
+ qglNormalPointer = NULL;
+ qglOrtho = NULL;
+ qglPassThrough = NULL;
+ qglPixelMapfv = NULL;
+ qglPixelMapuiv = NULL;
+ qglPixelMapusv = NULL;
+ qglPixelStoref = NULL;
+ qglPixelStorei = NULL;
+ qglPixelTransferf = NULL;
+ qglPixelTransferi = NULL;
+ qglPixelZoom = NULL;
+ qglPointSize = NULL;
+ qglPolygonMode = NULL;
+ qglPolygonOffset = NULL;
+ qglPolygonStipple = NULL;
+ qglPopAttrib = NULL;
+ qglPopClientAttrib = NULL;
+ qglPopMatrix = NULL;
+ qglPopName = NULL;
+ qglPrioritizeTextures = NULL;
+ qglPushAttrib = NULL;
+ qglPushClientAttrib = NULL;
+ qglPushMatrix = NULL;
+ qglPushName = NULL;
+ qglRasterPos2d = NULL;
+ qglRasterPos2dv = NULL;
+ qglRasterPos2f = NULL;
+ qglRasterPos2fv = NULL;
+ qglRasterPos2i = NULL;
+ qglRasterPos2iv = NULL;
+ qglRasterPos2s = NULL;
+ qglRasterPos2sv = NULL;
+ qglRasterPos3d = NULL;
+ qglRasterPos3dv = NULL;
+ qglRasterPos3f = NULL;
+ qglRasterPos3fv = NULL;
+ qglRasterPos3i = NULL;
+ qglRasterPos3iv = NULL;
+ qglRasterPos3s = NULL;
+ qglRasterPos3sv = NULL;
+ qglRasterPos4d = NULL;
+ qglRasterPos4dv = NULL;
+ qglRasterPos4f = NULL;
+ qglRasterPos4fv = NULL;
+ qglRasterPos4i = NULL;
+ qglRasterPos4iv = NULL;
+ qglRasterPos4s = NULL;
+ qglRasterPos4sv = NULL;
+ qglReadBuffer = NULL;
+ qglReadPixels = NULL;
+ qglRectd = NULL;
+ qglRectdv = NULL;
+ qglRectf = NULL;
+ qglRectfv = NULL;
+ qglRecti = NULL;
+ qglRectiv = NULL;
+ qglRects = NULL;
+ qglRectsv = NULL;
+ qglRenderMode = NULL;
+ qglRotated = NULL;
+ qglRotatef = NULL;
+ qglScaled = NULL;
+ qglScalef = NULL;
+ qglScissor = NULL;
+ qglSelectBuffer = NULL;
+ qglShadeModel = NULL;
+ qglStencilFunc = NULL;
+ qglStencilMask = NULL;
+ qglStencilOp = NULL;
+ qglTexCoord1d = NULL;
+ qglTexCoord1dv = NULL;
+ qglTexCoord1f = NULL;
+ qglTexCoord1fv = NULL;
+ qglTexCoord1i = NULL;
+ qglTexCoord1iv = NULL;
+ qglTexCoord1s = NULL;
+ qglTexCoord1sv = NULL;
+ qglTexCoord2d = NULL;
+ qglTexCoord2dv = NULL;
+ qglTexCoord2f = NULL;
+ qglTexCoord2fv = NULL;
+ qglTexCoord2i = NULL;
+ qglTexCoord2iv = NULL;
+ qglTexCoord2s = NULL;
+ qglTexCoord2sv = NULL;
+ qglTexCoord3d = NULL;
+ qglTexCoord3dv = NULL;
+ qglTexCoord3f = NULL;
+ qglTexCoord3fv = NULL;
+ qglTexCoord3i = NULL;
+ qglTexCoord3iv = NULL;
+ qglTexCoord3s = NULL;
+ qglTexCoord3sv = NULL;
+ qglTexCoord4d = NULL;
+ qglTexCoord4dv = NULL;
+ qglTexCoord4f = NULL;
+ qglTexCoord4fv = NULL;
+ qglTexCoord4i = NULL;
+ qglTexCoord4iv = NULL;
+ qglTexCoord4s = NULL;
+ qglTexCoord4sv = NULL;
+ qglTexCoordPointer = NULL;
+ qglTexEnvf = NULL;
+ qglTexEnvfv = NULL;
+ qglTexEnvi = NULL;
+ qglTexEnviv = NULL;
+ qglTexGend = NULL;
+ qglTexGendv = NULL;
+ qglTexGenf = NULL;
+ qglTexGenfv = NULL;
+ qglTexGeni = NULL;
+ qglTexGeniv = NULL;
+ qglTexImage1D = NULL;
+ qglTexImage2D = NULL;
+ qglTexParameterf = NULL;
+ qglTexParameterfv = NULL;
+ qglTexParameteri = NULL;
+ qglTexParameteriv = NULL;
+ qglTexSubImage1D = NULL;
+ qglTexSubImage2D = NULL;
+ qglTranslated = NULL;
+ qglTranslatef = NULL;
+ qglVertex2d = NULL;
+ qglVertex2dv = NULL;
+ qglVertex2f = NULL;
+ qglVertex2fv = NULL;
+ qglVertex2i = NULL;
+ qglVertex2iv = NULL;
+ qglVertex2s = NULL;
+ qglVertex2sv = NULL;
+ qglVertex3d = NULL;
+ qglVertex3dv = NULL;
+ qglVertex3f = NULL;
+ qglVertex3fv = NULL;
+ qglVertex3i = NULL;
+ qglVertex3iv = NULL;
+ qglVertex3s = NULL;
+ qglVertex3sv = NULL;
+ qglVertex4d = NULL;
+ qglVertex4dv = NULL;
+ qglVertex4f = NULL;
+ qglVertex4fv = NULL;
+ qglVertex4i = NULL;
+ qglVertex4iv = NULL;
+ qglVertex4s = NULL;
+ qglVertex4sv = NULL;
+ qglVertexPointer = NULL;
+ qglViewport = NULL;
+
+ qwglCopyContext = NULL;
+ qwglCreateContext = NULL;
+ qwglCreateLayerContext = NULL;
+ qwglDeleteContext = NULL;
+ qwglDescribeLayerPlane = NULL;
+ qwglGetCurrentContext = NULL;
+ qwglGetCurrentDC = NULL;
+ qwglGetLayerPaletteEntries = NULL;
+ qwglGetProcAddress = NULL;
+ qwglMakeCurrent = NULL;
+ qwglRealizeLayerPalette = NULL;
+ qwglSetLayerPaletteEntries = NULL;
+ qwglShareLists = NULL;
+ qwglSwapLayerBuffers = NULL;
+ qwglUseFontBitmaps = NULL;
+ qwglUseFontOutlines = NULL;
+
+ qwglChoosePixelFormat = NULL;
+ qwglDescribePixelFormat = NULL;
+ qwglGetPixelFormat = NULL;
+ qwglSetPixelFormat = NULL;
+ qwglSwapBuffers = NULL;
+
+ qwglSwapIntervalEXT = NULL;
+
+ qwglGetDeviceGammaRampEXT = NULL;
+ qwglSetDeviceGammaRampEXT = NULL;
+}
+
+# define GPA(h, a ) GetProcAddress( h, a )
+
+/*
+** QGL_Init
+**
+** This is responsible for binding our qgl function pointers to
+** the appropriate GL stuff. In Windows this means doing a
+** LoadLibrary and a bunch of calls to GetProcAddress. On other
+** operating systems we need to do the right thing, whatever that
+** might be.
+**
+*/
+qboolean QGL_Init(const char *dllname )
+{
+
+ g_hGLDLL = ::LoadLibrary(dllname);
+
+ qglAccum = dllAccum = GPA(g_hGLDLL, "glAccum" );
+ qglAlphaFunc = dllAlphaFunc = GPA(g_hGLDLL, "glAlphaFunc" );
+ qglAreTexturesResident = dllAreTexturesResident = GPA(g_hGLDLL, "glAreTexturesResident" );
+ qglArrayElement = dllArrayElement = GPA(g_hGLDLL, "glArrayElement" );
+ qglBegin = dllBegin = GPA(g_hGLDLL, "glBegin" );
+ qglBindTexture = dllBindTexture = GPA(g_hGLDLL, "glBindTexture" );
+ qglBitmap = dllBitmap = GPA(g_hGLDLL, "glBitmap" );
+ qglBlendFunc = dllBlendFunc = GPA(g_hGLDLL, "glBlendFunc" );
+ qglCallList = dllCallList = GPA(g_hGLDLL, "glCallList" );
+ qglCallLists = dllCallLists = GPA(g_hGLDLL, "glCallLists" );
+ qglClear = dllClear = GPA(g_hGLDLL, "glClear" );
+ qglClearAccum = dllClearAccum = GPA(g_hGLDLL, "glClearAccum" );
+ qglClearColor = dllClearColor = GPA(g_hGLDLL, "glClearColor" );
+ qglClearDepth = dllClearDepth = GPA(g_hGLDLL, "glClearDepth" );
+ qglClearIndex = dllClearIndex = GPA(g_hGLDLL, "glClearIndex" );
+ qglClearStencil = dllClearStencil = GPA(g_hGLDLL, "glClearStencil" );
+ qglClipPlane = dllClipPlane = GPA(g_hGLDLL, "glClipPlane" );
+ qglColor3b = dllColor3b = GPA(g_hGLDLL, "glColor3b" );
+ qglColor3bv = dllColor3bv = GPA(g_hGLDLL, "glColor3bv" );
+ qglColor3d = dllColor3d = GPA(g_hGLDLL, "glColor3d" );
+ qglColor3dv = dllColor3dv = GPA(g_hGLDLL, "glColor3dv" );
+ qglColor3f = dllColor3f = GPA(g_hGLDLL, "glColor3f" );
+ qglColor3fv = dllColor3fv = GPA(g_hGLDLL, "glColor3fv" );
+ qglColor3i = dllColor3i = GPA(g_hGLDLL, "glColor3i" );
+ qglColor3iv = dllColor3iv = GPA(g_hGLDLL, "glColor3iv" );
+ qglColor3s = dllColor3s = GPA(g_hGLDLL, "glColor3s" );
+ qglColor3sv = dllColor3sv = GPA(g_hGLDLL, "glColor3sv" );
+ qglColor3ub = dllColor3ub = GPA(g_hGLDLL, "glColor3ub" );
+ qglColor3ubv = dllColor3ubv = GPA(g_hGLDLL, "glColor3ubv" );
+ qglColor3ui = dllColor3ui = GPA(g_hGLDLL, "glColor3ui" );
+ qglColor3uiv = dllColor3uiv = GPA(g_hGLDLL, "glColor3uiv" );
+ qglColor3us = dllColor3us = GPA(g_hGLDLL, "glColor3us" );
+ qglColor3usv = dllColor3usv = GPA(g_hGLDLL, "glColor3usv" );
+ qglColor4b = dllColor4b = GPA(g_hGLDLL, "glColor4b" );
+ qglColor4bv = dllColor4bv = GPA(g_hGLDLL, "glColor4bv" );
+ qglColor4d = dllColor4d = GPA(g_hGLDLL, "glColor4d" );
+ qglColor4dv = dllColor4dv = GPA(g_hGLDLL, "glColor4dv" );
+ qglColor4f = dllColor4f = GPA(g_hGLDLL, "glColor4f" );
+ qglColor4fv = dllColor4fv = GPA(g_hGLDLL, "glColor4fv" );
+ qglColor4i = dllColor4i = GPA(g_hGLDLL, "glColor4i" );
+ qglColor4iv = dllColor4iv = GPA(g_hGLDLL, "glColor4iv" );
+ qglColor4s = dllColor4s = GPA(g_hGLDLL, "glColor4s" );
+ qglColor4sv = dllColor4sv = GPA(g_hGLDLL, "glColor4sv" );
+ qglColor4ub = dllColor4ub = GPA(g_hGLDLL, "glColor4ub" );
+ qglColor4ubv = dllColor4ubv = GPA(g_hGLDLL, "glColor4ubv" );
+ qglColor4ui = dllColor4ui = GPA(g_hGLDLL, "glColor4ui" );
+ qglColor4uiv = dllColor4uiv = GPA(g_hGLDLL, "glColor4uiv" );
+ qglColor4us = dllColor4us = GPA(g_hGLDLL, "glColor4us" );
+ qglColor4usv = dllColor4usv = GPA(g_hGLDLL, "glColor4usv" );
+ qglColorMask = dllColorMask = GPA(g_hGLDLL, "glColorMask" );
+ qglColorMaterial = dllColorMaterial = GPA(g_hGLDLL, "glColorMaterial" );
+ qglColorPointer = dllColorPointer = GPA(g_hGLDLL, "glColorPointer" );
+ qglCopyPixels = dllCopyPixels = GPA(g_hGLDLL, "glCopyPixels" );
+ qglCopyTexImage1D = dllCopyTexImage1D = GPA(g_hGLDLL, "glCopyTexImage1D" );
+ qglCopyTexImage2D = dllCopyTexImage2D = GPA(g_hGLDLL, "glCopyTexImage2D" );
+ qglCopyTexSubImage1D = dllCopyTexSubImage1D = GPA(g_hGLDLL, "glCopyTexSubImage1D" );
+ qglCopyTexSubImage2D = dllCopyTexSubImage2D = GPA(g_hGLDLL, "glCopyTexSubImage2D" );
+ qglCullFace = dllCullFace = GPA(g_hGLDLL, "glCullFace" );
+ qglDeleteLists = dllDeleteLists = GPA(g_hGLDLL, "glDeleteLists" );
+ qglDeleteTextures = dllDeleteTextures = GPA(g_hGLDLL, "glDeleteTextures" );
+ qglDepthFunc = dllDepthFunc = GPA(g_hGLDLL, "glDepthFunc" );
+ qglDepthMask = dllDepthMask = GPA(g_hGLDLL, "glDepthMask" );
+ qglDepthRange = dllDepthRange = GPA(g_hGLDLL, "glDepthRange" );
+ qglDisable = dllDisable = GPA(g_hGLDLL, "glDisable" );
+ qglDisableClientState = dllDisableClientState = GPA(g_hGLDLL, "glDisableClientState" );
+ qglDrawArrays = dllDrawArrays = GPA(g_hGLDLL, "glDrawArrays" );
+ qglDrawBuffer = dllDrawBuffer = GPA(g_hGLDLL, "glDrawBuffer" );
+ qglDrawElements = dllDrawElements = GPA(g_hGLDLL, "glDrawElements" );
+ qglDrawPixels = dllDrawPixels = GPA(g_hGLDLL, "glDrawPixels" );
+ qglEdgeFlag = dllEdgeFlag = GPA(g_hGLDLL, "glEdgeFlag" );
+ qglEdgeFlagPointer = dllEdgeFlagPointer = GPA(g_hGLDLL, "glEdgeFlagPointer" );
+ qglEdgeFlagv = dllEdgeFlagv = GPA(g_hGLDLL, "glEdgeFlagv" );
+ qglEnable = dllEnable = GPA(g_hGLDLL, "glEnable" );
+ qglEnableClientState = dllEnableClientState = GPA(g_hGLDLL, "glEnableClientState" );
+ qglEnd = dllEnd = GPA(g_hGLDLL, "glEnd" );
+ qglEndList = dllEndList = GPA(g_hGLDLL, "glEndList" );
+ qglEvalCoord1d = dllEvalCoord1d = GPA(g_hGLDLL, "glEvalCoord1d" );
+ qglEvalCoord1dv = dllEvalCoord1dv = GPA(g_hGLDLL, "glEvalCoord1dv" );
+ qglEvalCoord1f = dllEvalCoord1f = GPA(g_hGLDLL, "glEvalCoord1f" );
+ qglEvalCoord1fv = dllEvalCoord1fv = GPA(g_hGLDLL, "glEvalCoord1fv" );
+ qglEvalCoord2d = dllEvalCoord2d = GPA(g_hGLDLL, "glEvalCoord2d" );
+ qglEvalCoord2dv = dllEvalCoord2dv = GPA(g_hGLDLL, "glEvalCoord2dv" );
+ qglEvalCoord2f = dllEvalCoord2f = GPA(g_hGLDLL, "glEvalCoord2f" );
+ qglEvalCoord2fv = dllEvalCoord2fv = GPA(g_hGLDLL, "glEvalCoord2fv" );
+ qglEvalMesh1 = dllEvalMesh1 = GPA(g_hGLDLL, "glEvalMesh1" );
+ qglEvalMesh2 = dllEvalMesh2 = GPA(g_hGLDLL, "glEvalMesh2" );
+ qglEvalPoint1 = dllEvalPoint1 = GPA(g_hGLDLL, "glEvalPoint1" );
+ qglEvalPoint2 = dllEvalPoint2 = GPA(g_hGLDLL, "glEvalPoint2" );
+ qglFeedbackBuffer = dllFeedbackBuffer = GPA(g_hGLDLL, "glFeedbackBuffer" );
+ qglFinish = dllFinish = GPA(g_hGLDLL, "glFinish" );
+ qglFlush = dllFlush = GPA(g_hGLDLL, "glFlush" );
+ qglFogf = dllFogf = GPA(g_hGLDLL, "glFogf" );
+ qglFogfv = dllFogfv = GPA(g_hGLDLL, "glFogfv" );
+ qglFogi = dllFogi = GPA(g_hGLDLL, "glFogi" );
+ qglFogiv = dllFogiv = GPA(g_hGLDLL, "glFogiv" );
+ qglFrontFace = dllFrontFace = GPA(g_hGLDLL, "glFrontFace" );
+ qglFrustum = dllFrustum = GPA(g_hGLDLL, "glFrustum" );
+ qglGenLists = dllGenLists = GPA(g_hGLDLL, "glGenLists" );
+ qglGenTextures = dllGenTextures = GPA(g_hGLDLL, "glGenTextures" );
+ qglGetBooleanv = dllGetBooleanv = GPA(g_hGLDLL, "glGetBooleanv" );
+ qglGetClipPlane = dllGetClipPlane = GPA(g_hGLDLL, "glGetClipPlane" );
+ qglGetDoublev = dllGetDoublev = GPA(g_hGLDLL, "glGetDoublev" );
+ qglGetError = dllGetError = GPA(g_hGLDLL, "glGetError" );
+ qglGetFloatv = dllGetFloatv = GPA(g_hGLDLL, "glGetFloatv" );
+ qglGetIntegerv = dllGetIntegerv = GPA(g_hGLDLL, "glGetIntegerv" );
+ qglGetLightfv = dllGetLightfv = GPA(g_hGLDLL, "glGetLightfv" );
+ qglGetLightiv = dllGetLightiv = GPA(g_hGLDLL, "glGetLightiv" );
+ qglGetMapdv = dllGetMapdv = GPA(g_hGLDLL, "glGetMapdv" );
+ qglGetMapfv = dllGetMapfv = GPA(g_hGLDLL, "glGetMapfv" );
+ qglGetMapiv = dllGetMapiv = GPA(g_hGLDLL, "glGetMapiv" );
+ qglGetMaterialfv = dllGetMaterialfv = GPA(g_hGLDLL, "glGetMaterialfv" );
+ qglGetMaterialiv = dllGetMaterialiv = GPA(g_hGLDLL, "glGetMaterialiv" );
+ qglGetPixelMapfv = dllGetPixelMapfv = GPA(g_hGLDLL, "glGetPixelMapfv" );
+ qglGetPixelMapuiv = dllGetPixelMapuiv = GPA(g_hGLDLL, "glGetPixelMapuiv" );
+ qglGetPixelMapusv = dllGetPixelMapusv = GPA(g_hGLDLL, "glGetPixelMapusv" );
+ qglGetPointerv = dllGetPointerv = GPA(g_hGLDLL, "glGetPointerv" );
+ qglGetPolygonStipple = dllGetPolygonStipple = GPA(g_hGLDLL, "glGetPolygonStipple" );
+ qglGetString = dllGetString = GPA(g_hGLDLL, "glGetString" );
+ qglGetTexEnvfv = dllGetTexEnvfv = GPA(g_hGLDLL, "glGetTexEnvfv" );
+ qglGetTexEnviv = dllGetTexEnviv = GPA(g_hGLDLL, "glGetTexEnviv" );
+ qglGetTexGendv = dllGetTexGendv = GPA(g_hGLDLL, "glGetTexGendv" );
+ qglGetTexGenfv = dllGetTexGenfv = GPA(g_hGLDLL, "glGetTexGenfv" );
+ qglGetTexGeniv = dllGetTexGeniv = GPA(g_hGLDLL, "glGetTexGeniv" );
+ qglGetTexImage = dllGetTexImage = GPA(g_hGLDLL, "glGetTexImage" );
+ qglGetTexLevelParameterfv = dllGetTexLevelParameterfv = GPA(g_hGLDLL, "glGetLevelParameterfv" );
+ qglGetTexLevelParameteriv = dllGetTexLevelParameteriv = GPA(g_hGLDLL, "glGetLevelParameteriv" );
+ qglGetTexParameterfv = dllGetTexParameterfv = GPA(g_hGLDLL, "glGetTexParameterfv" );
+ qglGetTexParameteriv = dllGetTexParameteriv = GPA(g_hGLDLL, "glGetTexParameteriv" );
+ qglHint = dllHint = GPA(g_hGLDLL, "glHint" );
+ qglIndexMask = dllIndexMask = GPA(g_hGLDLL, "glIndexMask" );
+ qglIndexPointer = dllIndexPointer = GPA(g_hGLDLL, "glIndexPointer" );
+ qglIndexd = dllIndexd = GPA(g_hGLDLL, "glIndexd" );
+ qglIndexdv = dllIndexdv = GPA(g_hGLDLL, "glIndexdv" );
+ qglIndexf = dllIndexf = GPA(g_hGLDLL, "glIndexf" );
+ qglIndexfv = dllIndexfv = GPA(g_hGLDLL, "glIndexfv" );
+ qglIndexi = dllIndexi = GPA(g_hGLDLL, "glIndexi" );
+ qglIndexiv = dllIndexiv = GPA(g_hGLDLL, "glIndexiv" );
+ qglIndexs = dllIndexs = GPA(g_hGLDLL, "glIndexs" );
+ qglIndexsv = dllIndexsv = GPA(g_hGLDLL, "glIndexsv" );
+ qglIndexub = dllIndexub = GPA(g_hGLDLL, "glIndexub" );
+ qglIndexubv = dllIndexubv = GPA(g_hGLDLL, "glIndexubv" );
+ qglInitNames = dllInitNames = GPA(g_hGLDLL, "glInitNames" );
+ qglInterleavedArrays = dllInterleavedArrays = GPA(g_hGLDLL, "glInterleavedArrays" );
+ qglIsEnabled = dllIsEnabled = GPA(g_hGLDLL, "glIsEnabled" );
+ qglIsList = dllIsList = GPA(g_hGLDLL, "glIsList" );
+ qglIsTexture = dllIsTexture = GPA(g_hGLDLL, "glIsTexture" );
+ qglLightModelf = dllLightModelf = GPA(g_hGLDLL, "glLightModelf" );
+ qglLightModelfv = dllLightModelfv = GPA(g_hGLDLL, "glLightModelfv" );
+ qglLightModeli = dllLightModeli = GPA(g_hGLDLL, "glLightModeli" );
+ qglLightModeliv = dllLightModeliv = GPA(g_hGLDLL, "glLightModeliv" );
+ qglLightf = dllLightf = GPA(g_hGLDLL, "glLightf" );
+ qglLightfv = dllLightfv = GPA(g_hGLDLL, "glLightfv" );
+ qglLighti = dllLighti = GPA(g_hGLDLL, "glLighti" );
+ qglLightiv = dllLightiv = GPA(g_hGLDLL, "glLightiv" );
+ qglLineStipple = dllLineStipple = GPA(g_hGLDLL, "glLineStipple" );
+ qglLineWidth = dllLineWidth = GPA(g_hGLDLL, "glLineWidth" );
+ qglListBase = dllListBase = GPA(g_hGLDLL, "glListBase" );
+ qglLoadIdentity = dllLoadIdentity = GPA(g_hGLDLL, "glLoadIdentity" );
+ qglLoadMatrixd = dllLoadMatrixd = GPA(g_hGLDLL, "glLoadMatrixd" );
+ qglLoadMatrixf = dllLoadMatrixf = GPA(g_hGLDLL, "glLoadMatrixf" );
+ qglLoadName = dllLoadName = GPA(g_hGLDLL, "glLoadName" );
+ qglLogicOp = dllLogicOp = GPA(g_hGLDLL, "glLogicOp" );
+ qglMap1d = dllMap1d = GPA(g_hGLDLL, "glMap1d" );
+ qglMap1f = dllMap1f = GPA(g_hGLDLL, "glMap1f" );
+ qglMap2d = dllMap2d = GPA(g_hGLDLL, "glMap2d" );
+ qglMap2f = dllMap2f = GPA(g_hGLDLL, "glMap2f" );
+ qglMapGrid1d = dllMapGrid1d = GPA(g_hGLDLL, "glMapGrid1d" );
+ qglMapGrid1f = dllMapGrid1f = GPA(g_hGLDLL, "glMapGrid1f" );
+ qglMapGrid2d = dllMapGrid2d = GPA(g_hGLDLL, "glMapGrid2d" );
+ qglMapGrid2f = dllMapGrid2f = GPA(g_hGLDLL, "glMapGrid2f" );
+ qglMaterialf = dllMaterialf = GPA(g_hGLDLL, "glMaterialf" );
+ qglMaterialfv = dllMaterialfv = GPA(g_hGLDLL, "glMaterialfv" );
+ qglMateriali = dllMateriali = GPA(g_hGLDLL, "glMateriali" );
+ qglMaterialiv = dllMaterialiv = GPA(g_hGLDLL, "glMaterialiv" );
+ qglMatrixMode = dllMatrixMode = GPA(g_hGLDLL, "glMatrixMode" );
+ qglMultMatrixd = dllMultMatrixd = GPA(g_hGLDLL, "glMultMatrixd" );
+ qglMultMatrixf = dllMultMatrixf = GPA(g_hGLDLL, "glMultMatrixf" );
+ qglNewList = dllNewList = GPA(g_hGLDLL, "glNewList" );
+ qglNormal3b = dllNormal3b = GPA(g_hGLDLL, "glNormal3b" );
+ qglNormal3bv = dllNormal3bv = GPA(g_hGLDLL, "glNormal3bv" );
+ qglNormal3d = dllNormal3d = GPA(g_hGLDLL, "glNormal3d" );
+ qglNormal3dv = dllNormal3dv = GPA(g_hGLDLL, "glNormal3dv" );
+ qglNormal3f = dllNormal3f = GPA(g_hGLDLL, "glNormal3f" );
+ qglNormal3fv = dllNormal3fv = GPA(g_hGLDLL, "glNormal3fv" );
+ qglNormal3i = dllNormal3i = GPA(g_hGLDLL, "glNormal3i" );
+ qglNormal3iv = dllNormal3iv = GPA(g_hGLDLL, "glNormal3iv" );
+ qglNormal3s = dllNormal3s = GPA(g_hGLDLL, "glNormal3s" );
+ qglNormal3sv = dllNormal3sv = GPA(g_hGLDLL, "glNormal3sv" );
+ qglNormalPointer = dllNormalPointer = GPA(g_hGLDLL, "glNormalPointer" );
+ qglOrtho = dllOrtho = GPA(g_hGLDLL, "glOrtho" );
+ qglPassThrough = dllPassThrough = GPA(g_hGLDLL, "glPassThrough" );
+ qglPixelMapfv = dllPixelMapfv = GPA(g_hGLDLL, "glPixelMapfv" );
+ qglPixelMapuiv = dllPixelMapuiv = GPA(g_hGLDLL, "glPixelMapuiv" );
+ qglPixelMapusv = dllPixelMapusv = GPA(g_hGLDLL, "glPixelMapusv" );
+ qglPixelStoref = dllPixelStoref = GPA(g_hGLDLL, "glPixelStoref" );
+ qglPixelStorei = dllPixelStorei = GPA(g_hGLDLL, "glPixelStorei" );
+ qglPixelTransferf = dllPixelTransferf = GPA(g_hGLDLL, "glPixelTransferf" );
+ qglPixelTransferi = dllPixelTransferi = GPA(g_hGLDLL, "glPixelTransferi" );
+ qglPixelZoom = dllPixelZoom = GPA(g_hGLDLL, "glPixelZoom" );
+ qglPointSize = dllPointSize = GPA(g_hGLDLL, "glPointSize" );
+ qglPolygonMode = dllPolygonMode = GPA(g_hGLDLL, "glPolygonMode" );
+ qglPolygonOffset = dllPolygonOffset = GPA(g_hGLDLL, "glPolygonOffset" );
+ qglPolygonStipple = dllPolygonStipple = GPA(g_hGLDLL, "glPolygonStipple" );
+ qglPopAttrib = dllPopAttrib = GPA(g_hGLDLL, "glPopAttrib" );
+ qglPopClientAttrib = dllPopClientAttrib = GPA(g_hGLDLL, "glPopClientAttrib" );
+ qglPopMatrix = dllPopMatrix = GPA(g_hGLDLL, "glPopMatrix" );
+ qglPopName = dllPopName = GPA(g_hGLDLL, "glPopName" );
+ qglPrioritizeTextures = dllPrioritizeTextures = GPA(g_hGLDLL, "glPrioritizeTextures" );
+ qglPushAttrib = dllPushAttrib = GPA(g_hGLDLL, "glPushAttrib" );
+ qglPushClientAttrib = dllPushClientAttrib = GPA(g_hGLDLL, "glPushClientAttrib" );
+ qglPushMatrix = dllPushMatrix = GPA(g_hGLDLL, "glPushMatrix" );
+ qglPushName = dllPushName = GPA(g_hGLDLL, "glPushName" );
+ qglRasterPos2d = dllRasterPos2d = GPA(g_hGLDLL, "glRasterPos2d" );
+ qglRasterPos2dv = dllRasterPos2dv = GPA(g_hGLDLL, "glRasterPos2dv" );
+ qglRasterPos2f = dllRasterPos2f = GPA(g_hGLDLL, "glRasterPos2f" );
+ qglRasterPos2fv = dllRasterPos2fv = GPA(g_hGLDLL, "glRasterPos2fv" );
+ qglRasterPos2i = dllRasterPos2i = GPA(g_hGLDLL, "glRasterPos2i" );
+ qglRasterPos2iv = dllRasterPos2iv = GPA(g_hGLDLL, "glRasterPos2iv" );
+ qglRasterPos2s = dllRasterPos2s = GPA(g_hGLDLL, "glRasterPos2s" );
+ qglRasterPos2sv = dllRasterPos2sv = GPA(g_hGLDLL, "glRasterPos2sv" );
+ qglRasterPos3d = dllRasterPos3d = GPA(g_hGLDLL, "glRasterPos3d" );
+ qglRasterPos3dv = dllRasterPos3dv = GPA(g_hGLDLL, "glRasterPos3dv" );
+ qglRasterPos3f = dllRasterPos3f = GPA(g_hGLDLL, "glRasterPos3f" );
+ qglRasterPos3fv = dllRasterPos3fv = GPA(g_hGLDLL, "glRasterPos3fv" );
+ qglRasterPos3i = dllRasterPos3i = GPA(g_hGLDLL, "glRasterPos3i" );
+ qglRasterPos3iv = dllRasterPos3iv = GPA(g_hGLDLL, "glRasterPos3iv" );
+ qglRasterPos3s = dllRasterPos3s = GPA(g_hGLDLL, "glRasterPos3s" );
+ qglRasterPos3sv = dllRasterPos3sv = GPA(g_hGLDLL, "glRasterPos3sv" );
+ qglRasterPos4d = dllRasterPos4d = GPA(g_hGLDLL, "glRasterPos4d" );
+ qglRasterPos4dv = dllRasterPos4dv = GPA(g_hGLDLL, "glRasterPos4dv" );
+ qglRasterPos4f = dllRasterPos4f = GPA(g_hGLDLL, "glRasterPos4f" );
+ qglRasterPos4fv = dllRasterPos4fv = GPA(g_hGLDLL, "glRasterPos4fv" );
+ qglRasterPos4i = dllRasterPos4i = GPA(g_hGLDLL, "glRasterPos4i" );
+ qglRasterPos4iv = dllRasterPos4iv = GPA(g_hGLDLL, "glRasterPos4iv" );
+ qglRasterPos4s = dllRasterPos4s = GPA(g_hGLDLL, "glRasterPos4s" );
+ qglRasterPos4sv = dllRasterPos4sv = GPA(g_hGLDLL, "glRasterPos4sv" );
+ qglReadBuffer = dllReadBuffer = GPA(g_hGLDLL, "glReadBuffer" );
+ qglReadPixels = dllReadPixels = GPA(g_hGLDLL, "glReadPixels" );
+ qglRectd = dllRectd = GPA(g_hGLDLL, "glRectd" );
+ qglRectdv = dllRectdv = GPA(g_hGLDLL, "glRectdv" );
+ qglRectf = dllRectf = GPA(g_hGLDLL, "glRectf" );
+ qglRectfv = dllRectfv = GPA(g_hGLDLL, "glRectfv" );
+ qglRecti = dllRecti = GPA(g_hGLDLL, "glRecti" );
+ qglRectiv = dllRectiv = GPA(g_hGLDLL, "glRectiv" );
+ qglRects = dllRects = GPA(g_hGLDLL, "glRects" );
+ qglRectsv = dllRectsv = GPA(g_hGLDLL, "glRectsv" );
+ qglRenderMode = dllRenderMode = GPA(g_hGLDLL, "glRenderMode" );
+ qglRotated = dllRotated = GPA(g_hGLDLL, "glRotated" );
+ qglRotatef = dllRotatef = GPA(g_hGLDLL, "glRotatef" );
+ qglScaled = dllScaled = GPA(g_hGLDLL, "glScaled" );
+ qglScalef = dllScalef = GPA(g_hGLDLL, "glScalef" );
+ qglScissor = dllScissor = GPA(g_hGLDLL, "glScissor" );
+ qglSelectBuffer = dllSelectBuffer = GPA(g_hGLDLL, "glSelectBuffer" );
+ qglShadeModel = dllShadeModel = GPA(g_hGLDLL, "glShadeModel" );
+ qglStencilFunc = dllStencilFunc = GPA(g_hGLDLL, "glStencilFunc" );
+ qglStencilMask = dllStencilMask = GPA(g_hGLDLL, "glStencilMask" );
+ qglStencilOp = dllStencilOp = GPA(g_hGLDLL, "glStencilOp" );
+ qglTexCoord1d = dllTexCoord1d = GPA(g_hGLDLL, "glTexCoord1d" );
+ qglTexCoord1dv = dllTexCoord1dv = GPA(g_hGLDLL, "glTexCoord1dv" );
+ qglTexCoord1f = dllTexCoord1f = GPA(g_hGLDLL, "glTexCoord1f" );
+ qglTexCoord1fv = dllTexCoord1fv = GPA(g_hGLDLL, "glTexCoord1fv" );
+ qglTexCoord1i = dllTexCoord1i = GPA(g_hGLDLL, "glTexCoord1i" );
+ qglTexCoord1iv = dllTexCoord1iv = GPA(g_hGLDLL, "glTexCoord1iv" );
+ qglTexCoord1s = dllTexCoord1s = GPA(g_hGLDLL, "glTexCoord1s" );
+ qglTexCoord1sv = dllTexCoord1sv = GPA(g_hGLDLL, "glTexCoord1sv" );
+ qglTexCoord2d = dllTexCoord2d = GPA(g_hGLDLL, "glTexCoord2d" );
+ qglTexCoord2dv = dllTexCoord2dv = GPA(g_hGLDLL, "glTexCoord2dv" );
+ qglTexCoord2f = dllTexCoord2f = GPA(g_hGLDLL, "glTexCoord2f" );
+ qglTexCoord2fv = dllTexCoord2fv = GPA(g_hGLDLL, "glTexCoord2fv" );
+ qglTexCoord2i = dllTexCoord2i = GPA(g_hGLDLL, "glTexCoord2i" );
+ qglTexCoord2iv = dllTexCoord2iv = GPA(g_hGLDLL, "glTexCoord2iv" );
+ qglTexCoord2s = dllTexCoord2s = GPA(g_hGLDLL, "glTexCoord2s" );
+ qglTexCoord2sv = dllTexCoord2sv = GPA(g_hGLDLL, "glTexCoord2sv" );
+ qglTexCoord3d = dllTexCoord3d = GPA(g_hGLDLL, "glTexCoord3d" );
+ qglTexCoord3dv = dllTexCoord3dv = GPA(g_hGLDLL, "glTexCoord3dv" );
+ qglTexCoord3f = dllTexCoord3f = GPA(g_hGLDLL, "glTexCoord3f" );
+ qglTexCoord3fv = dllTexCoord3fv = GPA(g_hGLDLL, "glTexCoord3fv" );
+ qglTexCoord3i = dllTexCoord3i = GPA(g_hGLDLL, "glTexCoord3i" );
+ qglTexCoord3iv = dllTexCoord3iv = GPA(g_hGLDLL, "glTexCoord3iv" );
+ qglTexCoord3s = dllTexCoord3s = GPA(g_hGLDLL, "glTexCoord3s" );
+ qglTexCoord3sv = dllTexCoord3sv = GPA(g_hGLDLL, "glTexCoord3sv" );
+ qglTexCoord4d = dllTexCoord4d = GPA(g_hGLDLL, "glTexCoord4d" );
+ qglTexCoord4dv = dllTexCoord4dv = GPA(g_hGLDLL, "glTexCoord4dv" );
+ qglTexCoord4f = dllTexCoord4f = GPA(g_hGLDLL, "glTexCoord4f" );
+ qglTexCoord4fv = dllTexCoord4fv = GPA(g_hGLDLL, "glTexCoord4fv" );
+ qglTexCoord4i = dllTexCoord4i = GPA(g_hGLDLL, "glTexCoord4i" );
+ qglTexCoord4iv = dllTexCoord4iv = GPA(g_hGLDLL, "glTexCoord4iv" );
+ qglTexCoord4s = dllTexCoord4s = GPA(g_hGLDLL, "glTexCoord4s" );
+ qglTexCoord4sv = dllTexCoord4sv = GPA(g_hGLDLL, "glTexCoord4sv" );
+ qglTexCoordPointer = dllTexCoordPointer = GPA(g_hGLDLL, "glTexCoordPointer" );
+ qglTexEnvf = dllTexEnvf = GPA(g_hGLDLL, "glTexEnvf" );
+ qglTexEnvfv = dllTexEnvfv = GPA(g_hGLDLL, "glTexEnvfv" );
+ qglTexEnvi = dllTexEnvi = GPA(g_hGLDLL, "glTexEnvi" );
+ qglTexEnviv = dllTexEnviv = GPA(g_hGLDLL, "glTexEnviv" );
+ qglTexGend = dllTexGend = GPA(g_hGLDLL, "glTexGend" );
+ qglTexGendv = dllTexGendv = GPA(g_hGLDLL, "glTexGendv" );
+ qglTexGenf = dllTexGenf = GPA(g_hGLDLL, "glTexGenf" );
+ qglTexGenfv = dllTexGenfv = GPA(g_hGLDLL, "glTexGenfv" );
+ qglTexGeni = dllTexGeni = GPA(g_hGLDLL, "glTexGeni" );
+ qglTexGeniv = dllTexGeniv = GPA(g_hGLDLL, "glTexGeniv" );
+ qglTexImage1D = dllTexImage1D = GPA(g_hGLDLL, "glTexImage1D" );
+ qglTexImage2D = dllTexImage2D = GPA(g_hGLDLL, "glTexImage2D" );
+ qglTexParameterf = dllTexParameterf = GPA(g_hGLDLL, "glTexParameterf" );
+ qglTexParameterfv = dllTexParameterfv = GPA(g_hGLDLL, "glTexParameterfv" );
+ qglTexParameteri = dllTexParameteri = GPA(g_hGLDLL, "glTexParameteri" );
+ qglTexParameteriv = dllTexParameteriv = GPA(g_hGLDLL, "glTexParameteriv" );
+ qglTexSubImage1D = dllTexSubImage1D = GPA(g_hGLDLL, "glTexSubImage1D" );
+ qglTexSubImage2D = dllTexSubImage2D = GPA(g_hGLDLL, "glTexSubImage2D" );
+ qglTranslated = dllTranslated = GPA(g_hGLDLL, "glTranslated" );
+ qglTranslatef = dllTranslatef = GPA(g_hGLDLL, "glTranslatef" );
+ qglVertex2d = dllVertex2d = GPA(g_hGLDLL, "glVertex2d" );
+ qglVertex2dv = dllVertex2dv = GPA(g_hGLDLL, "glVertex2dv" );
+ qglVertex2f = dllVertex2f = GPA(g_hGLDLL, "glVertex2f" );
+ qglVertex2fv = dllVertex2fv = GPA(g_hGLDLL, "glVertex2fv" );
+ qglVertex2i = dllVertex2i = GPA(g_hGLDLL, "glVertex2i" );
+ qglVertex2iv = dllVertex2iv = GPA(g_hGLDLL, "glVertex2iv" );
+ qglVertex2s = dllVertex2s = GPA(g_hGLDLL, "glVertex2s" );
+ qglVertex2sv = dllVertex2sv = GPA(g_hGLDLL, "glVertex2sv" );
+ qglVertex3d = dllVertex3d = GPA(g_hGLDLL, "glVertex3d" );
+ qglVertex3dv = dllVertex3dv = GPA(g_hGLDLL, "glVertex3dv" );
+ qglVertex3f = dllVertex3f = GPA(g_hGLDLL, "glVertex3f" );
+ qglVertex3fv = dllVertex3fv = GPA(g_hGLDLL, "glVertex3fv" );
+ qglVertex3i = dllVertex3i = GPA(g_hGLDLL, "glVertex3i" );
+ qglVertex3iv = dllVertex3iv = GPA(g_hGLDLL, "glVertex3iv" );
+ qglVertex3s = dllVertex3s = GPA(g_hGLDLL, "glVertex3s" );
+ qglVertex3sv = dllVertex3sv = GPA(g_hGLDLL, "glVertex3sv" );
+ qglVertex4d = dllVertex4d = GPA(g_hGLDLL, "glVertex4d" );
+ qglVertex4dv = dllVertex4dv = GPA(g_hGLDLL, "glVertex4dv" );
+ qglVertex4f = dllVertex4f = GPA(g_hGLDLL, "glVertex4f" );
+ qglVertex4fv = dllVertex4fv = GPA(g_hGLDLL, "glVertex4fv" );
+ qglVertex4i = dllVertex4i = GPA(g_hGLDLL, "glVertex4i" );
+ qglVertex4iv = dllVertex4iv = GPA(g_hGLDLL, "glVertex4iv" );
+ qglVertex4s = dllVertex4s = GPA(g_hGLDLL, "glVertex4s" );
+ qglVertex4sv = dllVertex4sv = GPA(g_hGLDLL, "glVertex4sv" );
+ qglVertexPointer = dllVertexPointer = GPA(g_hGLDLL, "glVertexPointer" );
+ qglViewport = dllViewport = GPA(g_hGLDLL, "glViewport" );
+
+ qwglCopyContext = GPA(g_hGLDLL, "wglCopyContext" );
+ qwglCreateContext = GPA(g_hGLDLL, "wglCreateContext" );
+ qwglCreateLayerContext = GPA(g_hGLDLL, "wglCreateLayerContext" );
+ qwglDeleteContext = GPA(g_hGLDLL, "wglDeleteContext" );
+ qwglDescribeLayerPlane = GPA(g_hGLDLL, "wglDescribeLayerPlane" );
+ qwglGetCurrentContext = GPA(g_hGLDLL, "wglGetCurrentContext" );
+ qwglGetCurrentDC = GPA(g_hGLDLL, "wglGetCurrentDC" );
+ qwglGetLayerPaletteEntries = GPA(g_hGLDLL, "wglGetLayerPaletteEntries" );
+ qwglGetProcAddress = GPA(g_hGLDLL, "wglGetProcAddress" );
+ qwglMakeCurrent = GPA(g_hGLDLL, "wglMakeCurrent" );
+ qwglRealizeLayerPalette = GPA(g_hGLDLL, "wglRealizeLayerPalette" );
+ qwglSetLayerPaletteEntries = GPA(g_hGLDLL, "wglSetLayerPaletteEntries" );
+ qwglShareLists = GPA(g_hGLDLL, "wglShareLists" );
+ qwglSwapLayerBuffers = GPA(g_hGLDLL, "wglSwapLayerBuffers" );
+ qwglUseFontBitmaps = GPA(g_hGLDLL, "wglUseFontBitmapsA" );
+ qwglUseFontOutlines = GPA(g_hGLDLL, "wglUseFontOutlinesA" );
+
+ qwglChoosePixelFormat = GPA(g_hGLDLL, "wglChoosePixelFormat" );
+ qwglDescribePixelFormat = GPA(g_hGLDLL, "wglDescribePixelFormat" );
+ qwglGetPixelFormat = GPA(g_hGLDLL, "wglGetPixelFormat" );
+ qwglSetPixelFormat = GPA(g_hGLDLL, "wglSetPixelFormat" );
+ qwglSwapBuffers = GPA(g_hGLDLL, "wglSwapBuffers" );
+
+ qwglSwapIntervalEXT = 0;
+ qglPointParameterfEXT = 0;
+ qglPointParameterfvEXT = 0;
+ qglColorTableEXT = 0;
+ qglSelectTextureSGIS = 0;
+ qglMTexCoord2fSGIS = 0;
+
+ return true;
+}
+
+#pragma warning (default : 4113 4133 4047 )
+
+
+
diff --git a/q3radiant/RADBSP.CPP b/q3radiant/RADBSP.CPP
new file mode 100755
index 0000000..fb7c3d3
--- /dev/null
+++ b/q3radiant/RADBSP.CPP
@@ -0,0 +1,77 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+// #includes follow...
+//-----------------------------------------------------------------------------
+//
+#include "StdAfx.h" // For: Precompiled Headers
+//
+//-----------------------------------------------------------------------------
+// #defines, consts, etc follow...
+//-----------------------------------------------------------------------------
+//
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+//
+//-----------------------------------------------------------------------------
+// Implementation follows...
+//-----------------------------------------------------------------------------
+//
+
+// msvc 5.xx does not do well optimizing this code
+#pragma optimize("",off)
+
+HINSTANCE g_hQBSPDLL = NULL;
+
+typedef void (WINAPI* PFN_QBSP)(char*, HWND, const char*);
+
+void RunTools(char* pCommandLine, HWND hwnd, const char* pPAKFile)
+{
+ static PFN_QBSP lpfnQBSP = NULL;
+ if (g_hQBSPDLL == NULL)
+ g_hQBSPDLL = ::LoadLibrary("qbspdll.dll");
+ else
+ {
+ ::FreeLibrary(g_hQBSPDLL);
+ g_hQBSPDLL = ::LoadLibrary("qbspdll.dll");
+ lpfnQBSP = NULL;
+ }
+ if (g_hQBSPDLL != NULL)
+ {
+ if (lpfnQBSP == NULL && g_hQBSPDLL != NULL)
+ {
+ FARPROC pFunction = ::GetProcAddress(g_hQBSPDLL, "FullProcess");
+ lpfnQBSP = reinterpret_cast<PFN_QBSP>(pFunction);
+ }
+ if (lpfnQBSP != NULL)
+ {
+ (*lpfnQBSP)(pCommandLine, hwnd, pPAKFile);
+ }
+ }
+}
+
+
+#pragma optimize("",on)
+
diff --git a/q3radiant/RADEditView.cpp b/q3radiant/RADEditView.cpp
new file mode 100755
index 0000000..789bf0f
--- /dev/null
+++ b/q3radiant/RADEditView.cpp
@@ -0,0 +1,84 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RADEditView.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "RADEditView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditView
+
+IMPLEMENT_DYNCREATE(CRADEditView, CEditView)
+
+CRADEditView::CRADEditView()
+{
+}
+
+CRADEditView::~CRADEditView()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CRADEditView, CEditView)
+ //{{AFX_MSG_MAP(CRADEditView)
+ ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditView drawing
+
+void CRADEditView::OnDraw(CDC* pDC)
+{
+ CDocument* pDoc = GetDocument();
+ // TODO: add draw code here
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditView diagnostics
+
+#ifdef _DEBUG
+void CRADEditView::AssertValid() const
+{
+ CEditView::AssertValid();
+}
+
+void CRADEditView::Dump(CDumpContext& dc) const
+{
+ CEditView::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditView message handlers
+
+void CRADEditView::OnChange()
+{
+}
diff --git a/q3radiant/RADEditView.h b/q3radiant/RADEditView.h
new file mode 100755
index 0000000..53255a5
--- /dev/null
+++ b/q3radiant/RADEditView.h
@@ -0,0 +1,75 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_RADEDITVIEW_H__DC829123_812D_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_RADEDITVIEW_H__DC829123_812D_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// RADEditView.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditView view
+
+class CRADEditView : public CEditView
+{
+public:
+ CRADEditView(); // protected constructor used by dynamic creation
+ DECLARE_DYNCREATE(CRADEditView)
+protected:
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRADEditView)
+ protected:
+ virtual void OnDraw(CDC* pDC); // overridden to draw this view
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ virtual ~CRADEditView();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CRADEditView)
+ afx_msg void OnChange();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_RADEDITVIEW_H__DC829123_812D_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/RADEditWnd.cpp b/q3radiant/RADEditWnd.cpp
new file mode 100755
index 0000000..0e8ab1a
--- /dev/null
+++ b/q3radiant/RADEditWnd.cpp
@@ -0,0 +1,75 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RADEditWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "RADEditWnd.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditWnd
+
+CRADEditWnd::CRADEditWnd()
+{
+}
+
+CRADEditWnd::~CRADEditWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CRADEditWnd, CWnd)
+ //{{AFX_MSG_MAP(CRADEditWnd)
+ ON_WM_CREATE()
+ ON_WM_SIZE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditWnd message handlers
+
+int CRADEditWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ CRect rctClient;
+ GetClientRect(rctClient);
+ m_wndEdit.Create(WS_CHILD | WS_VSCROLL | ES_AUTOHSCROLL | ES_MULTILINE | WS_VISIBLE, rctClient, this, 101);
+ return 0;
+}
+
+void CRADEditWnd::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+ CRect rctClient;
+ GetClientRect(rctClient);
+ m_wndEdit.SetWindowPos(NULL, rctClient.left, rctClient.top, rctClient.Width(), rctClient.Height(), SWP_SHOWWINDOW);
+}
diff --git a/q3radiant/RADEditWnd.h b/q3radiant/RADEditWnd.h
new file mode 100755
index 0000000..663c552
--- /dev/null
+++ b/q3radiant/RADEditWnd.h
@@ -0,0 +1,73 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_RADEDITWND_H__DC829124_812D_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_RADEDITWND_H__DC829124_812D_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// RADEditWnd.h : header file
+//
+
+#include "EditWnd.h"
+/////////////////////////////////////////////////////////////////////////////
+// CRADEditWnd window
+
+class CRADEditWnd : public CWnd
+{
+// Construction
+public:
+ CRADEditWnd();
+
+// Attributes
+public:
+ CEdit* GetEditWnd() {return dynamic_cast<CEdit*>(&m_wndEdit); };
+protected:
+ CEditWnd m_wndEdit;
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRADEditWnd)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CRADEditWnd();
+
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CRADEditWnd)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_RADEDITWND_H__DC829124_812D_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/RADKEYS.INI b/q3radiant/RADKEYS.INI
new file mode 100755
index 0000000..f5506ec
--- /dev/null
+++ b/q3radiant/RADKEYS.INI
@@ -0,0 +1,67 @@
+; command mapping for QERadiant
+;
+; syntax is as follows
+; Command name = keystroke
+;
+; use +alt, shift or ctrl to modify the keys (you can combine them)
+; i.e.
+; EntityColor = k+ctrl
+;
+; the special keys are as follows
+;
+; UP = Cursor up
+; DOWN = Cursor down
+; LEFT = Cursor left
+; RIGHT = Cursor right
+; SPACE = space
+; BACKSPACE = back space
+; ESCAPE = escape
+; END = end
+; INSERT = insert
+; DELETE = delete
+; PAGEUP = page up
+; PAGEDOWN = page down
+; TAB = tab
+; RETURN = return (enter)
+; F1..F2 = f1 .. f12
+
+
+[Commands]
+EntityColor = K
+CameraForward = UP
+CameraBack = DOWN
+CameraLeft = LEFT
+CameraRight = RIGHT
+CameraUp = D
+CameraDown = C
+CameraAngleUp = A
+CameraAngleDown = Z
+CameraStrafeRight = ,
+CameraStrafeLeft = .
+ToggleGrid = 0
+SetGrid1 = 1
+SetGrid2 = 2
+SetGrid4 = 3
+SetGrid8 = 4
+SetGrid16 = 5
+SetGrid32 = 6
+SetGrid64 = 7
+DragEdges = E
+DragVertices = V
+ViewEntityInfo = N
+ViewConsole = O
+ViewTextures = T
+SurfaceInspector = S
+CloneSelection = SPACE
+DeleteSelection = BACKSPACE
+UnSelectSelection = ESCAPE
+CenterView = END
+ZoomOut = INSERT
+ZoomIn = DELETE
+UpFloor = PAGEUP
+DownFloor = PAGEDOWN
+ToggleClipper = X
+ToggleRealtime = R
+EntityList = L
+MapInfo = M
+
diff --git a/q3radiant/Radiant.clw b/q3radiant/Radiant.clw
new file mode 100755
index 0000000..bba578e
--- /dev/null
+++ b/q3radiant/Radiant.clw
@@ -0,0 +1,1957 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+LastClass=CRadiantApp
+LastTemplate=CDialog
+NewFileInclude1=#include "stdafx.h"
+NewFileInclude2=#include "Radiant.h"
+LastPage=0
+
+ClassCount=40
+Class1=CRadiantApp
+Class2=CRadiantDoc
+Class3=CRadiantView
+Class4=CMainFrame
+Class7=CZWnd
+Class8=CCamWnd
+
+ResourceCount=56
+Resource1=IDR_MENU_DROP
+Resource2=IDD_DLG_SCRIPTS
+Resource3=IDD_ENTITY
+Resource8=IDD_DLG_ENTITYLIST
+Resource9=IDR_MENU1
+Resource10=IDD_GROUPBAR
+Resource11=IDD_PLAYWAVE
+Resource12=IDD_GAMMA
+Resource13=IDD_DLG_GROUP
+Resource4=IDD_DIALOG_NEWPATCH
+Resource5=IDR_POPUP_VIEW
+Resource6=IDR_POPUP_GROUP
+Resource7=IDD_DLG_INFORMATION
+Class9=CXYWnd
+Class10=CTexWnd
+Class11=CEditWnd
+Class5=CAboutDlg
+Class6=CChildFrame
+Resource14=IDR_MINIACCEL
+Class12=CLstToolBar
+Resource15=IDR_MENU11
+Resource16=IDR_TOOLBAR_ADVANCED
+Class13=CRotateDlg
+Class14=CPrefsDlg
+Class15=CRADEditView
+Class16=CRADEditWnd
+Resource17=IDD_TEXTUREBAR
+Resource18=IDD_SURFACE
+Class17=CMapInfo
+Resource19=IDD_DIALOG_CAP
+Class18=CEntityListDlg
+Resource20=IDR_RADIANTYPE
+Class19=CScriptDlg
+Resource21=IDR_POPUP_TEXTURE
+Class20=CNewProjDlg
+Resource22=IDR_TOOLBAR_SCALELOCK
+Class21=CCommandsDlg
+Resource23=IDD_DIALOG2
+Resource24=IDR_MAINFRAME
+Resource25=IDR_POPUP_SELECTION
+Class22=CScaleDialog
+Class23=CTexEdit
+Class24=CSurfaceDlg
+Class25=CFindTextureDlg
+Resource26=IDD_DIALOG_PATCH
+Resource27=IDD_TEXLIST
+Class26=CBSInput
+Resource28=IDD_DIALOG_SCALE
+Class27=CDialogInfo
+Resource29=IDD_FINDTEXTURE
+Resource30=IDR_ACCEL_SURFACE
+Resource31=IDD_DIALOG_TEXTURELIST
+Resource32="IDD_ADDCMD"
+Resource33="IDD_PROJECT"
+Resource34=IDD_NEWNAME
+Resource35=IDD_DIALOG_THICKEN
+Class28=CTextureBar
+Resource36=IDD_ABOUT
+Resource37=IDD_DIALOG_TEXTURELAYOUT
+Resource38=IDR_TOOLBAR1
+Resource39=IDR_SHADERFRAME
+Class29=CDialogTextures
+Resource40=IDD_FINDBRUSH
+Class30=CPatchDensityDlg
+Resource41=IDD_DIALOG_INPUT
+Class31=CTextureLayout
+Resource42=IDD_PROJECT
+Class32=CCapDialog
+Resource43=IDD_DLG_COMMANDLIST
+Class33=CDialogThick
+Resource44=IDD_DLG_NEWPROJECT
+Class34=CShaderEdit
+Class35=CShaderFrame
+Resource45=IDD_DLG_MAPINFO
+Resource46="IDR_SHADERFRAME"
+Resource47="IDR_SHADERTYPE"
+Resource48=IDR_POPUP_ENTITY
+Class36=CPatchDialog
+Class37=CWaveOpen
+Resource49=IDD_DLG_PREFS
+Resource50=IDD_DIALOG_STAIRS
+Resource51=IDD_ROTATE
+Resource52=IDD_ADDCMD
+Class38=CGroupBar
+Resource53=IDR_ACCELERATOR1
+Class39=CGroupDlg
+Resource54=IDD_SIDES
+Resource55=IDD_DIALOG_FINDREPLACE
+Class40=CNameDlg
+Resource56=IDR_MENU_QUAKE3
+
+[CLS:CRadiantApp]
+Type=0
+HeaderFile=Radiant.h
+ImplementationFile=Radiant.cpp
+Filter=N
+LastObject=ID_HELP
+BaseClass=CWinApp
+VirtualFilter=AC
+
+[CLS:CRadiantDoc]
+Type=0
+HeaderFile=RadiantDoc.h
+ImplementationFile=RadiantDoc.cpp
+Filter=N
+LastObject=CRadiantDoc
+
+[CLS:CRadiantView]
+Type=0
+HeaderFile=RadiantView.h
+ImplementationFile=RadiantView.cpp
+Filter=C
+
+[CLS:CMainFrame]
+Type=0
+HeaderFile=MainFrm.h
+ImplementationFile=MainFrm.cpp
+Filter=W
+BaseClass=CFrameWnd
+VirtualFilter=fWC
+LastObject=CMainFrame
+
+
+[CLS:CChildFrame]
+Type=0
+HeaderFile=ChildFrm.h
+ImplementationFile=ChildFrm.cpp
+Filter=M
+
+[CLS:CAboutDlg]
+Type=0
+HeaderFile=Radiant.cpp
+ImplementationFile=Radiant.cpp
+Filter=D
+
+[MNU:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_PRINT_SETUP
+Command4=ID_FILE_MRU_FILE1
+Command5=ID_APP_EXIT
+Command6=ID_VIEW_TOOLBAR
+Command7=ID_VIEW_STATUS_BAR
+Command8=ID_APP_ABOUT
+CommandCount=8
+
+[TB:IDR_MAINFRAME]
+Type=1
+Class=CMainFrame
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_EDIT_CUT
+Command5=ID_EDIT_COPY
+Command6=ID_EDIT_PASTE
+Command7=ID_FILE_PRINT
+Command8=ID_APP_ABOUT
+CommandCount=8
+
+[MNU:IDR_RADIANTYPE]
+Type=1
+Class=CRadiantView
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_CLOSE
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVE_AS
+Command6=ID_FILE_PRINT
+Command7=ID_FILE_PRINT_PREVIEW
+Command8=ID_FILE_PRINT_SETUP
+Command9=ID_FILE_MRU_FILE1
+Command10=ID_APP_EXIT
+Command11=ID_EDIT_UNDO
+Command12=ID_EDIT_CUT
+Command13=ID_EDIT_COPY
+Command14=ID_EDIT_PASTE
+Command15=ID_VIEW_TOOLBAR
+Command16=ID_VIEW_STATUS_BAR
+Command17=ID_WINDOW_NEW
+Command18=ID_WINDOW_CASCADE
+Command19=ID_WINDOW_TILE_HORZ
+Command20=ID_WINDOW_ARRANGE
+Command21=ID_APP_ABOUT
+CommandCount=21
+
+[TB:IDR_TOOLBAR1]
+Type=1
+Class=?
+Command1=ID_FILE_OPEN
+Command2=ID_FILE_SAVE
+Command3=ID_BRUSH_FLIPX
+Command4=ID_BRUSH_ROTATEX
+Command5=ID_BRUSH_FLIPY
+Command6=ID_BRUSH_ROTATEY
+Command7=ID_BRUSH_FLIPZ
+Command8=ID_BRUSH_ROTATEZ
+Command9=ID_POPUP_SELECTION
+Command10=ID_SELECTION_CSGSUBTRACT
+Command11=ID_SELECTION_MAKEHOLLOW
+Command12=ID_VIEW_CHANGE
+Command13=ID_TEXTURES_POPUP
+Command14=ID_VIEW_CAMERATOGGLE
+Command15=ID_VIEW_CAMERAUPDATE
+Command16=ID_VIEW_CUBICCLIPPING
+Command17=ID_VIEW_ENTITY
+Command18=ID_VIEW_CLIPPER
+Command19=ID_SELECT_MOUSEROTATE
+Command20=ID_SELECT_MOUSESCALE
+Command21=ID_SCALELOCKX
+Command22=ID_SCALELOCKY
+Command23=ID_SCALELOCKZ
+CommandCount=23
+
+[DLG:IDD_FINDTEXTURE]
+Type=1
+Class=?
+ControlCount=3
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_EDIT1,edit,1350631552
+
+[DLG:IDD_ENTITY]
+Type=1
+Class=?
+ControlCount=35
+Control1=IDC_E_LIST,listbox,1352729859
+Control2=IDC_E_COMMENT,edit,1352730628
+Control3=IDC_E_135,button,1342242816
+Control4=IDC_E_180,button,1342242816
+Control5=IDC_E_225,button,1342242816
+Control6=IDC_E_270,button,1342242816
+Control7=IDC_E_90,button,1342242816
+Control8=IDC_E_45,button,1342242816
+Control9=IDC_E_0,button,1342242816
+Control10=IDC_E_315,button,1342242816
+Control11=IDC_E_UP,button,1342242816
+Control12=IDC_E_DOWN,button,1342242816
+Control13=IDC_CHECK1,button,1476460547
+Control14=IDC_CHECK2,button,1476460547
+Control15=IDC_CHECK3,button,1476460547
+Control16=IDC_CHECK4,button,1476460547
+Control17=IDC_CHECK5,button,1476460547
+Control18=IDC_CHECK6,button,1476460547
+Control19=IDC_CHECK7,button,1476460547
+Control20=IDC_CHECK8,button,1476460547
+Control21=IDC_CHECK9,button,1342242819
+Control22=IDC_CHECK10,button,1342242819
+Control23=IDC_CHECK11,button,1342242819
+Control24=IDC_CHECK12,button,1342242819
+Control25=IDC_E_PROPS,listbox,1352729987
+Control26=IDC_E_DELPROP,button,1342242816
+Control27=IDC_E_STATUS,edit,1353779396
+Control28=IDC_STATIC_KEY,static,1342308352
+Control29=IDC_STATIC_VALUE,static,1342308352
+Control30=IDC_E_KEY_FIELD,edit,1350631552
+Control31=IDC_E_VALUE_FIELD,edit,1350631552
+Control32=IDC_BTN_HIDE,button,1342242816
+Control33=IDC_BTN_ASSIGNSOUND,button,1342242816
+Control34=IDC_BTN_ASSIGNMODEL,button,1342242816
+Control35=IDC_TAB_MODE,SysTabControl32,1350565890
+
+[DLG:IDD_GAMMA]
+Type=1
+Class=?
+ControlCount=4
+Control1=IDC_G_EDIT,edit,1350631552
+Control2=IDOK,button,1342242817
+Control3=IDCANCEL,button,1342242816
+Control4=IDC_STATIC,static,1342308352
+
+[DLG:IDD_FINDBRUSH]
+Type=1
+Class=?
+ControlCount=6
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_FIND_ENTITY,edit,1350631552
+Control4=IDC_FIND_BRUSH,edit,1350631552
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+
+[DLG:IDD_ROTATE]
+Type=1
+Class=CRotateDlg
+ControlCount=12
+Control1=IDC_ROTX,edit,1350631552
+Control2=IDC_SPIN1,msctls_updown32,1342177335
+Control3=IDC_ROTY,edit,1350631552
+Control4=IDC_SPIN2,msctls_updown32,1342177335
+Control5=IDC_ROTZ,edit,1350631552
+Control6=IDC_SPIN3,msctls_updown32,1342177335
+Control7=IDOK,button,1342242817
+Control8=IDCANCEL,button,1342242816
+Control9=ID_APPLY,button,1342242816
+Control10=IDC_STATIC,static,1342308354
+Control11=IDC_STATIC,static,1342308354
+Control12=IDC_STATIC,static,1342308354
+
+[DLG:IDD_SIDES]
+Type=1
+Class=?
+ControlCount=4
+Control1=IDC_SIDES,edit,1350631552
+Control2=IDOK,button,1342242817
+Control3=IDCANCEL,button,1342242816
+Control4=IDC_STATIC,static,1342308352
+
+[DLG:IDD_ABOUT]
+Type=1
+Class=?
+ControlCount=9
+Control1=IDOK,button,1342242817
+Control2=IDC_STATIC,static,1350572558
+Control3=IDC_STATIC,button,1342177287
+Control4=IDC_ABOUT_GLVENDOR,static,1342308352
+Control5=IDC_ABOUT_GLVERSION,static,1342308352
+Control6=IDC_ABOUT_GLRENDERER,static,1342308352
+Control7=IDC_STATIC,button,1342177287
+Control8=IDC_STATIC,static,1342308364
+Control9=IDC_ABOUT_GLEXTENSIONS,edit,1476462660
+
+[DLG:IDD_SURFACE]
+Type=1
+Class=CSurfaceDlg
+ControlCount=103
+Control1=IDC_TEXTURE,edit,1350631552
+Control2=IDC_HSHIFT,edit,1350631552
+Control3=IDC_SPIN_HSHIFT,msctls_updown32,1342177332
+Control4=IDC_VSHIFT,edit,1350631552
+Control5=IDC_SPIN_VSHIFT,msctls_updown32,1342177332
+Control6=IDC_HSCALE,edit,1350631552
+Control7=IDC_SPIN_HSCALE,msctls_updown32,1342177332
+Control8=IDC_VSCALE,edit,1350631552
+Control9=IDC_SPIN_VSCALE,msctls_updown32,1342177332
+Control10=IDC_ROTATE,edit,1350631552
+Control11=IDC_SPIN_ROTATE,msctls_updown32,1342177332
+Control12=IDC_VALUE,edit,1350631552
+Control13=IDC_BTN_PATCHDETAILS,button,1342242816
+Control14=IDC_CHECK1,button,1342242819
+Control15=IDC_CHECK2,button,1342242819
+Control16=IDC_CHECK3,button,1342242819
+Control17=IDC_CHECK4,button,1342242819
+Control18=IDC_CHECK5,button,1342242819
+Control19=IDC_CHECK6,button,1342242819
+Control20=IDC_CHECK7,button,1342242819
+Control21=IDC_CHECK8,button,1342242819
+Control22=IDC_CHECK9,button,1342242819
+Control23=IDC_CHECK10,button,1342242819
+Control24=IDC_CHECK11,button,1342242819
+Control25=IDC_CHECK12,button,1342242819
+Control26=IDC_CHECK13,button,1342242819
+Control27=IDC_CHECK14,button,1342242819
+Control28=IDC_CHECK15,button,1342242819
+Control29=IDC_CHECK16,button,1342242819
+Control30=IDC_CHECK17,button,1342242819
+Control31=IDC_CHECK18,button,1342242819
+Control32=IDC_CHECK19,button,1342242819
+Control33=IDC_CHECK20,button,1342242819
+Control34=IDC_CHECK21,button,1342242819
+Control35=IDC_CHECK22,button,1342242819
+Control36=IDC_CHECK23,button,1342242819
+Control37=IDC_CHECK24,button,1342242819
+Control38=IDC_CHECK25,button,1342242819
+Control39=IDC_CHECK26,button,1342242819
+Control40=IDC_CHECK27,button,1342242819
+Control41=IDC_CHECK28,button,1342242819
+Control42=IDC_CHECK29,button,1342242819
+Control43=IDC_CHECK30,button,1342242819
+Control44=IDC_CHECK31,button,1342242819
+Control45=IDC_CHECK32,button,1342242819
+Control46=IDC_CHECK33,button,1342242819
+Control47=IDC_CHECK34,button,1342242819
+Control48=IDC_CHECK35,button,1342242819
+Control49=IDC_CHECK36,button,1342242819
+Control50=IDC_CHECK37,button,1342242819
+Control51=IDC_CHECK38,button,1342242819
+Control52=IDC_CHECK39,button,1342242819
+Control53=IDC_CHECK40,button,1342242819
+Control54=IDC_CHECK41,button,1342242819
+Control55=IDC_CHECK42,button,1342242819
+Control56=IDC_CHECK43,button,1342242819
+Control57=IDC_CHECK44,button,1342242819
+Control58=IDC_CHECK45,button,1342242819
+Control59=IDC_CHECK46,button,1342242819
+Control60=IDC_CHECK47,button,1342242819
+Control61=IDC_CHECK48,button,1342242819
+Control62=IDC_CHECK49,button,1342242819
+Control63=IDC_CHECK50,button,1342242819
+Control64=IDC_CHECK51,button,1342242819
+Control65=IDC_CHECK52,button,1342242819
+Control66=IDC_CHECK53,button,1342242819
+Control67=IDC_CHECK54,button,1342242819
+Control68=IDC_CHECK55,button,1342242819
+Control69=IDC_CHECK56,button,1342242819
+Control70=IDC_CHECK57,button,1342242819
+Control71=IDC_CHECK58,button,1342242819
+Control72=IDC_CHECK59,button,1342242819
+Control73=IDC_CHECK60,button,1342242819
+Control74=IDC_CHECK61,button,1342242819
+Control75=IDC_CHECK62,button,1342242819
+Control76=IDC_CHECK63,button,1342242819
+Control77=IDC_CHECK64,button,1342242819
+Control78=IDOK,button,1342242817
+Control79=IDAPPLY,button,1342242816
+Control80=ID_BTN_CANCEL,button,1342242816
+Control81=IDC_STATIC,static,1342308354
+Control82=IDC_STATIC,static,1342308354
+Control83=IDC_STATIC,static,1342308354
+Control84=IDC_STATIC,static,1342308354
+Control85=IDC_STATIC,static,1342308354
+Control86=IDC_STATIC,static,1342308352
+Control87=IDC_STATIC,button,1342177287
+Control88=IDC_STATIC,button,1342177287
+Control89=IDC_STATIC,static,1342308354
+Control90=IDC_STATIC,button,1342177287
+Control91=IDC_BTN_PATCHRESET,button,1342242816
+Control92=IDC_BTN_PATCHNATURAL,button,1342242816
+Control93=IDC_BTN_PATCHFIT,button,1342242816
+Control94=IDC_STATIC,static,1342308352
+Control95=IDC_STATIC,static,1342308352
+Control96=IDC_BTN_AXIAL,button,1342242816
+Control97=IDC_BTN_FACEFIT,button,1342242816
+Control98=IDC_EDIT_WIDTH,edit,1350639744
+Control99=IDC_SPIN_WIDTH,msctls_updown32,1342177335
+Control100=IDC_EDIT_HEIGHT,edit,1350639744
+Control101=IDC_SPIN_HEIGHT,msctls_updown32,1342177334
+Control102=IDC_STATIC,static,1342308352
+Control103=IDC_STATIC,static,1342308352
+
+[CLS:CZWnd]
+Type=0
+HeaderFile=ZWnd.h
+ImplementationFile=ZWnd.cpp
+BaseClass=CWnd
+Filter=W
+VirtualFilter=WC
+
+[CLS:CCamWnd]
+Type=0
+HeaderFile=CamWnd.h
+ImplementationFile=CamWnd.cpp
+BaseClass=CWnd
+Filter=W
+VirtualFilter=WC
+LastObject=CCamWnd
+
+[CLS:CXYWnd]
+Type=0
+HeaderFile=XYWnd.h
+ImplementationFile=XYWnd.cpp
+BaseClass=CWnd
+Filter=W
+VirtualFilter=WC
+LastObject=ID_SELECT_MOUSEROTATE
+
+[CLS:CTexWnd]
+Type=0
+HeaderFile=TexWnd.h
+ImplementationFile=TexWnd.cpp
+BaseClass=CWnd
+Filter=W
+VirtualFilter=WC
+LastObject=CTexWnd
+
+[CLS:CEditWnd]
+Type=0
+HeaderFile=EditWnd.h
+ImplementationFile=EditWnd.cpp
+BaseClass=CEdit
+Filter=W
+VirtualFilter=WC
+
+[CLS:CLstToolBar]
+Type=0
+HeaderFile=LstToolBar.h
+ImplementationFile=LstToolBar.cpp
+BaseClass=CToolBar
+Filter=W
+LastObject=CLstToolBar
+
+[MNU:IDR_POPUP_TEXTURE]
+Type=1
+Class=?
+Command1=ID_TEXTURES_WIREFRAME
+Command2=ID_TEXTURES_FLATSHADE
+Command3=ID_VIEW_NEAREST
+Command4=ID_VIEW_NEARESTMIPMAP
+Command5=ID_VIEW_LINEAR
+Command6=ID_VIEW_BILINEAR
+Command7=ID_VIEW_BILINEARMIPMAP
+Command8=ID_VIEW_TRILINEAR
+CommandCount=8
+
+[MNU:IDR_POPUP_SELECTION]
+Type=1
+Class=?
+Command1=ID_SELECTION_SELECTCOMPLETETALL
+Command2=ID_SELECTION_SELECTTOUCHING
+Command3=ID_SELECTION_SELECTPARTIALTALL
+Command4=ID_SELECTION_SELECTINSIDE
+CommandCount=4
+
+[MNU:IDR_POPUP_VIEW]
+Type=1
+Class=?
+Command1=ID_VIEW_XY
+Command2=ID_VIEW_SIDE
+Command3=ID_VIEW_FRONT
+CommandCount=3
+
+[CLS:CRotateDlg]
+Type=0
+HeaderFile=RotateDlg.h
+ImplementationFile=RotateDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CRotateDlg
+
+[DLG:IDD_DLG_PREFS]
+Type=1
+Class=CPrefsDlg
+ControlCount=81
+Control1=IDC_COMBO_WHATGAME,combobox,1344340226
+Control2=IDC_RADIO_MOUSE,button,1342308361
+Control3=IDC_RADIO2,button,1342177289
+Control4=IDC_RADIO_VIEWTYPE,button,1342308361
+Control5=IDC_RADIO_VIEWTYPE2,button,1342177289
+Control6=IDC_RADIO_VIEWTYPE3,button,1342177289
+Control7=IDC_RADIO_VIEWTYPE4,button,1342177289
+Control8=IDC_CHECK_SGIOPENGL,button,1342242819
+Control9=IDC_CHECK_BUGGYICD,button,1342242819
+Control10=IDC_CHECK_DISPLAYLISTS,button,1342242819
+Control11=IDC_CHECK_NOSTIPPLE,button,1342242819
+Control12=IDC_SLIDER_CAMSPEED,msctls_trackbar32,1342242816
+Control13=IDC_CHECK_CAMXYUPDATE,button,1342251011
+Control14=IDC_CHECK_QE4PAINTING,button,1342242819
+Control15=IDC_SLIDER_TEXTUREQUALITY,msctls_trackbar32,1342242817
+Control16=IDC_CHECK_TEXTURETOOLBAR,button,1342242819
+Control17=IDC_CHECK_TEXTURESCROLLBAR,button,1342242819
+Control18=IDC_CHECK_TEXTUREWINDOW,button,1342242819
+Control19=IDC_CHECK_RIGHTCLICK,button,1342242819
+Control20=IDC_CHECK_FACE,button,1342242819
+Control21=IDC_EDIT_ROTATION,edit,1350631552
+Control22=IDC_CHECK_ALTDRAG,button,1342242819
+Control23=IDC_CHECK_SNAPT,button,1342242819
+Control24=IDC_CHECK_MOUSECHASE,button,1342242819
+Control25=IDC_CHECK_WIDETOOLBAR,button,1342242819
+Control26=IDC_CHECK_LIGHTDRAW,button,1342242819
+Control27=IDC_CHECK_SIZEPAINT,button,1342242819
+Control28=IDC_CHECK_HICOLOR,button,1342242819
+Control29=IDC_STATIC,static,1342308352
+Control30=IDC_COMBO_SHADERS,combobox,1344339971
+Control31=IDC_EDIT_QUAKE2,edit,1350631552
+Control32=IDC_BTN_BROWSE,button,1342242816
+Control33=IDC_CHECK_INTERNALBSP,button,1342242819
+Control34=IDC_CHECK_NOCLAMP,button,1342242819
+Control35=IDC_CHECK_SNAPSHOTS,button,1342242819
+Control36=IDC_CHECK_SETGAME,button,1342242819
+Control37=IDC_CHECK_RUNQUAKE,button,1342242819
+Control38=IDC_CHECK_LOADLAST,button,1342242819
+Control39=IDC_CHECK_LOADLASTMAP,button,1342242819
+Control40=IDC_CHECK_AUTOSAVE,button,1342242819
+Control41=IDC_EDIT_AUTOSAVE,edit,1350639744
+Control42=IDC_SPIN_AUTOSAVE,msctls_updown32,1342177335
+Control43=IDC_STATIC,static,1342308352
+Control44=IDC_EDIT_STATUSPOINTSIZE,edit,1350631552
+Control45=IDC_SPIN_POINTSIZE,msctls_updown32,1342177335
+Control46=IDC_STATIC,static,1342308352
+Control47=IDC_EDIT_UNDOLEVELS,edit,1350631552
+Control48=IDC_SPIN_UNDO,msctls_updown32,1342177335
+Control49=IDC_CHECK_PAK,button,1342242819
+Control50=IDC_EDIT_PAKFILE,edit,1350631552
+Control51=IDC_BTN_BROWSEPAK,button,1342242816
+Control52=IDC_EDIT_PREFABPATH,edit,1350631552
+Control53=IDC_BTN_BROWSEPREFAB,button,1342242816
+Control54=IDC_EDIT_USERPATH,edit,1350631552
+Control55=IDC_BTN_BROWSEUSERINI,button,1342242816
+Control56=IDOK,button,1342242817
+Control57=IDCANCEL,button,1342242816
+Control58=IDC_CHECK_DLLENTITIES,button,1208034307
+Control59=IDC_CHECK_FACECOLOR,button,1208025091
+Control60=IDC_STATIC,static,1342308352
+Control61=IDC_CHECK_VERTEX,button,1208025091
+Control62=IDC_STATIC,button,1342177287
+Control63=IDC_STATIC,button,1342177287
+Control64=IDC_STATIC,button,1342177287
+Control65=IDB_VIEWDEFAULT,static,1342177294
+Control66=IDB_VIEWDEFAULT2,static,1342177294
+Control67=IDB_VIEWDEFAULT3,static,1342177294
+Control68=IDC_STATIC,button,1342177287
+Control69=IDB_VIEWDEFAULT_Z,static,1342177294
+Control70=IDC_STATIC,static,1342308352
+Control71=IDC_STATIC,static,1342308352
+Control72=IDC_STATIC,button,1342177287
+Control73=IDC_STATIC,static,1342308352
+Control74=IDC_STATIC,button,1342177287
+Control75=IDC_STATIC,static,1342308352
+Control76=IDC_STATIC,static,1342308352
+Control77=IDC_CHECK_USESHADERS,button,1208025091
+Control78=IDC_STATIC,button,1342177287
+Control79=IDC_STATIC,static,1342308352
+Control80=IDC_STATIC,static,1342308352
+Control81=IDC_STATIC,static,1342308352
+
+[CLS:CPrefsDlg]
+Type=0
+HeaderFile=PrefsDlg.h
+ImplementationFile=PrefsDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=IDC_SPIN_POINTSIZE
+VirtualFilter=dWC
+
+[CLS:CRADEditView]
+Type=0
+HeaderFile=RADEditView.h
+ImplementationFile=RADEditView.cpp
+BaseClass=CEditView
+Filter=C
+VirtualFilter=VWC
+
+[CLS:CRADEditWnd]
+Type=0
+HeaderFile=RADEditWnd.h
+ImplementationFile=RADEditWnd.cpp
+BaseClass=CWnd
+Filter=W
+VirtualFilter=WC
+
+[ACL:IDR_ACCELERATOR1]
+Type=1
+Class=?
+Command1=ID_BRUSH_3SIDED
+Command2=ID_BRUSH_4SIDED
+Command3=ID_BRUSH_5SIDED
+Command4=ID_BRUSH_6SIDED
+Command5=ID_BRUSH_7SIDED
+Command6=ID_BRUSH_8SIDED
+Command7=ID_BRUSH_9SIDED
+Command8=ID_VIEW_SHOWDETAIL
+Command9=ID_SELECTION_CONNECT
+Command10=ID_MISC_NEXTLEAKSPOT
+Command11=ID_SELECTION_MAKE_DETAIL
+Command12=ID_FILE_OPEN
+Command13=ID_MISC_PREVIOUSLEAKSPOT
+Command14=ID_FILE_SAVE
+Command15=ID_VIEW_ZZOOMIN
+Command16=ID_VIEW_ZZOOMOUT
+Command17=ID_FILE_EXIT
+CommandCount=17
+
+[DLG:IDD_DLG_MAPINFO]
+Type=1
+Class=CMapInfo
+ControlCount=9
+Control1=IDOK,button,1342242817
+Control2=IDC_STATIC,static,1342308352
+Control3=IDC_EDIT_TOTALBRUSHES,edit,1350639746
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_EDIT_TOTALENTITIES,edit,1350639746
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_EDIT_NET,edit,1350639746
+Control8=IDC_LIST_ENTITIES,listbox,1352728963
+Control9=IDC_STATIC,static,1342308352
+
+[CLS:CMapInfo]
+Type=0
+HeaderFile=MapInfo.h
+ImplementationFile=MapInfo.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=ID_EDIT_MAPINFO
+VirtualFilter=dWC
+
+[ACL:IDR_MAINFRAME]
+Type=1
+Class=?
+Command1=ID_BRUSH_7SIDED
+Command2=ID_BRUSH_8SIDED
+Command3=ID_BRUSH_9SIDED
+Command4=ID_VIEW_SHOWDETAIL
+Command5=ID_SELECTION_CONNECT
+Command6=ID_MISC_NEXTLEAKSPOT
+Command7=ID_SELECTION_MAKE_DETAIL
+Command8=ID_FILE_OPEN
+Command9=ID_MISC_PREVIOUSLEAKSPOT
+Command10=ID_FILE_SAVE
+Command11=ID_VIEW_ZZOOMIN
+Command12=ID_SELECTION_SELECT_NUDGEDOWN
+Command13=ID_VIEW_ZZOOMOUT
+Command14=ID_FILE_EXIT
+CommandCount=14
+
+[DLG:IDD_DLG_ENTITYLIST]
+Type=1
+Class=CEntityListDlg
+ControlCount=4
+Control1=IDOK,button,1342242817
+Control2=IDC_TREE_ENTITY,SysTreeView32,1350631431
+Control3=IDSELECT,button,1342242817
+Control4=IDC_LIST_ENTITY,SysListView32,1350664709
+
+[CLS:CEntityListDlg]
+Type=0
+HeaderFile=EntityListDlg.h
+ImplementationFile=EntityListDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDC_LIST_ENTITY
+
+[DLG:IDD_DLG_SCRIPTS]
+Type=1
+Class=CScriptDlg
+ControlCount=6
+Control1=ID_NEW,button,1476460545
+Control2=IDOK,button,1342242816
+Control3=IDC_LIST_SCRIPTS,listbox,1352728835
+Control4=ID_EDIT,button,1476460545
+Control5=ID_RUN,button,1342242817
+Control6=IDC_STATIC,static,1342308352
+
+[CLS:CScriptDlg]
+Type=0
+HeaderFile=ScriptDlg.h
+ImplementationFile=ScriptDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDC_LIST_SCRIPTS
+
+[DLG:IDD_DLG_NEWPROJECT]
+Type=1
+Class=CNewProjDlg
+ControlCount=6
+Control1=IDC_EDIT_NAME,edit,1350631552
+Control2=IDOK,button,1342242817
+Control3=IDCANCEL,button,1342242816
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_CHECK1,button,1476460547
+
+[CLS:CNewProjDlg]
+Type=0
+HeaderFile=NewProjDlg.h
+ImplementationFile=NewProjDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CNewProjDlg
+VirtualFilter=dWC
+
+[DLG:IDD_DLG_COMMANDLIST]
+Type=1
+Class=CCommandsDlg
+ControlCount=2
+Control1=IDOK,button,1342242817
+Control2=IDC_LIST_COMMANDS,listbox,1352728963
+
+[CLS:CCommandsDlg]
+Type=0
+HeaderFile=CommandsDlg.h
+ImplementationFile=CommandsDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CCommandsDlg
+
+[MNU:IDR_MENU_DROP]
+Type=1
+Class=?
+Command1=ID_SELECTION_SELECTCOMPLETETALL
+Command2=ID_SELECTION_SELECTTOUCHING
+Command3=ID_SELECTION_SELECTPARTIALTALL
+Command4=ID_SELECTION_SELECTINSIDE
+Command5=ID_DROP_GROUP_ADDTO
+Command6=ID_DROP_GROUP_REMOVE
+Command7=ID_DROP_GROUP_NAME
+Command8=ID_DROP_GROUP_NEWGROUP
+Command9=ID_SELECTION_UNGROUPENTITY
+Command10=ID_SELECTION_MAKE_DETAIL
+Command11=ID_SELECTION_MAKE_STRUCTURAL
+CommandCount=11
+
+[ACL:IDR_ACCEL_SURFACE]
+Type=1
+Class=?
+Command1=ID_BYEBYE
+CommandCount=1
+
+[DLG:IDD_DIALOG_SCALE]
+Type=1
+Class=CScaleDialog
+ControlCount=8
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_EDIT_X,edit,1350631552
+Control7=IDC_EDIT_Y,edit,1350631552
+Control8=IDC_EDIT_Z,edit,1350631552
+
+[CLS:CScaleDialog]
+Type=0
+HeaderFile=ScaleDialog.h
+ImplementationFile=ScaleDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDOK
+
+[CLS:CTexEdit]
+Type=0
+HeaderFile=TexEdit.h
+ImplementationFile=TexEdit.cpp
+BaseClass=CEdit
+Filter=W
+VirtualFilter=WC
+LastObject=CTexEdit
+
+[CLS:CSurfaceDlg]
+Type=0
+HeaderFile=SurfaceDlg.h
+ImplementationFile=SurfaceDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CSurfaceDlg
+VirtualFilter=dWC
+
+[DLG:IDD_DIALOG_FINDREPLACE]
+Type=1
+Class=CFindTextureDlg
+ControlCount=10
+Control1=IDC_EDIT_FIND,edit,1350631552
+Control2=IDC_EDIT_REPLACE,edit,1350631552
+Control3=IDC_CHECK_SELECTED,button,1342242819
+Control4=IDC_CHECK_FORCE,button,1342242819
+Control5=IDOK,button,1342242817
+Control6=IDCANCEL,button,1342242816
+Control7=IDC_STATIC,static,1342308352
+Control8=IDC_STATIC,static,1342308352
+Control9=ID_BTN_APPLY,button,1342242817
+Control10=IDC_CHECK_LIVE,button,1342242819
+
+[CLS:CFindTextureDlg]
+Type=0
+HeaderFile=FindTextureDlg.h
+ImplementationFile=FindTextureDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CFindTextureDlg
+
+[DLG:IDD_DIALOG_STAIRS]
+Type=1
+Class=?
+ControlCount=6
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_EDIT_ROTATION,edit,1350631552
+
+[DLG:IDD_DIALOG_INPUT]
+Type=1
+Class=CBSInput
+ControlCount=12
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC_FIELD1,static,1342308352
+Control4=IDC_EDIT_FIELD1,edit,1350631552
+Control5=IDC_STATIC_FIELD2,static,1342308352
+Control6=IDC_EDIT_FIELD2,edit,1350631552
+Control7=IDC_STATIC_FIELD3,static,1342308352
+Control8=IDC_EDIT_FIELD3,edit,1350631552
+Control9=IDC_STATIC_FIELD4,static,1342308352
+Control10=IDC_EDIT_FIELD4,edit,1350631552
+Control11=IDC_STATIC_FIELD5,static,1342308352
+Control12=IDC_EDIT_FIELD5,edit,1350631552
+
+[CLS:CBSInput]
+Type=0
+HeaderFile=BSInput.h
+ImplementationFile=BSInput.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CBSInput
+
+[CLS:CDialogInfo]
+Type=0
+HeaderFile=DialogInfo.h
+ImplementationFile=DialogInfo.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=ID_SCALELOCKX
+
+[DLG:IDD_DLG_INFORMATION]
+Type=1
+Class=CDialogInfo
+ControlCount=1
+Control1=IDC_EDIT1,edit,1486946308
+
+[TB:IDR_TOOLBAR_SCALELOCK]
+Type=1
+Class=?
+Command1=ID_SCALELOCKX
+Command2=ID_SCALELOCKY
+Command3=ID_SCALELOCKZ
+CommandCount=3
+
+[DLG:"IDD_PROJECT"]
+Type=1
+ControlCount=20
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,button,1342177287
+Control4=IDC_PRJBASEPATH,edit,1350631552
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_PRJRSHCMD,edit,1350631552
+Control8=IDC_STATIC,static,1342308352
+Control9=IDC_PRJREMOTEBASE,edit,1350631552
+Control10=IDC_STATIC,static,1342308352
+Control11=IDC_PRJENTITYPATH,edit,1350631552
+Control12=IDC_STATIC,static,1342308352
+Control13=IDC_PRJTEXPATH,edit,1350631552
+Control14=IDC_STATIC,button,1342177287
+Control15=IDC_ADDCMD,button,1342242816
+Control16=IDC_CMD_LIST,listbox,1352728835
+Control17=IDC_REMCMD,button,1342242816
+Control18=IDC_STATIC,static,1342308352
+Control19=IDC_PRJMAPSPATH,edit,1350631552
+Control20=IDC_EDITCMD,button,1342242816
+
+[DLG:"IDD_ADDCMD"]
+Type=1
+ControlCount=6
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_CMDMENUTEXT,edit,1350631552
+Control4=IDC_CMDCOMMAND,edit,1350631552
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+
+[DLG:IDD_ADDCMD]
+Type=1
+Class=?
+ControlCount=6
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_CMDMENUTEXT,edit,1350631552
+Control4=IDC_CMDCOMMAND,edit,1350631552
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_STATIC,static,1342308352
+
+[DLG:IDD_PROJECT]
+Type=1
+Class=?
+ControlCount=22
+Control1=IDC_PRJBASEPATH,edit,1350631552
+Control2=IDC_PRJMAPSPATH,edit,1350631552
+Control3=IDC_PRJRSHCMD,edit,1350631552
+Control4=IDC_PRJREMOTEBASE,edit,1350631552
+Control5=IDC_PRJENTITYPATH,edit,1350631552
+Control6=IDC_PRJTEXPATH,edit,1350631552
+Control7=IDC_CMD_LIST,listbox,1352728835
+Control8=IDC_ADDCMD,button,1342242816
+Control9=IDC_EDITCMD,button,1342242816
+Control10=IDC_REMCMD,button,1342242816
+Control11=IDC_CHECK_BPRIMIT,button,1342242819
+Control12=IDOK,button,1342242817
+Control13=IDCANCEL,button,1342242816
+Control14=IDC_STATIC,button,1342177287
+Control15=IDC_STATIC,static,1342308352
+Control16=IDC_STATIC,static,1342308352
+Control17=IDC_STATIC,static,1342308352
+Control18=IDC_STATIC,static,1342308352
+Control19=IDC_STATIC,static,1342308352
+Control20=IDC_STATIC,button,1342177287
+Control21=IDC_STATIC,static,1342308352
+Control22=IDC_STATIC,button,1342177287
+
+[DLG:IDD_TEXTUREBAR]
+Type=1
+Class=CTextureBar
+ControlCount=17
+Control1=IDC_HSHIFT,edit,1350631552
+Control2=IDC_SPIN_HSHIFT,msctls_updown32,1342177332
+Control3=IDC_VSHIFT,edit,1350631552
+Control4=IDC_SPIN_VSHIFT,msctls_updown32,1342177332
+Control5=IDC_HSCALE,edit,1350631552
+Control6=IDC_SPIN_HSCALE,msctls_updown32,1342177332
+Control7=IDC_VSCALE,edit,1350631552
+Control8=IDC_SPIN_VSCALE,msctls_updown32,1342177332
+Control9=IDC_ROTATE,edit,1350631552
+Control10=IDC_SPIN_ROTATE,msctls_updown32,1342177332
+Control11=IDC_STATIC,static,1342308352
+Control12=IDC_STATIC,static,1342308352
+Control13=IDC_STATIC,static,1342308352
+Control14=IDC_STATIC,static,1342308352
+Control15=IDC_STATIC,static,1342308352
+Control16=IDC_BTN_APPLYTEXTURESTUFF,button,1073741825
+Control17=IDC_EDIT_ROTATEAMT,edit,1350631552
+
+[CLS:CTextureBar]
+Type=0
+HeaderFile=TextureBar.h
+ImplementationFile=TextureBar.cpp
+BaseClass=CDialogBar
+Filter=W
+VirtualFilter=dWC
+LastObject=CTextureBar
+
+[TB:IDR_TOOLBAR_ADVANCED]
+Type=1
+Class=?
+Command1=ID_FILE_OPEN
+Command2=ID_FILE_SAVE
+Command3=ID_BRUSH_FLIPX
+Command4=ID_BRUSH_ROTATEX
+Command5=ID_BRUSH_FLIPY
+Command6=ID_BRUSH_ROTATEY
+Command7=ID_BRUSH_FLIPZ
+Command8=ID_BRUSH_ROTATEZ
+Command9=ID_SELECTION_SELECTCOMPLETETALL
+Command10=ID_SELECTION_SELECTTOUCHING
+Command11=ID_SELECTION_SELECTPARTIALTALL
+Command12=ID_SELECTION_SELECTINSIDE
+Command13=ID_SELECTION_CSGSUBTRACT
+Command14=ID_SELECTION_CSGMERGE
+Command15=ID_SELECTION_MAKEHOLLOW
+Command16=ID_VIEW_CLIPPER
+Command17=ID_VIEW_CHANGE
+Command18=ID_TEXTURES_POPUP
+Command19=ID_VIEW_CUBICCLIPPING
+Command20=ID_SELECT_MOUSEROTATE
+Command21=ID_SELECT_MOUSESCALE
+Command22=ID_SCALELOCKX
+Command23=ID_SCALELOCKY
+Command24=ID_SCALELOCKZ
+Command25=ID_DONTSELECTCURVE
+Command26=ID_PATCH_SHOWBOUNDINGBOX
+Command27=ID_PATCH_WIREFRAME
+Command28=ID_PATCH_BEND
+Command29=ID_PATCH_INSDEL
+Command30=ID_CURVE_CAP
+Command31=ID_PATCH_WELD
+Command32=ID_PATCH_DRILLDOWN
+Command33=ID_SHOW_ENTITIES
+CommandCount=33
+
+[MNU:IDR_MENU11]
+Type=1
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_FILE_SAVEAS
+Command5=ID_FILE_SAVEREGION
+Command6=ID_FILE_NEWPROJECT
+Command7=ID_FILE_LOADPROJECT
+Command8=ID_FILE_PROJECTSETTINGS
+Command9=ID_FILE_IMPORT
+Command10=ID_FILE_POINTFILE
+Command11=ID_FILE_EXIT
+Command12=ID_EDIT_UNDO
+Command13=ID_EDIT_COPYBRUSH
+Command14=ID_EDIT_PASTEBRUSH
+Command15=ID_EDIT_MAPINFO
+Command16=ID_EDIT_ENTITYINFO
+Command17=ID_BRUSH_SCRIPTS
+Command18=ID_PREFS
+Command19=ID_TOGGLECAMERA
+Command20=ID_TOGGLECONSOLE
+Command21=ID_VIEW_ENTITY
+Command22=ID_TOGGLEVIEW
+Command23=ID_TOGGLEVIEW_YZ
+Command24=ID_TOGGLEVIEW_XZ
+Command25=ID_TOGGLEZ
+Command26=ID_VIEW_CENTER
+Command27=ID_VIEW_UPFLOOR
+Command28=ID_VIEW_DOWNFLOOR
+Command29=ID_VIEW_NEXTVIEW
+Command30=ID_VIEW_XY
+Command31=ID_VIEW_SIDE
+Command32=ID_VIEW_FRONT
+Command33=ID_VIEW_100
+Command34=ID_VIEW_ZOOMIN
+Command35=ID_VIEW_ZOOMOUT
+Command36=ID_VIEW_Z100
+Command37=ID_VIEW_ZZOOMIN
+Command38=ID_VIEW_ZZOOMOUT
+Command39=ID_VIEW_CUBEIN
+Command40=ID_VIEW_CUBEOUT
+Command41=ID_VIEW_SHOWNAMES
+Command42=ID_VIEW_SHOWBLOCKS
+Command43=ID_VIEW_SHOWCOORDINATES
+Command44=ID_VIEW_SHOWENT
+Command45=ID_VIEW_SHOWPATH
+Command46=ID_VIEW_SHOWLIGHTS
+Command47=ID_VIEW_SHOWWATER
+Command48=ID_VIEW_SHOWCLIP
+Command49=ID_VIEW_SHOWWORLD
+Command50=ID_VIEW_SHOWDETAIL
+Command51=ID_VIEW_CUBICCLIPPING
+Command52=ID_SELECTION_DRAGEDGES
+Command53=ID_SELECTION_DRAGVERTECIES
+Command54=ID_SELECTION_CLONE
+Command55=ID_SELECTION_DESELECT
+Command56=ID_SELECTION_DELETE
+Command57=ID_BRUSH_FLIPX
+Command58=ID_BRUSH_FLIPY
+Command59=ID_BRUSH_FLIPZ
+Command60=ID_BRUSH_ROTATEX
+Command61=ID_BRUSH_ROTATEY
+Command62=ID_BRUSH_ROTATEZ
+Command63=ID_SELECTION_ARBITRARYROTATION
+Command64=ID_SELECT_SCALE
+Command65=ID_SELECTION_MAKEHOLLOW
+Command66=ID_SELECTION_CSGSUBTRACT
+Command67=ID_SELECTION_SELECTCOMPLETETALL
+Command68=ID_SELECTION_SELECTTOUCHING
+Command69=ID_SELECTION_SELECTPARTIALTALL
+Command70=ID_SELECTION_SELECTINSIDE
+Command71=ID_VIEW_CLIPPER
+Command72=ID_CLIP_SELECTED
+Command73=ID_SPLIT_SELECTED
+Command74=ID_FLIP_CLIP
+Command75=ID_SELECTION_CONNECT
+Command76=ID_SELECTION_UNGROUPENTITY
+Command77=ID_SELECTION_MAKE_DETAIL
+Command78=ID_SELECTION_MAKE_STRUCTURAL
+Command79=ID_GRID_1
+Command80=ID_GRID_2
+Command81=ID_GRID_4
+Command82=ID_GRID_8
+Command83=ID_GRID_16
+Command84=ID_GRID_32
+Command85=ID_GRID_64
+Command86=ID_SNAPTOGRID
+Command87=ID_TEXTURES_SHOWINUSE
+Command88=ID_TEXTURES_INSPECTOR
+Command89=ID_TEXTURES_WIREFRAME
+Command90=ID_TEXTURES_FLATSHADE
+Command91=ID_VIEW_NEAREST
+Command92=ID_VIEW_NEARESTMIPMAP
+Command93=ID_VIEW_LINEAR
+Command94=ID_VIEW_BILINEAR
+Command95=ID_VIEW_BILINEARMIPMAP
+Command96=ID_VIEW_TRILINEAR
+Command97=ID_TEXTURE_REPLACEALL
+Command98=ID_TOGGLE_LOCK
+Command99=ID_TOGGLE_ROTATELOCK
+Command100=ID_TEXTURES_LOAD
+Command101=ID_MISC_BENCHMARK
+Command102=ID_COLOR_SETORIGINAL
+Command103=ID_COLOR_SETQER
+Command104=ID_COLOR_SETBLACK
+Command105=ID_TEXTUREBK
+Command106=ID_COLORS_XYBK
+Command107=ID_COLORS_MAJOR
+Command108=ID_COLORS_MINOR
+Command109=ID_COLORS_GRIDTEXT
+Command110=ID_COLORS_GRIDBLOCK
+Command111=ID_COLORS_BRUSH
+Command112=ID_COLORS_SELECTEDBRUSH
+Command113=ID_COLORS_CLIPPER
+Command114=ID_COLORS_VIEWNAME
+Command115=ID_MISC_GAMMA
+Command116=ID_MISC_FINDBRUSH
+Command117=ID_MISC_NEXTLEAKSPOT
+Command118=ID_MISC_PREVIOUSLEAKSPOT
+Command119=ID_MISC_PRINTXY
+Command120=ID_MISC_SELECTENTITYCOLOR
+Command121=ID_REGION_OFF
+Command122=ID_REGION_SETXY
+Command123=ID_REGION_SETTALLBRUSH
+Command124=ID_REGION_SETBRUSH
+Command125=ID_REGION_SETSELECTION
+Command126=ID_BRUSH_3SIDED
+Command127=ID_BRUSH_4SIDED
+Command128=ID_BRUSH_5SIDED
+Command129=ID_BRUSH_6SIDED
+Command130=ID_BRUSH_7SIDED
+Command131=ID_BRUSH_8SIDED
+Command132=ID_BRUSH_9SIDED
+Command133=ID_BRUSH_ARBITRARYSIDED
+Command134=ID_BRUSH_MAKECONE
+Command135=ID_CURVE_CYLINDER
+Command136=ID_CURVE_ENDCAP
+Command137=ID_CURVE_BEVEL
+Command138=ID_CURVE_SPHERE
+Command139=ID_CURVE_HEMISPHERE
+Command140=ID_CURVE_QUARTER
+Command141=ID_CURVE_EIGHTHSPHERE
+Command142=ID_CURVE_INVERTCURVE
+Command143=ID_HELP_COMMANDLIST
+Command144=ID_HELP_ABOUT
+CommandCount=144
+
+[MNU:IDR_MENU_QUAKE3]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_IMPORTMAP
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVEAS
+Command6=ID_FILE_EXPORTMAP
+Command7=ID_FILE_SAVEREGION
+Command8=ID_FILE_NEWPROJECT
+Command9=ID_FILE_LOADPROJECT
+Command10=ID_FILE_PROJECTSETTINGS
+Command11=ID_FILE_POINTFILE
+Command12=ID_FILE_EXIT
+Command13=ID_EDIT_UNDO
+Command14=ID_EDIT_REDO
+Command15=ID_EDIT_COPYBRUSH
+Command16=ID_EDIT_PASTEBRUSH
+Command17=ID_SELECTION_DELETE
+Command18=ID_EDIT_MAPINFO
+Command19=ID_EDIT_ENTITYINFO
+Command20=ID_BRUSH_SCRIPTS
+Command21=ID_EDIT_LOADPREFAB
+Command22=ID_EDIT_SAVEPREFAB
+Command23=ID_PREFS
+Command24=ID_TOGGLECAMERA
+Command25=ID_TOGGLECONSOLE
+Command26=ID_VIEW_ENTITY
+Command27=ID_VIEW_GROUPS
+Command28=ID_TOGGLEVIEW
+Command29=ID_TOGGLEVIEW_YZ
+Command30=ID_TOGGLEVIEW_XZ
+Command31=ID_TOGGLEZ
+Command32=ID_VIEW_CENTER
+Command33=ID_VIEW_UPFLOOR
+Command34=ID_VIEW_DOWNFLOOR
+Command35=ID_VIEW_NEXTVIEW
+Command36=ID_VIEW_XY
+Command37=ID_VIEW_SIDE
+Command38=ID_VIEW_FRONT
+Command39=ID_VIEW_100
+Command40=ID_VIEW_ZOOMIN
+Command41=ID_VIEW_ZOOMOUT
+Command42=ID_VIEW_Z100
+Command43=ID_VIEW_ZZOOMIN
+Command44=ID_VIEW_ZZOOMOUT
+Command45=ID_VIEW_CUBEIN
+Command46=ID_VIEW_CUBEOUT
+Command47=ID_VIEW_SHOWNAMES
+Command48=ID_VIEW_SHOWBLOCKS
+Command49=ID_VIEW_SHOWCOORDINATES
+Command50=ID_VIEW_SHOWENT
+Command51=ID_VIEW_SHOWPATH
+Command52=ID_VIEW_SHOWLIGHTS
+Command53=ID_VIEW_SHOWWATER
+Command54=ID_VIEW_SHOWCLIP
+Command55=ID_VIEW_SHOWHINT
+Command56=ID_VIEW_SHOWWORLD
+Command57=ID_VIEW_SHOWDETAIL
+Command58=ID_VIEW_SHOWCURVES
+Command59=ID_VIEW_SHOWCAULK
+Command60=ID_VIEW_SHOWANGLES
+Command61=ID_VIEW_HIDESHOW_HIDESELECTED
+Command62=ID_VIEW_HIDESHOW_SHOWHIDDEN
+Command63=ID_VIEW_ENTITIESAS_BOUNDINGBOX
+Command64=ID_VIEW_ENTITIESAS_WIREFRAME
+Command65=ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME
+Command66=ID_VIEW_ENTITIESAS_SELECTEDSKINNED
+Command67=ID_VIEW_ENTITIESAS_SKINNED
+Command68=ID_VIEW_ENTITIESAS_SKINNEDANDBOXED
+Command69=ID_VIEW_CUBICCLIPPING
+Command70=ID_VIEW_OPENGLLIGHTING
+Command71=ID_SELECTION_DRAGEDGES
+Command72=ID_SELECTION_DRAGVERTECIES
+Command73=ID_SELECTION_CLONE
+Command74=ID_SELECTION_DESELECT
+Command75=ID_BRUSH_FLIPX
+Command76=ID_BRUSH_FLIPY
+Command77=ID_BRUSH_FLIPZ
+Command78=ID_BRUSH_ROTATEX
+Command79=ID_BRUSH_ROTATEY
+Command80=ID_BRUSH_ROTATEZ
+Command81=ID_SELECTION_ARBITRARYROTATION
+Command82=ID_SELECT_SCALE
+Command83=ID_SELECTION_MAKEHOLLOW
+Command84=ID_SELECTION_CSGSUBTRACT
+Command85=ID_SELECTION_CSGMERGE
+Command86=ID_SELECTION_SELECTCOMPLETETALL
+Command87=ID_SELECTION_SELECTTOUCHING
+Command88=ID_SELECTION_SELECTPARTIALTALL
+Command89=ID_SELECTION_SELECTINSIDE
+Command90=ID_VIEW_CLIPPER
+Command91=ID_CLIP_SELECTED
+Command92=ID_SPLIT_SELECTED
+Command93=ID_FLIP_CLIP
+Command94=ID_SELECTION_CONNECT
+Command95=ID_SELECTION_UNGROUPENTITY
+Command96=ID_SELECTION_MAKE_DETAIL
+Command97=ID_SELECTION_MAKE_STRUCTURAL
+Command98=ID_GRID_1
+Command99=ID_GRID_2
+Command100=ID_GRID_4
+Command101=ID_GRID_8
+Command102=ID_GRID_16
+Command103=ID_GRID_32
+Command104=ID_GRID_64
+Command105=ID_SNAPTOGRID
+Command106=ID_TEXTURES_SHOWINUSE
+Command107=ID_TEXTURES_SHOWALL
+Command108=ID_TEXTURES_INSPECTOR
+Command109=ID_TEXTURES_WIREFRAME
+Command110=ID_TEXTURES_FLATSHADE
+Command111=ID_VIEW_NEAREST
+Command112=ID_VIEW_NEARESTMIPMAP
+Command113=ID_VIEW_LINEAR
+Command114=ID_VIEW_BILINEAR
+Command115=ID_VIEW_BILINEARMIPMAP
+Command116=ID_VIEW_TRILINEAR
+Command117=ID_TEXTURE_REPLACEALL
+Command118=ID_TOGGLE_LOCK
+Command119=ID_TOGGLE_ROTATELOCK
+Command120=ID_TEXTURES_LOAD
+Command121=ID_TEXTURES_RELOADSHADERS
+Command122=ID_TEXTURES_SHADERS_SHOW
+Command123=ID_TEXTURES_FLUSH
+Command124=ID_TEXTURES_FLUSH_UNUSED
+Command125=ID_TEXTURES_TEXTUREWINDOWSCALE_200
+Command126=ID_TEXTURES_TEXTUREWINDOWSCALE_100
+Command127=ID_TEXTURES_TEXTUREWINDOWSCALE_50
+Command128=ID_TEXTURES_TEXTUREWINDOWSCALE_25
+Command129=ID_TEXTURES_TEXTUREWINDOWSCALE_10
+Command130=ID_MISC_BENCHMARK
+Command131=ID_COLOR_SETORIGINAL
+Command132=ID_COLOR_SETQER
+Command133=ID_COLOR_SETBLACK
+Command134=ID_TEXTUREBK
+Command135=ID_COLORS_XYBK
+Command136=ID_COLORS_MAJOR
+Command137=ID_COLORS_MINOR
+Command138=ID_COLORS_GRIDTEXT
+Command139=ID_COLORS_GRIDBLOCK
+Command140=ID_COLORS_BRUSH
+Command141=ID_COLORS_SELECTEDBRUSH
+Command142=ID_COLORS_CLIPPER
+Command143=ID_COLORS_VIEWNAME
+Command144=ID_MISC_GAMMA
+Command145=ID_MISC_FINDBRUSH
+Command146=ID_MISC_NEXTLEAKSPOT
+Command147=ID_MISC_PREVIOUSLEAKSPOT
+Command148=ID_MISC_PRINTXY
+Command149=ID_MISC_SELECTENTITYCOLOR
+Command150=ID_REGION_OFF
+Command151=ID_REGION_SETXY
+Command152=ID_REGION_SETTALLBRUSH
+Command153=ID_REGION_SETBRUSH
+Command154=ID_REGION_SETSELECTION
+Command155=ID_BRUSH_3SIDED
+Command156=ID_BRUSH_4SIDED
+Command157=ID_BRUSH_5SIDED
+Command158=ID_BRUSH_6SIDED
+Command159=ID_BRUSH_7SIDED
+Command160=ID_BRUSH_8SIDED
+Command161=ID_BRUSH_9SIDED
+Command162=ID_BRUSH_ARBITRARYSIDED
+Command163=ID_BRUSH_MAKECONE
+Command164=ID_BRUSH_PRIMITIVES_SPHERE
+Command165=ID_CURVE_PATCHTUBE
+Command166=ID_CURVE_PATCHDENSETUBE
+Command167=ID_CURVE_PATCHVERYDENSETUBE
+Command168=ID_CURVE_PATCHSQUARE
+Command169=ID_CURVE_PATCHENDCAP
+Command170=ID_CURVE_PATCHBEVEL
+Command171=ID_CURVE_MOREENDCAPSBEVELS_SQUAREBEVEL
+Command172=ID_CURVE_MOREENDCAPSBEVELS_SQUAREENDCAP
+Command173=ID_CURVE_PATCHCONE
+Command174=ID_CURVE_PRIMITIVES_SPHERE
+Command175=ID_CURVE_SIMPLEPATCHMESH
+Command176=ID_CURVE_INSERT_INSERTCOLUMN
+Command177=ID_CURVE_INSERT_ADDCOLUMN
+Command178=ID_CURVE_INSERT_INSERTROW
+Command179=ID_CURVE_INSERT_ADDROW
+Command180=ID_CURVE_DELETE_FIRSTCOLUMN
+Command181=ID_CURVE_DELETE_LASTCOLUMN
+Command182=ID_CURVE_DELETE_FIRSTROW
+Command183=ID_CURVE_DELETE_LASTROW
+Command184=ID_CURVE_NEGATIVE
+Command185=ID_CURVE_REDISPERSE_COLS
+Command186=ID_CURVE_REDISPERSE_ROWS
+Command187=ID_CURVE_MATRIX_TRANSPOSE
+Command188=ID_CURVE_CAP
+Command189=ID_CURVE_CAP_INVERTEDBEVEL
+Command190=ID_CURVE_CAP_INVERTEDENDCAP
+Command191=ID_CURVE_CYCLECAP
+Command192=ID_CURVE_OVERLAY_SET
+Command193=ID_CURVE_OVERLAY_CLEAR
+Command194=ID_CURVE_THICKEN
+Command195=ID_PLUGINS_REFRESH
+Command196=ID_HELP
+Command197=ID_HELP_COMMANDLIST
+Command198=ID_HELP_ABOUT
+CommandCount=198
+
+[MNU:IDR_MENU1]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_IMPORTMAP
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVEAS
+Command6=ID_FILE_EXPORTMAP
+Command7=ID_FILE_SAVEREGION
+Command8=ID_FILE_NEWPROJECT
+Command9=ID_FILE_LOADPROJECT
+Command10=ID_FILE_PROJECTSETTINGS
+Command11=ID_FILE_POINTFILE
+Command12=ID_FILE_EXIT
+Command13=ID_EDIT_UNDO
+Command14=ID_EDIT_COPYBRUSH
+Command15=ID_EDIT_PASTEBRUSH
+Command16=ID_EDIT_MAPINFO
+Command17=ID_EDIT_ENTITYINFO
+Command18=ID_BRUSH_SCRIPTS
+Command19=ID_EDIT_LOADPREFAB
+Command20=ID_PREFS
+Command21=ID_TOGGLECAMERA
+Command22=ID_TOGGLECONSOLE
+Command23=ID_VIEW_ENTITY
+Command24=ID_TOGGLEVIEW
+Command25=ID_TOGGLEVIEW_YZ
+Command26=ID_TOGGLEVIEW_XZ
+Command27=ID_TOGGLEZ
+Command28=ID_VIEW_CENTER
+Command29=ID_VIEW_UPFLOOR
+Command30=ID_VIEW_DOWNFLOOR
+Command31=ID_VIEW_NEXTVIEW
+Command32=ID_VIEW_XY
+Command33=ID_VIEW_SIDE
+Command34=ID_VIEW_FRONT
+Command35=ID_VIEW_100
+Command36=ID_VIEW_ZOOMIN
+Command37=ID_VIEW_ZOOMOUT
+Command38=ID_VIEW_Z100
+Command39=ID_VIEW_ZZOOMIN
+Command40=ID_VIEW_ZZOOMOUT
+Command41=ID_VIEW_CUBEIN
+Command42=ID_VIEW_CUBEOUT
+Command43=ID_VIEW_SHOWNAMES
+Command44=ID_VIEW_SHOWBLOCKS
+Command45=ID_VIEW_SHOWCOORDINATES
+Command46=ID_VIEW_SHOWENT
+Command47=ID_VIEW_SHOWPATH
+Command48=ID_VIEW_SHOWLIGHTS
+Command49=ID_VIEW_SHOWWATER
+Command50=ID_VIEW_SHOWCLIP
+Command51=ID_VIEW_SHOWWORLD
+Command52=ID_VIEW_SHOWDETAIL
+Command53=ID_VIEW_CUBICCLIPPING
+Command54=ID_DYNAMIC_LIGHTING
+Command55=ID_SELECTION_DRAGEDGES
+Command56=ID_SELECTION_DRAGVERTECIES
+Command57=ID_SELECTION_CLONE
+Command58=ID_SELECTION_DESELECT
+Command59=ID_SELECTION_DELETE
+Command60=ID_BRUSH_FLIPX
+Command61=ID_BRUSH_FLIPY
+Command62=ID_BRUSH_FLIPZ
+Command63=ID_BRUSH_ROTATEX
+Command64=ID_BRUSH_ROTATEY
+Command65=ID_BRUSH_ROTATEZ
+Command66=ID_SELECTION_ARBITRARYROTATION
+Command67=ID_SELECT_SCALE
+Command68=ID_SELECTION_MAKEHOLLOW
+Command69=ID_SELECTION_CSGSUBTRACT
+Command70=ID_SELECTION_CSGADD
+Command71=ID_SELECTION_SELECTCOMPLETETALL
+Command72=ID_SELECTION_SELECTTOUCHING
+Command73=ID_SELECTION_SELECTPARTIALTALL
+Command74=ID_SELECTION_SELECTINSIDE
+Command75=ID_SELECTION_SELECT_NUDGELEFT
+Command76=ID_SELECTION_SELECT_NUDGERIGHT
+Command77=ID_SELECTION_SELECT_NUDGEUP
+Command78=ID_SELECTION_SELECT_NUDGEDOWN
+Command79=ID_VIEW_CLIPPER
+Command80=ID_CLIP_SELECTED
+Command81=ID_SPLIT_SELECTED
+Command82=ID_FLIP_CLIP
+Command83=ID_SELECTION_CONNECT
+Command84=ID_SELECTION_UNGROUPENTITY
+Command85=ID_SELECTION_MAKE_DETAIL
+Command86=ID_SELECTION_MAKE_STRUCTURAL
+Command87=ID_GRID_1
+Command88=ID_GRID_2
+Command89=ID_GRID_4
+Command90=ID_GRID_8
+Command91=ID_GRID_16
+Command92=ID_GRID_32
+Command93=ID_GRID_64
+Command94=ID_SNAPTOGRID
+Command95=ID_TEXTURES_SHOWINUSE
+Command96=ID_TEXTURES_INSPECTOR
+Command97=ID_TEXTURES_WIREFRAME
+Command98=ID_TEXTURES_FLATSHADE
+Command99=ID_VIEW_NEAREST
+Command100=ID_VIEW_NEARESTMIPMAP
+Command101=ID_VIEW_LINEAR
+Command102=ID_VIEW_BILINEAR
+Command103=ID_VIEW_BILINEARMIPMAP
+Command104=ID_VIEW_TRILINEAR
+Command105=ID_TEXTURE_REPLACEALL
+Command106=ID_TOGGLE_LOCK
+Command107=ID_TOGGLE_ROTATELOCK
+Command108=ID_TEXTURES_LOAD
+Command109=ID_TEXTURES_LOADLIST
+Command110=ID_MISC_BENCHMARK
+Command111=ID_COLOR_SETORIGINAL
+Command112=ID_COLOR_SETQER
+Command113=ID_COLOR_SETBLACK
+Command114=ID_TEXTUREBK
+Command115=ID_COLORS_XYBK
+Command116=ID_COLORS_MAJOR
+Command117=ID_COLORS_MINOR
+Command118=ID_COLORS_GRIDTEXT
+Command119=ID_COLORS_GRIDBLOCK
+Command120=ID_COLORS_BRUSH
+Command121=ID_COLORS_SELECTEDBRUSH
+Command122=ID_COLORS_CLIPPER
+Command123=ID_COLORS_VIEWNAME
+Command124=ID_MISC_GAMMA
+Command125=ID_MISC_FINDBRUSH
+Command126=ID_MISC_NEXTLEAKSPOT
+Command127=ID_MISC_PREVIOUSLEAKSPOT
+Command128=ID_MISC_PRINTXY
+Command129=ID_MISC_SELECTENTITYCOLOR
+Command130=ID_CONVERTCURVES
+Command131=ID_REGION_OFF
+Command132=ID_REGION_SETXY
+Command133=ID_REGION_SETTALLBRUSH
+Command134=ID_REGION_SETBRUSH
+Command135=ID_REGION_SETSELECTION
+Command136=ID_BRUSH_3SIDED
+Command137=ID_BRUSH_4SIDED
+Command138=ID_BRUSH_5SIDED
+Command139=ID_BRUSH_6SIDED
+Command140=ID_BRUSH_7SIDED
+Command141=ID_BRUSH_8SIDED
+Command142=ID_BRUSH_9SIDED
+Command143=ID_BRUSH_ARBITRARYSIDED
+Command144=ID_BRUSH_MAKECONE
+Command145=ID_HELP_COMMANDLIST
+Command146=ID_HELP_ABOUT
+CommandCount=146
+
+[ACL:IDR_MINIACCEL]
+Type=1
+Class=?
+Command1=ID_SELECTION_SELECT_NUDGEDOWN
+Command2=ID_SELECTION_SELECT_NUDGELEFT
+Command3=ID_SELECTION_SELECT_NUDGERIGHT
+Command4=ID_SELECTION_SELECT_NUDGEUP
+CommandCount=4
+
+[DLG:IDD_DIALOG_TEXTURELIST]
+Type=1
+Class=CDialogTextures
+ControlCount=3
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_LIST_TEXTURES,listbox,1352728835
+
+[CLS:CDialogTextures]
+Type=0
+HeaderFile=DialogTextures.h
+ImplementationFile=DialogTextures.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=ID_TEXTURES_LOADLIST
+VirtualFilter=dWC
+
+[DLG:IDD_DIALOG_NEWPATCH]
+Type=1
+Class=CPatchDensityDlg
+ControlCount=6
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_COMBO_WIDTH,combobox,1344339971
+Control6=IDC_COMBO_HEIGHT,combobox,1344339971
+
+[CLS:CPatchDensityDlg]
+Type=0
+HeaderFile=PatchDensityDlg.h
+ImplementationFile=PatchDensityDlg.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CPatchDensityDlg
+
+[DLG:IDD_DIALOG_TEXTURELAYOUT]
+Type=1
+Class=CTextureLayout
+ControlCount=7
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_STATIC,static,1342308352
+Control5=IDC_EDIT_X,edit,1350631552
+Control6=IDC_STATIC,static,1342308352
+Control7=IDC_EDIT_Y,edit,1350631552
+
+[CLS:CTextureLayout]
+Type=0
+HeaderFile=TextureLayout.h
+ImplementationFile=TextureLayout.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CTextureLayout
+
+[DLG:IDD_DIALOG_CAP]
+Type=1
+Class=CCapDialog
+ControlCount=10
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_RADIO_CAP,button,1342308361
+Control4=IDC_RADIO_CAP2,button,1342177289
+Control5=IDC_RADIO_CAP3,button,1342177289
+Control6=IDC_RADIO_CAP4,button,1342177289
+Control7=IDC_STATIC,static,1342183438
+Control8=IDC_STATIC,static,1342183438
+Control9=IDC_STATIC,static,1342183438
+Control10=IDC_STATIC,static,1342183438
+
+[CLS:CCapDialog]
+Type=0
+HeaderFile=CapDialog.h
+ImplementationFile=CapDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=CCapDialog
+
+[DLG:IDD_DIALOG_THICKEN]
+Type=1
+Class=CDialogThick
+ControlCount=6
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_STATIC,static,1342308352
+Control4=IDC_EDIT_AMOUNT,edit,1350631552
+Control5=IDC_STATIC,static,1342308352
+Control6=IDC_CHECK_SEAMS,button,1342242819
+
+[CLS:CDialogThick]
+Type=0
+HeaderFile=DialogThick.h
+ImplementationFile=DialogThick.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=IDC_EDIT_AMOUNT
+VirtualFilter=dWC
+
+[MNU:IDR_POPUP_ENTITY]
+Type=1
+Class=?
+Command1=ID_VIEW_ENTITIESAS_BOUNDINGBOX
+Command2=ID_VIEW_ENTITIESAS_WIREFRAME
+Command3=ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME
+Command4=ID_VIEW_ENTITIESAS_SELECTEDSKINNED
+Command5=ID_VIEW_ENTITIESAS_SKINNED
+Command6=ID_VIEW_ENTITIESAS_SKINNEDANDBOXED
+CommandCount=6
+
+[CLS:CShaderEdit]
+Type=0
+HeaderFile=ShaderEdit.h
+ImplementationFile=ShaderEdit.cpp
+BaseClass=CFrameWnd
+Filter=T
+VirtualFilter=fWC
+
+[CLS:CShaderFrame]
+Type=0
+HeaderFile=ShaderFrame.h
+ImplementationFile=ShaderFrame.cpp
+BaseClass=CFrameWnd
+Filter=T
+VirtualFilter=fWC
+LastObject=IDC_COMBO_TYPE
+
+[MNU:"IDR_SHADERFRAME"]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_PRINT_SETUP
+Command4=ID_FILE_MRU_FILE1
+Command5=ID_APP_EXIT
+Command6=ID_VIEW_TOOLBAR
+Command7=ID_VIEW_STATUS_BAR
+Command8=ID_APP_ABOUT
+CommandCount=8
+
+[MNU:"IDR_SHADERTYPE"]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_CLOSE
+Command4=ID_FILE_SAVE
+Command5=ID_FILE_SAVE_AS
+Command6=ID_FILE_PRINT
+Command7=ID_FILE_PRINT_SETUP
+Command8=ID_FILE_MRU_FILE1
+Command9=ID_APP_EXIT
+Command10=ID_EDIT_UNDO
+Command11=ID_EDIT_CUT
+Command12=ID_EDIT_COPY
+Command13=ID_EDIT_PASTE
+Command14=ID_EDIT_CLEAR
+Command15=ID_EDIT_FIND
+Command16=ID_EDIT_REPEAT
+Command17=ID_EDIT_REPLACE
+Command18=ID_EDIT_SELECT_ALL
+Command19=ID_VIEW_TOOLBAR
+Command20=ID_VIEW_STATUS_BAR
+Command21=ID_WINDOW_CASCADE
+Command22=ID_WINDOW_TILE_HORZ
+Command23=ID_WINDOW_ARRANGE
+Command24=ID_APP_ABOUT
+CommandCount=24
+
+[TB:IDR_SHADERFRAME]
+Type=1
+Class=?
+Command1=ID_FILE_OPEN
+Command2=ID_FILE_SAVE
+Command3=ID_EDIT_CUT
+Command4=ID_EDIT_COPY
+Command5=ID_EDIT_PASTE
+CommandCount=5
+
+[MNU:IDR_SHADERFRAME]
+Type=1
+Class=?
+Command1=ID_FILE_NEW
+Command2=ID_FILE_OPEN
+Command3=ID_FILE_SAVE
+Command4=ID_FILE_SAVE_AS
+Command5=ID_FILE_CLOSE
+Command6=ID_EDIT_UNDO
+Command7=ID_EDIT_CUT
+Command8=ID_EDIT_COPY
+Command9=ID_EDIT_PASTE
+Command10=ID_EDIT_CLEAR
+Command11=ID_EDIT_FIND
+Command12=ID_EDIT_REPEAT
+Command13=ID_EDIT_REPLACE
+Command14=ID_EDIT_SELECT_ALL
+CommandCount=14
+
+[DLG:IDD_DIALOG_PATCH]
+Type=1
+Class=CPatchDialog
+ControlCount=41
+Control1=IDC_COMBO_ROW,combobox,1344340227
+Control2=IDC_COMBO_COL,combobox,1344340227
+Control3=IDC_EDIT_X,edit,1350631552
+Control4=IDC_EDIT_Y,edit,1350631552
+Control5=IDC_EDIT_Z,edit,1350631552
+Control6=IDC_EDIT_S,edit,1350631552
+Control7=IDC_EDIT_T,edit,1350631552
+Control8=IDC_COMBO_TYPE,combobox,1344340227
+Control9=IDC_EDIT_NAME,edit,1350631552
+Control10=IDC_HSHIFT,edit,1350631552
+Control11=IDC_SPIN_HSHIFT,msctls_updown32,1342177332
+Control12=IDC_VSHIFT,edit,1350631552
+Control13=IDC_SPIN_VSHIFT,msctls_updown32,1342177332
+Control14=IDC_HSCALE,edit,1350631552
+Control15=IDC_SPIN_HSCALE,msctls_updown32,1342177332
+Control16=IDC_VSCALE,edit,1350631552
+Control17=IDC_SPIN_VSCALE,msctls_updown32,1342177332
+Control18=IDC_ROTATE,edit,1350631552
+Control19=IDC_SPIN_ROTATE,msctls_updown32,1342177332
+Control20=IDC_BTN_PATCHDETAILS,button,1342242816
+Control21=IDC_BTN_PATCHRESET,button,1342242816
+Control22=IDC_BTN_PATCHNATURAL,button,1342242816
+Control23=IDC_BTN_PATCHFIT,button,1342242816
+Control24=ID_APPLY,button,1342242816
+Control25=IDOK,button,1342242817
+Control26=IDC_STATIC,static,1342308352
+Control27=IDC_STATIC,static,1342308352
+Control28=IDC_STATIC,static,1342308352
+Control29=IDC_STATIC,static,1342308352
+Control30=IDC_STATIC,static,1342308352
+Control31=IDC_STATIC,static,1342308352
+Control32=IDC_STATIC,static,1342308352
+Control33=IDC_STATIC,static,1342308352
+Control34=IDC_STATIC,static,1342308352
+Control35=IDC_STATIC,static,1342308352
+Control36=IDC_STATIC,static,1342308352
+Control37=IDC_STATIC,static,1342308352
+Control38=IDC_STATIC,static,1342308352
+Control39=IDC_STATIC,button,1342177287
+Control40=IDC_STATIC,button,1342177287
+Control41=IDC_STATIC,static,1342308352
+
+[CLS:CPatchDialog]
+Type=0
+HeaderFile=PatchDialog.h
+ImplementationFile=PatchDialog.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=IDC_HSHIFT
+
+[CLS:CWaveOpen]
+Type=0
+HeaderFile=WaveOpen.h
+ImplementationFile=WaveOpen.cpp
+BaseClass=CFileDialog
+Filter=D
+LastObject=ID_VIEW_OPENGLLIGHTING
+VirtualFilter=dWC
+
+[DLG:IDD_PLAYWAVE]
+Type=1
+Class=?
+ControlCount=1
+Control1=IDC_BTN_PLAY,button,1342242816
+
+[DLG:IDD_TEXLIST]
+Type=1
+Class=?
+ControlCount=3
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+Control3=IDC_LIST_TEXTURES,listbox,1352728835
+
+[DLG:IDD_DIALOG2]
+Type=1
+Class=?
+ControlCount=2
+Control1=IDOK,button,1342242817
+Control2=IDCANCEL,button,1342242816
+
+[DLG:IDD_GROUPBAR]
+Type=1
+Class=CGroupBar
+ControlCount=5
+Control1=IDC_COMBO_GROUPS,combobox,1344340226
+Control2=IDC_STATIC,static,1342308352
+Control3=IDC_BTN_ADDGROUP,button,1342242816
+Control4=IDC_BTN_REMOVEGROUP,button,1342242816
+Control5=IDC_BTN_LISTGROUPS,button,1342242816
+
+[CLS:CGroupBar]
+Type=0
+HeaderFile=GroupBar.h
+ImplementationFile=GroupBar.cpp
+BaseClass=CDialog
+Filter=D
+VirtualFilter=dWC
+LastObject=ID_TEXTURES_FLUSH_UNUSED
+
+[DLG:IDD_DLG_GROUP]
+Type=1
+Class=CGroupDlg
+ControlCount=4
+Control1=IDC_TREE_GROUP,SysTreeView32,1350631439
+Control2=IDC_BTN_ADD,button,1342242816
+Control3=IDC_BTN_DEL,button,1342242816
+Control4=IDC_BTN_EDIT,button,1342242816
+
+[CLS:CGroupDlg]
+Type=0
+HeaderFile=GroupDlg.h
+ImplementationFile=GroupDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=IDC_TREE_GROUP
+VirtualFilter=dWC
+
+[MNU:IDR_POPUP_GROUP]
+Type=1
+Class=?
+Command1=ID_VIEW_XY
+Command2=ID_VIEW_SIDE
+Command3=ID_VIEW_FRONT
+CommandCount=3
+
+[DLG:IDD_NEWNAME]
+Type=1
+Class=CNameDlg
+ControlCount=4
+Control1=IDC_EDIT_NAME,edit,1350631552
+Control2=IDOK,button,1342242817
+Control3=IDCANCEL,button,1342242816
+Control4=IDC_STATIC,static,1342308352
+
+[CLS:CNameDlg]
+Type=0
+HeaderFile=NameDlg.h
+ImplementationFile=NameDlg.cpp
+BaseClass=CDialog
+Filter=D
+LastObject=CNameDlg
+VirtualFilter=dWC
+
diff --git a/q3radiant/Radiant.cpp b/q3radiant/Radiant.cpp
new file mode 100755
index 0000000..215a7a8
--- /dev/null
+++ b/q3radiant/Radiant.cpp
@@ -0,0 +1,261 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// Radiant.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+
+#include "MainFrm.h"
+#include "ChildFrm.h"
+#include "RadiantDoc.h"
+#include "RadiantView.h"
+#include "PrefsDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantApp
+
+BEGIN_MESSAGE_MAP(CRadiantApp, CWinApp)
+ //{{AFX_MSG_MAP(CRadiantApp)
+ ON_COMMAND(ID_HELP, OnHelp)
+ //}}AFX_MSG_MAP
+ // Standard file based document commands
+ ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
+ ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
+ // Standard print setup command
+ ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantApp construction
+
+CRadiantApp::CRadiantApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CRadiantApp object
+
+CRadiantApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantApp initialization
+
+HINSTANCE g_hOpenGL32 = NULL;
+HINSTANCE g_hOpenGL = NULL;
+bool g_bBuildList = false;
+
+BOOL CRadiantApp::InitInstance()
+{
+ //g_hOpenGL32 = ::LoadLibrary("opengl32.dll");
+ // AfxEnableControlContainer();
+
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+ //AfxEnableMemoryTracking(FALSE);
+
+ // VC7 says deprecated and no longer necessary
+#if 0
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+#endif
+
+ // If there's a .INI file in the directory use it instead of registry
+ char RadiantPath[_MAX_PATH];
+ GetModuleFileName( NULL, RadiantPath, _MAX_PATH );
+
+ // search for exe
+ CFileFind Finder;
+ Finder.FindFile( RadiantPath );
+ Finder.FindNextFile();
+ // extract root
+ CString Root = Finder.GetRoot();
+ // build root\*.ini
+ CString IniPath = Root + "\\REGISTRY.INI";
+ // search for ini file
+ Finder.FindNextFile();
+ if (Finder.FindFile( IniPath ))
+ {
+ Finder.FindNextFile();
+ // use the .ini file instead of the registry
+ free((void*)m_pszProfileName);
+ m_pszProfileName=_tcsdup(_T(Finder.GetFilePath()));
+ // look for the registry key for void* buffers storage ( these can't go into .INI files )
+ int i=0;
+ CString key;
+ HKEY hkResult;
+ DWORD dwDisp;
+ DWORD type;
+ char iBuf[3];
+ do
+ {
+ sprintf( iBuf, "%d", i );
+ key = "Software\\Q3Radiant\\IniPrefs" + CString(iBuf);
+ // does this key exists ?
+ if ( RegOpenKeyEx( HKEY_CURRENT_USER, key, 0, KEY_ALL_ACCESS, &hkResult ) != ERROR_SUCCESS )
+ {
+ // this key doesn't exist, so it's the one we'll use
+ strcpy( g_qeglobals.use_ini_registry, key.GetBuffer(0) );
+ RegCreateKeyEx( HKEY_CURRENT_USER, key, 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkResult, &dwDisp );
+ RegSetValueEx( hkResult, "RadiantName", 0, REG_SZ, reinterpret_cast<CONST BYTE *>(RadiantPath), strlen( RadiantPath )+1 );
+ RegCloseKey( hkResult );
+ break;
+ }
+ else
+ {
+ char RadiantAux[ _MAX_PATH ];
+ unsigned long size = _MAX_PATH;
+ // the key exists, is it the one we are looking for ?
+ RegQueryValueEx( hkResult, "RadiantName", 0, &type, reinterpret_cast<BYTE *>(RadiantAux), &size );
+ RegCloseKey( hkResult );
+ if ( !strcmp( RadiantAux, RadiantPath ) )
+ {
+ // got it !
+ strcpy( g_qeglobals.use_ini_registry, key.GetBuffer(0) );
+ break;
+ }
+ }
+ i++;
+ } while (1);
+ g_qeglobals.use_ini = true;
+ }
+ else
+ {
+ // Change the registry key under which our settings are stored.
+ // You should modify this string to be something appropriate
+ // such as the name of your company or organization.
+ SetRegistryKey("Q3Radiant");
+ g_qeglobals.use_ini = false;
+ }
+
+ LoadStdProfileSettings(); // Load standard INI file options (including MRU)
+
+
+ // Register the application's document templates. Document templates
+ // serve as the connection between documents, frame windows and views.
+
+// CMultiDocTemplate* pDocTemplate;
+// pDocTemplate = new CMultiDocTemplate(
+// IDR_RADIANTYPE,
+// RUNTIME_CLASS(CRadiantDoc),
+// RUNTIME_CLASS(CMainFrame), // custom MDI child frame
+// RUNTIME_CLASS(CRadiantView));
+// AddDocTemplate(pDocTemplate);
+
+ // create main MDI Frame window
+
+ g_PrefsDlg.LoadPrefs();
+
+ int nMenu = IDR_MENU1;
+
+ CString strOpenGL = (g_PrefsDlg.m_bSGIOpenGL) ? "opengl.dll" : "opengl32.dll";
+ CString strGLU = (g_PrefsDlg.m_bSGIOpenGL) ? "glu.dll" : "glu32.dll";
+
+ if (!QGL_Init(strOpenGL, strGLU))
+ {
+ g_PrefsDlg.m_bSGIOpenGL ^= 1;
+ strOpenGL = (g_PrefsDlg.m_bSGIOpenGL) ? "opengl.dll" : "opengl32.dll";
+ strGLU = (g_PrefsDlg.m_bSGIOpenGL) ? "glu.dll" : "glu32.dll";
+ if (!QGL_Init(strOpenGL, strGLU))
+ {
+ AfxMessageBox("Failed to load OpenGL libraries. \"OPENGL32.DLL\" and \"OPENGL.DLL\" were tried");
+ return FALSE;
+ }
+ g_PrefsDlg.SavePrefs();
+ }
+
+ CString strTemp = m_lpCmdLine;
+ strTemp.MakeLower();
+ if (strTemp.Find("builddefs") >= 0)
+ g_bBuildList = true;
+
+ CMainFrame* pMainFrame = new CMainFrame;
+ if (!pMainFrame->LoadFrame(nMenu))
+ return FALSE;
+
+ if (pMainFrame->m_hAccelTable)
+ ::DestroyAcceleratorTable(pMainFrame->m_hAccelTable);
+
+ pMainFrame->LoadAccelTable(MAKEINTRESOURCE(IDR_MINIACCEL));
+
+ m_pMainWnd = pMainFrame;
+
+ // Parse command line for standard shell commands, DDE, file open
+ CCommandLineInfo cmdInfo;
+ ParseCommandLine(cmdInfo);
+
+ // Dispatch commands specified on the command line
+ //if (!ProcessShellCommand(cmdInfo))
+ // return FALSE;
+
+ // The main window has been initialized, so show and update it.
+ pMainFrame->ShowWindow(m_nCmdShow);
+ pMainFrame->UpdateWindow();
+
+ free((void*)m_pszHelpFilePath);
+ CString strHelp = g_strAppPath;
+ AddSlash(strHelp);
+ strHelp += "Q3RManual.chm";
+ m_pszHelpFilePath= _tcsdup(strHelp);
+
+
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantApp commands
+
+int CRadiantApp::ExitInstance()
+{
+ // TODO: Add your specialized code here and/or call the base class
+ //::FreeLibrary(g_hOpenGL32);
+ QGL_Shutdown();
+ return CWinApp::ExitInstance();
+}
+
+BOOL CRadiantApp::OnIdle(LONG lCount)
+{
+ if (g_pParentWnd)
+ g_pParentWnd->RoutineProcessing();
+ return CWinApp::OnIdle(lCount);
+}
+
+void CRadiantApp::OnHelp()
+{
+ ShellExecute(m_pMainWnd->GetSafeHwnd(), "open", m_pszHelpFilePath, NULL, NULL, SW_SHOW);
+}
diff --git a/q3radiant/Radiant.h b/q3radiant/Radiant.h
new file mode 100755
index 0000000..e910543
--- /dev/null
+++ b/q3radiant/Radiant.h
@@ -0,0 +1,71 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// Radiant.h : main header file for the RADIANT application
+//
+
+#if !defined(AFX_RADIANT_H__330BBF06_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+#define AFX_RADIANT_H__330BBF06_731C_11D1_B539_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantApp:
+// See Radiant.cpp for the implementation of this class
+//
+
+class CRadiantApp : public CWinApp
+{
+public:
+ CRadiantApp();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRadiantApp)
+ public:
+ virtual BOOL InitInstance();
+ virtual int ExitInstance();
+ virtual BOOL OnIdle(LONG lCount);
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CRadiantApp)
+ afx_msg void OnHelp();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_RADIANT_H__330BBF06_731C_11D1_B539_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/Radiant.rc b/q3radiant/Radiant.rc
new file mode 100755
index 0000000..dcab967
--- /dev/null
+++ b/q3radiant/Radiant.rc
@@ -0,0 +1,2838 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\Radiant.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#include ""afxprint.rc"" // printing/print preview resources\r\n"
+ "#endif\0"
+END
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON DISCARDABLE "res\\icon2.ico"
+IDR_MAINFRAME ICON DISCARDABLE "res\\Radiant.ico"
+IDR_RADIANTYPE ICON DISCARDABLE "res\\RadiantDoc.ico"
+IDR_SHADERFRAME ICON DISCARDABLE "RES\\shaderframe.ico"
+IDR_SHADERTYPE ICON DISCARDABLE "RES\\shaderdoc.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDR_SHADERFRAME BITMAP MOVEABLE PURE "res\\Toolbar.bmp"
+IDR_TOOLBAR1 BITMAP DISCARDABLE "res\\toolbar1.bmp"
+IDB_BITMAP1 BITMAP DISCARDABLE "res\\q.bmp"
+IDB_VIEWDEFAULT BITMAP DISCARDABLE "res\\bitmap2.bmp"
+IDB_VIEWQE4 BITMAP DISCARDABLE "res\\viewdefa.bmp"
+IDB_VIEW4WAY BITMAP DISCARDABLE "res\\viewoppo.bmp"
+IDB_VIEWDEFAULT_Z BITMAP DISCARDABLE "res\\bmp00001.bmp"
+IDB_3DFX BITMAP DISCARDABLE "res\\logo_sm3dfx.bmp"
+IDR_TOOLBAR_SCALELOCK BITMAP DISCARDABLE "res\\toolbar2.bmp"
+IDR_TOOLBAR_ADVANCED BITMAP DISCARDABLE "res\\bmp00002.bmp"
+IDB_IENDCAP BITMAP DISCARDABLE "res\\iendcap.bmp"
+IDB_ENDCAP BITMAP DISCARDABLE "res\\endcap.bmp"
+IDB_BEVEL BITMAP DISCARDABLE "res\\bevel.bmp"
+IDB_IBEVEL BITMAP DISCARDABLE "res\\ibevel.bmp"
+IDB_BITMAP_GROUPS BITMAP DISCARDABLE "res\\bmp00003.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Toolbar
+//
+
+IDR_SHADERFRAME TOOLBAR DISCARDABLE 16, 15
+BEGIN
+ BUTTON ID_FILE_OPEN
+ BUTTON ID_FILE_SAVE
+ SEPARATOR
+ BUTTON ID_EDIT_CUT
+ BUTTON ID_EDIT_COPY
+ BUTTON ID_EDIT_PASTE
+END
+
+IDR_TOOLBAR1 TOOLBAR DISCARDABLE 16, 15
+BEGIN
+ BUTTON ID_FILE_OPEN
+ BUTTON ID_FILE_SAVE
+ SEPARATOR
+ BUTTON ID_BRUSH_FLIPX
+ BUTTON ID_BRUSH_ROTATEX
+ BUTTON ID_BRUSH_FLIPY
+ BUTTON ID_BRUSH_ROTATEY
+ BUTTON ID_BRUSH_FLIPZ
+ BUTTON ID_BRUSH_ROTATEZ
+ SEPARATOR
+ BUTTON ID_POPUP_SELECTION
+ SEPARATOR
+ BUTTON ID_SELECTION_CSGSUBTRACT
+ BUTTON ID_SELECTION_MAKEHOLLOW
+ SEPARATOR
+ BUTTON ID_VIEW_CHANGE
+ SEPARATOR
+ BUTTON ID_TEXTURES_POPUP
+ SEPARATOR
+ BUTTON ID_VIEW_CAMERATOGGLE
+ BUTTON ID_VIEW_CAMERAUPDATE
+ BUTTON ID_VIEW_CUBICCLIPPING
+ SEPARATOR
+ BUTTON ID_VIEW_ENTITY
+ SEPARATOR
+ BUTTON ID_VIEW_CLIPPER
+ SEPARATOR
+ BUTTON ID_SELECT_MOUSEROTATE
+ SEPARATOR
+ BUTTON ID_SELECT_MOUSESCALE
+ BUTTON ID_SCALELOCKX
+ BUTTON ID_SCALELOCKY
+ BUTTON ID_SCALELOCKZ
+END
+
+IDR_TOOLBAR_SCALELOCK TOOLBAR DISCARDABLE 16, 15
+BEGIN
+ BUTTON ID_SCALELOCKX
+ BUTTON ID_SCALELOCKY
+ BUTTON ID_SCALELOCKZ
+END
+
+IDR_TOOLBAR_ADVANCED TOOLBAR DISCARDABLE 16, 15
+BEGIN
+ BUTTON ID_FILE_OPEN
+ BUTTON ID_FILE_SAVE
+ SEPARATOR
+ BUTTON ID_BRUSH_FLIPX
+ BUTTON ID_BRUSH_ROTATEX
+ BUTTON ID_BRUSH_FLIPY
+ BUTTON ID_BRUSH_ROTATEY
+ BUTTON ID_BRUSH_FLIPZ
+ BUTTON ID_BRUSH_ROTATEZ
+ SEPARATOR
+ BUTTON ID_SELECTION_SELECTCOMPLETETALL
+ BUTTON ID_SELECTION_SELECTTOUCHING
+ BUTTON ID_SELECTION_SELECTPARTIALTALL
+ BUTTON ID_SELECTION_SELECTINSIDE
+ SEPARATOR
+ BUTTON ID_SELECTION_CSGSUBTRACT
+ BUTTON ID_SELECTION_CSGMERGE
+ BUTTON ID_SELECTION_MAKEHOLLOW
+ BUTTON ID_VIEW_CLIPPER
+ SEPARATOR
+ BUTTON ID_VIEW_CHANGE
+ BUTTON ID_TEXTURES_POPUP
+ BUTTON ID_VIEW_CUBICCLIPPING
+ SEPARATOR
+ BUTTON ID_SELECT_MOUSEROTATE
+ SEPARATOR
+ BUTTON ID_SELECT_MOUSESCALE
+ SEPARATOR
+ BUTTON ID_SCALELOCKX
+ BUTTON ID_SCALELOCKY
+ BUTTON ID_SCALELOCKZ
+ SEPARATOR
+ BUTTON ID_DONTSELECTCURVE
+ BUTTON ID_PATCH_SHOWBOUNDINGBOX
+ BUTTON ID_PATCH_WIREFRAME
+ BUTTON ID_PATCH_BEND
+ BUTTON ID_PATCH_INSDEL
+ BUTTON ID_CURVE_CAP
+ BUTTON ID_PATCH_WELD
+ BUTTON ID_PATCH_DRILLDOWN
+ SEPARATOR
+ BUTTON ID_SHOW_ENTITIES
+ SEPARATOR
+ BUTTON ID_SPLINES_POPUP
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_SHADERFRAME MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
+ MENUITEM "Save &As...", ID_FILE_SAVE_AS
+ MENUITEM SEPARATOR
+ MENUITEM "Close", ID_FILE_CLOSE
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
+ MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
+ MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
+ MENUITEM "Delete\tDel", ID_EDIT_CLEAR
+ MENUITEM SEPARATOR
+ MENUITEM "&Find...", ID_EDIT_FIND
+ MENUITEM "Find &Next\tF3", ID_EDIT_REPEAT
+ MENUITEM "&Replace...", ID_EDIT_REPLACE
+ MENUITEM SEPARATOR
+ MENUITEM "Select &All", ID_EDIT_SELECT_ALL
+ END
+END
+
+IDR_MAINFRAME MENU PRELOAD DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM SEPARATOR
+ MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP
+ MENUITEM SEPARATOR
+ MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_APP_EXIT
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
+ MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About Radiant...", ID_APP_ABOUT
+ END
+END
+
+IDR_RADIANTYPE MENU PRELOAD DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New\tCtrl+N", ID_FILE_NEW
+ MENUITEM "&Open...\tCtrl+O", ID_FILE_OPEN
+ MENUITEM "&Close", ID_FILE_CLOSE
+ MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE
+ MENUITEM "Save &As...", ID_FILE_SAVE_AS
+ MENUITEM SEPARATOR
+ MENUITEM "&Print...\tCtrl+P", ID_FILE_PRINT
+ MENUITEM "Print Pre&view", ID_FILE_PRINT_PREVIEW
+ MENUITEM "P&rint Setup...", ID_FILE_PRINT_SETUP
+ MENUITEM SEPARATOR
+ MENUITEM "Recent File", ID_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_APP_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Undo\tCtrl+Z", ID_EDIT_UNDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t\tCtrl+X", ID_EDIT_CUT
+ MENUITEM "&Copy\tCtrl+C", ID_EDIT_COPY
+ MENUITEM "&Paste\tCtrl+V", ID_EDIT_PASTE
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Toolbar", ID_VIEW_TOOLBAR
+ MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&New Window", ID_WINDOW_NEW
+ MENUITEM "&Cascade", ID_WINDOW_CASCADE
+ MENUITEM "&Tile", ID_WINDOW_TILE_HORZ
+ MENUITEM "&Arrange Icons", ID_WINDOW_ARRANGE
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About Radiant...", ID_APP_ABOUT
+ END
+END
+
+IDR_MENU_QUAKE3 MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New map", ID_FILE_NEW
+ MENUITEM SEPARATOR
+ MENUITEM "&Open...", ID_FILE_OPEN
+ MENUITEM "&Load...", ID_FILE_IMPORTMAP
+ MENUITEM "&Save", ID_FILE_SAVE
+ MENUITEM "Save &as...", ID_FILE_SAVEAS
+ MENUITEM "Save s&elected...", ID_FILE_EXPORTMAP
+ MENUITEM SEPARATOR
+ MENUITEM "Save re&gion...", ID_FILE_SAVEREGION
+ MENUITEM SEPARATOR
+ MENUITEM "New p&roject...", ID_FILE_NEWPROJECT
+ MENUITEM "Load &project...", ID_FILE_LOADPROJECT
+ MENUITEM "Pro&ject settings...", ID_FILE_PROJECTSETTINGS
+ MENUITEM SEPARATOR
+ MENUITEM "&Pointfile...", ID_FILE_POINTFILE
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Undo\tCtrl-Z", ID_EDIT_UNDO
+ MENUITEM "&Redo\tShift-Ctrl-Z", ID_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "&Copy\tCtrl-C", ID_EDIT_COPYBRUSH
+ MENUITEM "&Paste\tCtrl-V", ID_EDIT_PASTEBRUSH
+ MENUITEM "&Delete\tBackspace", ID_SELECTION_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "Map Info...", ID_EDIT_MAPINFO
+ MENUITEM "Entity Info...", ID_EDIT_ENTITYINFO
+ MENUITEM SEPARATOR
+ MENUITEM "Brush Scripts...", ID_BRUSH_SCRIPTS
+ MENUITEM SEPARATOR
+ MENUITEM "Load Pre&fab...", ID_EDIT_LOADPREFAB
+ MENUITEM "Save Selection as Prefab...", ID_EDIT_SAVEPREFAB
+ MENUITEM SEPARATOR
+ MENUITEM "Preferences...", ID_PREFS
+ END
+ POPUP "&View"
+ BEGIN
+ POPUP "Toggle"
+ BEGIN
+ MENUITEM "Camera View", ID_TOGGLECAMERA
+ MENUITEM "Console View", ID_TOGGLECONSOLE
+ MENUITEM "Entity View", ID_VIEW_ENTITY
+ MENUITEM "Groups View", ID_VIEW_GROUPS
+ MENUITEM "XY (Top)", ID_TOGGLEVIEW
+ MENUITEM "YZ (Side)", ID_TOGGLEVIEW_YZ
+ MENUITEM "XZ (Front)", ID_TOGGLEVIEW_XZ
+ MENUITEM "Z View", ID_TOGGLEZ
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Center\tEnd", ID_VIEW_CENTER
+ MENUITEM "&Up Floor\tPage Up", ID_VIEW_UPFLOOR
+ MENUITEM "&Down Floor\tPage Down", ID_VIEW_DOWNFLOOR
+ MENUITEM SEPARATOR
+ MENUITEM "&Next (XY, YZ, XY)\tCtrl-TAB", ID_VIEW_NEXTVIEW
+ POPUP "Layout"
+ BEGIN
+ MENUITEM "XY (Top)", ID_VIEW_XY
+ MENUITEM "YZ", ID_VIEW_SIDE
+ MENUITEM "XZ", ID_VIEW_FRONT
+ END
+ POPUP "Zoom"
+ BEGIN
+ MENUITEM "&XY 100%", ID_VIEW_100
+ MENUITEM "XY Zoom &In\tDelete", ID_VIEW_ZOOMIN
+ MENUITEM "XY Zoom &Out\tInsert", ID_VIEW_ZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "&Z 100%", ID_VIEW_Z100
+ MENUITEM "Z Zoo&m In\tctrl-Delete", ID_VIEW_ZZOOMIN
+ MENUITEM "Z Zoom O&ut\tctrl-Insert", ID_VIEW_ZZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "Cubic Clip Zoom In\tctrl-]", ID_VIEW_CUBEIN
+ MENUITEM "Cubic Clip Zoom Out\tctrl-[", ID_VIEW_CUBEOUT
+ END
+ MENUITEM SEPARATOR
+ POPUP "Show"
+ BEGIN
+ MENUITEM "Show &Names", ID_VIEW_SHOWNAMES
+ , CHECKED
+ MENUITEM "Show Blocks", ID_VIEW_SHOWBLOCKS
+ MENUITEM "Show C&oordinates", ID_VIEW_SHOWCOORDINATES
+ , CHECKED
+ MENUITEM "Show &Entities", ID_VIEW_SHOWENT, CHECKED
+ MENUITEM "Show &Path", ID_VIEW_SHOWPATH
+ , CHECKED
+ MENUITEM "Show &Lights", ID_VIEW_SHOWLIGHTS
+ , CHECKED
+ MENUITEM "Show &Water", ID_VIEW_SHOWWATER
+ , CHECKED
+ MENUITEM "Show Clip &Brush", ID_VIEW_SHOWCLIP
+ , CHECKED
+ MENUITEM "Show &Hint Brush", ID_VIEW_SHOWHINT
+ , CHECKED
+ MENUITEM "Show Wor&ld", ID_VIEW_SHOWWORLD
+ , CHECKED
+ MENUITEM "Show Detail\tctrl-D", ID_VIEW_SHOWDETAIL
+ , CHECKED
+ MENUITEM "Show Curves", ID_VIEW_SHOWCURVES
+ , CHECKED
+ MENUITEM "Show Caulk", ID_VIEW_SHOWCAULK
+ , CHECKED
+ MENUITEM "Show Angles", ID_VIEW_SHOWANGLES
+ END
+ POPUP "Hide/Show"
+ BEGIN
+ MENUITEM "Hide Selected", ID_VIEW_HIDESHOW_HIDESELECTED
+
+ MENUITEM "Show Hidden", ID_VIEW_HIDESHOW_SHOWHIDDEN
+
+ END
+ MENUITEM SEPARATOR
+ POPUP "Entities as"
+ BEGIN
+ MENUITEM "Bounding box", ID_VIEW_ENTITIESAS_BOUNDINGBOX
+
+ MENUITEM "Wireframe", ID_VIEW_ENTITIESAS_WIREFRAME
+
+ MENUITEM "Selected Wireframe", ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME
+
+ MENUITEM "Selected Skinned", ID_VIEW_ENTITIESAS_SELECTEDSKINNED
+
+ MENUITEM "Skinned", ID_VIEW_ENTITIESAS_SKINNED
+
+ MENUITEM "Skinned and Boxed", ID_VIEW_ENTITIESAS_SKINNEDANDBOXED
+
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Cubic Clipping", ID_VIEW_CUBICCLIPPING
+ , CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "OpenGL Lighting", ID_VIEW_OPENGLLIGHTING
+ END
+ POPUP "&Selection"
+ BEGIN
+ POPUP "Drag"
+ BEGIN
+ MENUITEM "Drag &Edges", ID_SELECTION_DRAGEDGES
+ MENUITEM "Drag &Vertices", ID_SELECTION_DRAGVERTECIES
+
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Clone", ID_SELECTION_CLONE
+ MENUITEM "Deselect\tEsc", ID_SELECTION_DESELECT
+ MENUITEM SEPARATOR
+ POPUP "Flip"
+ BEGIN
+ MENUITEM "Flip &X", ID_BRUSH_FLIPX
+ MENUITEM "Flip &Y", ID_BRUSH_FLIPY
+ MENUITEM "Flip &Z", ID_BRUSH_FLIPZ
+ END
+ MENUITEM SEPARATOR
+ POPUP "Rotate"
+ BEGIN
+ MENUITEM "Rotate X", ID_BRUSH_ROTATEX
+ MENUITEM "Rotate Y", ID_BRUSH_ROTATEY
+ MENUITEM "Rotate Z", ID_BRUSH_ROTATEZ
+ MENUITEM "Arbitrary rotation...", ID_SELECTION_ARBITRARYROTATION
+
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Scale...", ID_SELECT_SCALE
+ POPUP "CSG"
+ BEGIN
+ MENUITEM "&Hollow", ID_SELECTION_MAKEHOLLOW
+ MENUITEM "&Subtract", ID_SELECTION_CSGSUBTRACT
+ MENUITEM "&Merge", ID_SELECTION_CSGMERGE
+ END
+ MENUITEM SEPARATOR
+ POPUP "Select"
+ BEGIN
+ MENUITEM "Select Complete &Tall", ID_SELECTION_SELECTCOMPLETETALL
+
+ MENUITEM "Select T&ouching", ID_SELECTION_SELECTTOUCHING
+
+ MENUITEM "Select &Partial Tall", ID_SELECTION_SELECTPARTIALTALL
+
+ MENUITEM "Select &Inside", ID_SELECTION_SELECTINSIDE
+
+ END
+ MENUITEM SEPARATOR
+ POPUP "Clipper"
+ BEGIN
+ MENUITEM "Toggle Clipper", ID_VIEW_CLIPPER
+ MENUITEM SEPARATOR
+ MENUITEM "Clip selection", ID_CLIP_SELECTED
+ MENUITEM "Split selectedion", ID_SPLIT_SELECTED
+ MENUITEM "Flip Clip orientation", ID_FLIP_CLIP
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Connect entities", ID_SELECTION_CONNECT
+ MENUITEM "Ungroup entity", ID_SELECTION_UNGROUPENTITY
+ MENUITEM "Make detail", ID_SELECTION_MAKE_DETAIL
+ MENUITEM "Make structural", ID_SELECTION_MAKE_STRUCTURAL
+ END
+ POPUP "&Bsp"
+ BEGIN
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Grid"
+ BEGIN
+ MENUITEM "Grid1\t&1", ID_GRID_1
+ MENUITEM "Grid2\t&2", ID_GRID_2
+ MENUITEM "Grid4\t&3", ID_GRID_4
+ MENUITEM "Grid8\t&4", ID_GRID_8, CHECKED
+ MENUITEM "Grid16\t&5", ID_GRID_16
+ MENUITEM "Grid32\t&6", ID_GRID_32
+ MENUITEM "Grid64\t&7", ID_GRID_64
+ MENUITEM SEPARATOR
+ MENUITEM "Snap to grid", ID_SNAPTOGRID, CHECKED
+ END
+ POPUP "&Textures"
+ BEGIN
+ MENUITEM "Show In &Use\tU", ID_TEXTURES_SHOWINUSE
+ MENUITEM "Show &All\tCtrl-A", ID_TEXTURES_SHOWALL
+ MENUITEM SEPARATOR
+ MENUITEM "&Surface Inspector\tS", ID_TEXTURES_INSPECTOR
+ MENUITEM SEPARATOR
+ POPUP "Render Quality"
+ BEGIN
+ MENUITEM "&Wireframe", ID_TEXTURES_WIREFRAME
+ MENUITEM "&Flat shade", ID_TEXTURES_FLATSHADE
+ MENUITEM "&Nearest", ID_VIEW_NEAREST
+ MENUITEM "Nearest &Mipmap", ID_VIEW_NEARESTMIPMAP
+ MENUITEM "&Linear", ID_VIEW_LINEAR
+ MENUITEM "&Bilinear", ID_VIEW_BILINEAR
+ MENUITEM "B&ilinear Mipmap", ID_VIEW_BILINEARMIPMAP
+ MENUITEM "T&rilinear", ID_VIEW_TRILINEAR
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Find / Replace...", ID_TEXTURE_REPLACEALL
+ MENUITEM SEPARATOR
+ POPUP "Texture Lock"
+ BEGIN
+ MENUITEM "Moves", ID_TOGGLE_LOCK, CHECKED
+ MENUITEM "Rotations", ID_TOGGLE_ROTATELOCK
+ , CHECKED
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Load...", ID_TEXTURES_LOAD
+ POPUP "Shaders"
+ BEGIN
+ MENUITEM "Load All (Reload)", ID_TEXTURES_RELOADSHADERS
+
+ MENUITEM "Show", ID_TEXTURES_SHADERS_SHOW
+ , CHECKED
+ END
+ MENUITEM SEPARATOR
+ POPUP "Flush"
+ BEGIN
+ MENUITEM "All", ID_TEXTURES_FLUSH
+ MENUITEM "Unused", ID_TEXTURES_FLUSH_UNUSED
+ END
+ MENUITEM SEPARATOR
+ POPUP "Texture Window Scale"
+ BEGIN
+ MENUITEM "200%", ID_TEXTURES_TEXTUREWINDOWSCALE_200
+
+ MENUITEM "100%", ID_TEXTURES_TEXTUREWINDOWSCALE_100
+
+ MENUITEM "50%", ID_TEXTURES_TEXTUREWINDOWSCALE_50
+
+ MENUITEM "25%", ID_TEXTURES_TEXTUREWINDOWSCALE_25
+
+ MENUITEM "10%", ID_TEXTURES_TEXTUREWINDOWSCALE_10
+
+ END
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Misc"
+ BEGIN
+ MENUITEM "&Benchmark", ID_MISC_BENCHMARK
+ POPUP "&Colors"
+ BEGIN
+ POPUP "Themes"
+ BEGIN
+ MENUITEM "QE4 Original", ID_COLOR_SETORIGINAL
+ MENUITEM "Q3Radiant Original", ID_COLOR_SETQER
+ MENUITEM "Black and Green", ID_COLOR_SETBLACK
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Texture Background...", ID_TEXTUREBK
+ MENUITEM "Grid Background...", ID_COLORS_XYBK
+ MENUITEM "Grid Major...", ID_COLORS_MAJOR
+ MENUITEM "Grid Minor...", ID_COLORS_MINOR
+ MENUITEM "Grid Text...", ID_COLORS_GRIDTEXT
+ MENUITEM "Grid Block...", ID_COLORS_GRIDBLOCK
+ MENUITEM "Default Brush...", ID_COLORS_BRUSH
+ MENUITEM "Selected Brush...", ID_COLORS_SELECTEDBRUSH
+ MENUITEM "Clipper...", ID_COLORS_CLIPPER
+ MENUITEM "Active View name...", ID_COLORS_VIEWNAME
+ END
+ MENUITEM "&Gamma...", ID_MISC_GAMMA
+ MENUITEM "Find brush...", ID_MISC_FINDBRUSH
+ MENUITEM "Next leak spot\tctrl-l", ID_MISC_NEXTLEAKSPOT
+ MENUITEM "Previous leak spot\tctrl-p", ID_MISC_PREVIOUSLEAKSPOT
+ MENUITEM "&Print XY View", ID_MISC_PRINTXY
+ MENUITEM "&Select Entity Color...\tK", ID_MISC_SELECTENTITYCOLOR
+ END
+ POPUP "&Region"
+ BEGIN
+ MENUITEM "&Off", ID_REGION_OFF
+ MENUITEM "&Set XY", ID_REGION_SETXY
+ MENUITEM "Set &Tall Brush", ID_REGION_SETTALLBRUSH
+ MENUITEM "Set &Brush", ID_REGION_SETBRUSH
+ MENUITEM "Set Se&lected Brushes", ID_REGION_SETSELECTION
+ END
+ POPUP "&Brush"
+ BEGIN
+ MENUITEM "3 sided\tctrl-3", ID_BRUSH_3SIDED
+ MENUITEM "4 sided\tctrl-4", ID_BRUSH_4SIDED
+ MENUITEM "5 sided\tctrl-5", ID_BRUSH_5SIDED
+ MENUITEM "6 sided\tctrl-6", ID_BRUSH_6SIDED
+ MENUITEM "7 sided\tctrl-7", ID_BRUSH_7SIDED
+ MENUITEM "8 sided\tctrl-8", ID_BRUSH_8SIDED
+ MENUITEM "9 sided\tctrl-9", ID_BRUSH_9SIDED
+ MENUITEM SEPARATOR
+ MENUITEM "Arbitrary sided...", ID_BRUSH_ARBITRARYSIDED
+ MENUITEM SEPARATOR
+ POPUP "Primitives"
+ BEGIN
+ MENUITEM "Cone...", ID_BRUSH_MAKECONE
+ MENUITEM "Sphere...", ID_BRUSH_PRIMITIVES_SPHERE
+
+ END
+ END
+ POPUP "&Curve"
+ BEGIN
+ MENUITEM "Cylinder", ID_CURVE_PATCHTUBE
+ POPUP "More Cylinders"
+ BEGIN
+ MENUITEM "Dense Cylinder", ID_CURVE_PATCHDENSETUBE
+ MENUITEM "Very Dense Cylinder", ID_CURVE_PATCHVERYDENSETUBE
+
+ MENUITEM "Square Cylinder", ID_CURVE_PATCHSQUARE
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "End cap", ID_CURVE_PATCHENDCAP
+ MENUITEM "Bevel", ID_CURVE_PATCHBEVEL
+ POPUP "More End caps, Bevels"
+ BEGIN
+ MENUITEM "Square Endcap", ID_CURVE_MOREENDCAPSBEVELS_SQUAREBEVEL
+
+ MENUITEM "Square Bevel", ID_CURVE_MOREENDCAPSBEVELS_SQUAREENDCAP
+
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Cone", ID_CURVE_PATCHCONE
+ MENUITEM "Sphere", ID_CURVE_PRIMITIVES_SPHERE
+ , GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "Simple Patch Mesh...", ID_CURVE_SIMPLEPATCHMESH
+ MENUITEM SEPARATOR
+ POPUP "Insert"
+ BEGIN
+ MENUITEM "Insert (2) Columns", ID_CURVE_INSERT_INSERTCOLUMN
+
+ MENUITEM "Add (2) Columns", ID_CURVE_INSERT_ADDCOLUMN
+
+ MENUITEM SEPARATOR
+ MENUITEM "Insert (2) Rows", ID_CURVE_INSERT_INSERTROW
+
+ MENUITEM "Add (2) Rows", ID_CURVE_INSERT_ADDROW
+ END
+ POPUP "Delete"
+ BEGIN
+ MENUITEM "First (2) Columns", ID_CURVE_DELETE_FIRSTCOLUMN
+
+ MENUITEM "Last (2) Columns", ID_CURVE_DELETE_LASTCOLUMN
+
+ MENUITEM SEPARATOR
+ MENUITEM "First (2) Rows", ID_CURVE_DELETE_FIRSTROW
+ MENUITEM "Last (2) Rows", ID_CURVE_DELETE_LASTROW
+ END
+ MENUITEM SEPARATOR
+ POPUP "Matrix"
+ BEGIN
+ MENUITEM "Invert", ID_CURVE_NEGATIVE
+ POPUP "Re-disperse"
+ BEGIN
+ MENUITEM "Cols", ID_CURVE_REDISPERSE_COLS
+
+ MENUITEM "Rows", ID_CURVE_REDISPERSE_ROWS
+
+ END
+ MENUITEM "Transpose", ID_CURVE_MATRIX_TRANSPOSE
+
+ END
+ MENUITEM SEPARATOR
+ POPUP "Cap"
+ BEGIN
+ MENUITEM "Normal", ID_CURVE_CAP
+ MENUITEM "Inverted Bevel", ID_CURVE_CAP_INVERTEDBEVEL
+
+ MENUITEM "Inverted Endcap", ID_CURVE_CAP_INVERTEDENDCAP
+
+ MENUITEM SEPARATOR
+ MENUITEM "Cycle Cap Texture", ID_CURVE_CYCLECAP
+ END
+ MENUITEM SEPARATOR
+ POPUP "Overlay"
+ BEGIN
+ MENUITEM "Set", ID_CURVE_OVERLAY_SET
+ MENUITEM "Clear", ID_CURVE_OVERLAY_CLEAR
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Thicken...", ID_CURVE_THICKEN
+ END
+ POPUP "&Terrain"
+ BEGIN
+ MENUITEM "Create Terrain from &Brush", ID_TERRAIN_CREATETERRAINFROMBRUSH
+
+ MENUITEM "Raise/Lower Terrain", ID_TERRAIN_RAISELOWERTERRAIN
+ , CHECKED
+ END
+ POPUP "&Plugins"
+ BEGIN
+ MENUITEM "Refresh", ID_PLUGINS_REFRESH
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "Help\tF1", ID_HELP
+ MENUITEM SEPARATOR
+ MENUITEM "Command list...", ID_HELP_COMMANDLIST
+ MENUITEM SEPARATOR
+ MENUITEM "&About...", ID_HELP_ABOUT
+ END
+END
+
+IDR_POPUP_TEXTURE MENU DISCARDABLE
+BEGIN
+ POPUP "Popup"
+ BEGIN
+ MENUITEM "&Wireframe", ID_TEXTURES_WIREFRAME
+ MENUITEM "&Flat shade", ID_TEXTURES_FLATSHADE
+ MENUITEM "&Nearest", ID_VIEW_NEAREST
+ MENUITEM "Nearest &Mipmap", ID_VIEW_NEARESTMIPMAP
+ MENUITEM "&Linear", ID_VIEW_LINEAR
+ MENUITEM "&Bilinear", ID_VIEW_BILINEAR
+ MENUITEM "B&ilinear Mipmap", ID_VIEW_BILINEARMIPMAP
+ MENUITEM "T&rilinear", ID_VIEW_TRILINEAR
+ END
+END
+
+IDR_POPUP_SELECTION MENU DISCARDABLE
+BEGIN
+ POPUP "Popup"
+ BEGIN
+ MENUITEM "Select Complete &Tall", ID_SELECTION_SELECTCOMPLETETALL
+
+ MENUITEM "Select T&ouching", ID_SELECTION_SELECTTOUCHING
+ MENUITEM "Select &Partial Tall", ID_SELECTION_SELECTPARTIALTALL
+
+ MENUITEM "Select &Inside", ID_SELECTION_SELECTINSIDE
+ END
+END
+
+IDR_POPUP_VIEW MENU DISCARDABLE
+BEGIN
+ POPUP "Popup"
+ BEGIN
+ MENUITEM "XY (Top)", ID_VIEW_XY
+ MENUITEM "XZ", ID_VIEW_SIDE
+ MENUITEM "YZ", ID_VIEW_FRONT
+ END
+END
+
+IDR_MENU_DROP MENU DISCARDABLE
+BEGIN
+ POPUP "Drop"
+ BEGIN
+ MENUITEM SEPARATOR
+ POPUP "Select"
+ BEGIN
+ MENUITEM "Select Complete &Tall", ID_SELECTION_SELECTCOMPLETETALL
+
+ MENUITEM "Select T&ouching", ID_SELECTION_SELECTTOUCHING
+
+ MENUITEM "Select &Partial Tall", ID_SELECTION_SELECTPARTIALTALL
+
+ MENUITEM "Select &Inside", ID_SELECTION_SELECTINSIDE
+
+ END
+ MENUITEM SEPARATOR
+ POPUP "Group"
+ BEGIN
+ MENUITEM "Add to...", ID_DROP_GROUP_ADDTO
+ MENUITEM "Remove", ID_DROP_GROUP_REMOVE
+ MENUITEM SEPARATOR
+ MENUITEM "Name...", ID_DROP_GROUP_NAME
+ MENUITEM SEPARATOR
+ MENUITEM "New Group...", ID_DROP_GROUP_NEWGROUP
+ END
+ MENUITEM "Ungroup entity", ID_SELECTION_UNGROUPENTITY
+ MENUITEM "Make detail", ID_SELECTION_MAKE_DETAIL
+ MENUITEM "Make structural", ID_SELECTION_MAKE_STRUCTURAL
+ END
+END
+
+IDR_MENU1 MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New map", ID_FILE_NEW
+ MENUITEM SEPARATOR
+ MENUITEM "&Open...", ID_FILE_OPEN
+ MENUITEM "&Load...", ID_FILE_IMPORTMAP
+ MENUITEM "&Save", ID_FILE_SAVE
+ MENUITEM "Save &as...", ID_FILE_SAVEAS
+ MENUITEM "Save s&elected...", ID_FILE_EXPORTMAP
+ MENUITEM SEPARATOR
+ MENUITEM "Save re&gion...", ID_FILE_SAVEREGION
+ MENUITEM SEPARATOR
+ MENUITEM "New p&roject...", ID_FILE_NEWPROJECT
+ MENUITEM "Load &project...", ID_FILE_LOADPROJECT
+ MENUITEM "Pro&ject settings...", ID_FILE_PROJECTSETTINGS
+ MENUITEM SEPARATOR
+ MENUITEM "&Pointfile...", ID_FILE_POINTFILE
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", ID_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Undo (no really :-)", ID_EDIT_UNDO
+ MENUITEM SEPARATOR
+ MENUITEM "&Copy brush", ID_EDIT_COPYBRUSH
+ MENUITEM "&Paste brush", ID_EDIT_PASTEBRUSH
+ MENUITEM SEPARATOR
+ MENUITEM "Map Info...", ID_EDIT_MAPINFO
+ MENUITEM "Entity Info...", ID_EDIT_ENTITYINFO
+ MENUITEM SEPARATOR
+ MENUITEM "Brush Scripts...", ID_BRUSH_SCRIPTS
+ MENUITEM SEPARATOR
+ MENUITEM "Load Pre&fab...", ID_EDIT_LOADPREFAB
+ MENUITEM SEPARATOR
+ MENUITEM "Preferences...", ID_PREFS
+ END
+ POPUP "&View"
+ BEGIN
+ POPUP "Toggle"
+ BEGIN
+ MENUITEM "Camera View", ID_TOGGLECAMERA
+ MENUITEM "Console View", ID_TOGGLECONSOLE
+ MENUITEM "Entity View", ID_VIEW_ENTITY
+ MENUITEM "XY (Top)", ID_TOGGLEVIEW
+ MENUITEM "YZ (Side)", ID_TOGGLEVIEW_YZ
+ MENUITEM "XZ (Front)", ID_TOGGLEVIEW_XZ
+ MENUITEM "Z View", ID_TOGGLEZ
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Center\tEnd", ID_VIEW_CENTER
+ MENUITEM "&Up Floor\tPage Up", ID_VIEW_UPFLOOR
+ MENUITEM "&Down Floor\tPage Down", ID_VIEW_DOWNFLOOR
+ MENUITEM SEPARATOR
+ MENUITEM "&Next (XY, YZ, XY)\tCtrl-TAB", ID_VIEW_NEXTVIEW
+ POPUP "Layout"
+ BEGIN
+ MENUITEM "XY (Top)", ID_VIEW_XY
+ MENUITEM "YZ", ID_VIEW_SIDE
+ MENUITEM "XZ", ID_VIEW_FRONT
+ END
+ POPUP "Zoom"
+ BEGIN
+ MENUITEM "&XY 100%", ID_VIEW_100
+ MENUITEM "XY Zoom &In\tDelete", ID_VIEW_ZOOMIN
+ MENUITEM "XY Zoom &Out\tInsert", ID_VIEW_ZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "&Z 100%", ID_VIEW_Z100
+ MENUITEM "Z Zoo&m In\tctrl-Delete", ID_VIEW_ZZOOMIN
+ MENUITEM "Z Zoom O&ut\tctrl-Insert", ID_VIEW_ZZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "Cubic Clip Zoom In\tctrl-]", ID_VIEW_CUBEIN
+ MENUITEM "Cubic Clip Zoom Out\tctrl-[", ID_VIEW_CUBEOUT
+ END
+ MENUITEM SEPARATOR
+ POPUP "Show"
+ BEGIN
+ MENUITEM "Show &Names", ID_VIEW_SHOWNAMES
+ , CHECKED
+ MENUITEM "Show Blocks", ID_VIEW_SHOWBLOCKS
+ MENUITEM "Show C&oordinates", ID_VIEW_SHOWCOORDINATES
+ , CHECKED
+ MENUITEM "Show &Entities", ID_VIEW_SHOWENT, CHECKED
+ MENUITEM "Show &Path", ID_VIEW_SHOWPATH
+ , CHECKED
+ MENUITEM "Show &Lights", ID_VIEW_SHOWLIGHTS
+ , CHECKED
+ MENUITEM "Show &Water", ID_VIEW_SHOWWATER
+ , CHECKED
+ MENUITEM "Show Clip &Brush", ID_VIEW_SHOWCLIP
+ , CHECKED
+ MENUITEM "Show Wor&ld", ID_VIEW_SHOWWORLD
+ , CHECKED
+ MENUITEM "Show Detail\tctrl-D", ID_VIEW_SHOWDETAIL
+ , CHECKED
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Cubic Clipping", ID_VIEW_CUBICCLIPPING
+ , CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "Dynamic Lighting", ID_DYNAMIC_LIGHTING
+ END
+ POPUP "&Selection"
+ BEGIN
+ POPUP "Drag"
+ BEGIN
+ MENUITEM "Drag &Edges", ID_SELECTION_DRAGEDGES
+ MENUITEM "Drag &Vertices", ID_SELECTION_DRAGVERTECIES
+
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Clone", ID_SELECTION_CLONE
+ MENUITEM "Deselect", ID_SELECTION_DESELECT
+ MENUITEM "&Delete", ID_SELECTION_DELETE
+ MENUITEM SEPARATOR
+ POPUP "Flip"
+ BEGIN
+ MENUITEM "Flip &X", ID_BRUSH_FLIPX
+ MENUITEM "Flip &Y", ID_BRUSH_FLIPY
+ MENUITEM "Flip &Z", ID_BRUSH_FLIPZ
+ END
+ MENUITEM SEPARATOR
+ POPUP "Rotate"
+ BEGIN
+ MENUITEM "Rotate X", ID_BRUSH_ROTATEX
+ MENUITEM "Rotate Y", ID_BRUSH_ROTATEY
+ MENUITEM "Rotate Z", ID_BRUSH_ROTATEZ
+ MENUITEM "Arbitrary rotation...", ID_SELECTION_ARBITRARYROTATION
+
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Scale...", ID_SELECT_SCALE
+ POPUP "CSG"
+ BEGIN
+ MENUITEM "Make &Hollow", ID_SELECTION_MAKEHOLLOW
+ MENUITEM "CSG &Subtract", ID_SELECTION_CSGSUBTRACT
+ MENUITEM "CSG &Add", ID_SELECTION_CSGADD
+ END
+ MENUITEM SEPARATOR
+ POPUP "Select"
+ BEGIN
+ MENUITEM "Select Complete &Tall", ID_SELECTION_SELECTCOMPLETETALL
+
+ MENUITEM "Select T&ouching", ID_SELECTION_SELECTTOUCHING
+
+ MENUITEM "Select &Partial Tall", ID_SELECTION_SELECTPARTIALTALL
+
+ MENUITEM "Select &Inside", ID_SELECTION_SELECTINSIDE
+
+ MENUITEM "Nudge Left", ID_SELECTION_SELECT_NUDGELEFT
+
+ MENUITEM "Nudge Right", ID_SELECTION_SELECT_NUDGERIGHT
+
+ MENUITEM "Nudge Up", ID_SELECTION_SELECT_NUDGEUP
+
+ MENUITEM "Nudge Down", ID_SELECTION_SELECT_NUDGEDOWN
+
+ END
+ MENUITEM SEPARATOR
+ POPUP "Clipper"
+ BEGIN
+ MENUITEM "Toggle Clipper", ID_VIEW_CLIPPER
+ MENUITEM SEPARATOR
+ MENUITEM "Clip selection", ID_CLIP_SELECTED
+ MENUITEM "Split selectedion", ID_SPLIT_SELECTED
+ MENUITEM "Flip Clip orientation", ID_FLIP_CLIP
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Connect entities", ID_SELECTION_CONNECT
+ MENUITEM "Ungroup entity", ID_SELECTION_UNGROUPENTITY
+ MENUITEM "Make detail", ID_SELECTION_MAKE_DETAIL
+ MENUITEM "Make structural", ID_SELECTION_MAKE_STRUCTURAL
+ END
+ POPUP "&Bsp"
+ BEGIN
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Grid"
+ BEGIN
+ MENUITEM "Grid1\t&1", ID_GRID_1
+ MENUITEM "Grid2\t&2", ID_GRID_2
+ MENUITEM "Grid4\t&3", ID_GRID_4
+ MENUITEM "Grid8\t&4", ID_GRID_8, CHECKED
+ MENUITEM "Grid16\t&5", ID_GRID_16
+ MENUITEM "Grid32\t&6", ID_GRID_32
+ MENUITEM "Grid64\t&7", ID_GRID_64
+ MENUITEM SEPARATOR
+ MENUITEM "Snap to grid", ID_SNAPTOGRID, CHECKED
+ END
+ POPUP "&Textures"
+ BEGIN
+ MENUITEM "Show In &Use\tU", ID_TEXTURES_SHOWINUSE
+ MENUITEM "&Surface Inspector\tS", ID_TEXTURES_INSPECTOR
+ MENUITEM SEPARATOR
+ POPUP "Render Quality"
+ BEGIN
+ MENUITEM "&Wireframe", ID_TEXTURES_WIREFRAME
+ MENUITEM "&Flat shade", ID_TEXTURES_FLATSHADE
+ MENUITEM "&Nearest", ID_VIEW_NEAREST
+ MENUITEM "Nearest &Mipmap", ID_VIEW_NEARESTMIPMAP
+ MENUITEM "&Linear", ID_VIEW_LINEAR
+ MENUITEM "&Bilinear", ID_VIEW_BILINEAR
+ MENUITEM "B&ilinear Mipmap", ID_VIEW_BILINEARMIPMAP
+ MENUITEM "T&rilinear", ID_VIEW_TRILINEAR
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "Find / Replace...", ID_TEXTURE_REPLACEALL
+ MENUITEM SEPARATOR
+ MENUITEM "Move Texture Lock", ID_TOGGLE_LOCK, CHECKED
+ MENUITEM "Rotation Texture Lock", ID_TOGGLE_ROTATELOCK
+ , CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "Load...", ID_TEXTURES_LOAD
+ MENUITEM "Load from List.. ", ID_TEXTURES_LOADLIST
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Misc"
+ BEGIN
+ MENUITEM "&Benchmark", ID_MISC_BENCHMARK
+ POPUP "&Colors"
+ BEGIN
+ POPUP "Themes"
+ BEGIN
+ MENUITEM "QE4 Original", ID_COLOR_SETORIGINAL
+ MENUITEM "Q3Radiant Original", ID_COLOR_SETQER
+ MENUITEM "Black and Green", ID_COLOR_SETBLACK
+ END
+ MENUITEM SEPARATOR
+ MENUITEM "&Texture Background...", ID_TEXTUREBK
+ MENUITEM "Grid Background...", ID_COLORS_XYBK
+ MENUITEM "Grid Major...", ID_COLORS_MAJOR
+ MENUITEM "Grid Minor...", ID_COLORS_MINOR
+ MENUITEM "Grid Text...", ID_COLORS_GRIDTEXT
+ MENUITEM "Grid Block...", ID_COLORS_GRIDBLOCK
+ MENUITEM "Default Brush...", ID_COLORS_BRUSH
+ MENUITEM "Selected Brush...", ID_COLORS_SELECTEDBRUSH
+ MENUITEM "Clipper...", ID_COLORS_CLIPPER
+ MENUITEM "Active View name...", ID_COLORS_VIEWNAME
+ END
+ MENUITEM "&Gamma...", ID_MISC_GAMMA
+ MENUITEM "Find brush...", ID_MISC_FINDBRUSH
+ MENUITEM "Next leak spot\tctrl-l", ID_MISC_NEXTLEAKSPOT
+ MENUITEM "Previous leak spot\tctrl-p", ID_MISC_PREVIOUSLEAKSPOT
+ MENUITEM "&Print XY View", ID_MISC_PRINTXY
+ MENUITEM "&Select Entity Color...\tK", ID_MISC_SELECTENTITYCOLOR
+ MENUITEM "Convert old curves", ID_CONVERTCURVES
+ END
+ POPUP "&Region"
+ BEGIN
+ MENUITEM "&Off", ID_REGION_OFF
+ MENUITEM "&Set XY", ID_REGION_SETXY
+ MENUITEM "Set &Tall Brush", ID_REGION_SETTALLBRUSH
+ MENUITEM "Set &Brush", ID_REGION_SETBRUSH
+ MENUITEM "Set Se&lected Brushes", ID_REGION_SETSELECTION
+ END
+ POPUP "&Brush"
+ BEGIN
+ MENUITEM "3 sided\tctrl-3", ID_BRUSH_3SIDED
+ MENUITEM "4 sided\tctrl-4", ID_BRUSH_4SIDED
+ MENUITEM "5 sided\tctrl-5", ID_BRUSH_5SIDED
+ MENUITEM "6 sided\tctrl-6", ID_BRUSH_6SIDED
+ MENUITEM "7 sided\tctrl-7", ID_BRUSH_7SIDED
+ MENUITEM "8 sided\tctrl-8", ID_BRUSH_8SIDED
+ MENUITEM "9 sided\tctrl-9", ID_BRUSH_9SIDED
+ MENUITEM SEPARATOR
+ MENUITEM "Arbitrary sided...", ID_BRUSH_ARBITRARYSIDED
+ MENUITEM SEPARATOR
+ POPUP "Primitives"
+ BEGIN
+ MENUITEM "Cone...", ID_BRUSH_MAKECONE
+ END
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "Command list...", ID_HELP_COMMANDLIST
+ MENUITEM SEPARATOR
+ MENUITEM "&About...", ID_HELP_ABOUT
+ END
+END
+
+IDR_POPUP_ENTITY MENU DISCARDABLE
+BEGIN
+ POPUP "Popup"
+ BEGIN
+ MENUITEM "Bounding box", ID_VIEW_ENTITIESAS_BOUNDINGBOX
+
+ MENUITEM "Wireframe", ID_VIEW_ENTITIESAS_WIREFRAME
+ MENUITEM "Selected Wireframe", ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME
+
+ MENUITEM "Selected Skinned", ID_VIEW_ENTITIESAS_SELECTEDSKINNED
+
+ MENUITEM "Skinned", ID_VIEW_ENTITIESAS_SKINNED
+ MENUITEM "Skinned and Boxed", ID_VIEW_ENTITIESAS_SKINNEDANDBOXED
+
+ END
+END
+
+IDR_POPUP_GROUP MENU DISCARDABLE
+BEGIN
+ POPUP "Popup"
+ BEGIN
+ MENUITEM "XY (Top)", ID_VIEW_XY
+ MENUITEM "XZ", ID_VIEW_SIDE
+ MENUITEM "YZ", ID_VIEW_FRONT
+ END
+END
+
+IDR_POPUP_SPLINE MENU DISCARDABLE
+BEGIN
+ POPUP "Popup"
+ BEGIN
+ POPUP "New Camera"
+ BEGIN
+ MENUITEM "Fixed", ID_POPUP_NEWCAMERA_FIXED
+ MENUITEM "Interpolated", ID_POPUP_NEWCAMERA_INTERPOLATED
+
+ MENUITEM "Spline", ID_POPUP_NEWCAMERA_SPLINE
+
+ END
+ MENUITEM "Camera Inspector...", ID_SPLINES_EDIT
+ MENUITEM SEPARATOR
+ MENUITEM "Test Camera", ID_SPLINE_TEST
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ "3", ID_BRUSH_3SIDED, VIRTKEY, CONTROL, NOINVERT
+ "4", ID_BRUSH_4SIDED, VIRTKEY, CONTROL, NOINVERT
+ "5", ID_BRUSH_5SIDED, VIRTKEY, CONTROL, NOINVERT
+ "6", ID_BRUSH_6SIDED, VIRTKEY, CONTROL, NOINVERT
+ "7", ID_BRUSH_7SIDED, VIRTKEY, CONTROL, NOINVERT
+ "8", ID_BRUSH_8SIDED, VIRTKEY, CONTROL, NOINVERT
+ "9", ID_BRUSH_9SIDED, VIRTKEY, CONTROL, NOINVERT
+ "D", ID_VIEW_SHOWDETAIL, VIRTKEY, CONTROL, NOINVERT
+ "K", ID_SELECTION_CONNECT, VIRTKEY, CONTROL, NOINVERT
+ "L", ID_MISC_NEXTLEAKSPOT, VIRTKEY, CONTROL, NOINVERT
+ "M", ID_SELECTION_MAKE_DETAIL, VIRTKEY, CONTROL, NOINVERT
+ "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "P", ID_MISC_PREVIOUSLEAKSPOT, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ VK_DELETE, ID_VIEW_ZZOOMIN, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_VIEW_ZZOOMOUT, VIRTKEY, CONTROL, NOINVERT
+ "X", ID_FILE_EXIT, VIRTKEY, CONTROL, NOINVERT
+END
+
+IDR_MAINFRAME ACCELERATORS DISCARDABLE
+BEGIN
+ "7", ID_BRUSH_7SIDED, VIRTKEY, CONTROL, NOINVERT
+ "8", ID_BRUSH_8SIDED, VIRTKEY, CONTROL, NOINVERT
+ "9", ID_BRUSH_9SIDED, VIRTKEY, CONTROL, NOINVERT
+ "D", ID_VIEW_SHOWDETAIL, VIRTKEY, CONTROL, NOINVERT
+ "K", ID_SELECTION_CONNECT, VIRTKEY, CONTROL, NOINVERT
+ "L", ID_MISC_NEXTLEAKSPOT, VIRTKEY, CONTROL, NOINVERT
+ "M", ID_SELECTION_MAKE_DETAIL, VIRTKEY, CONTROL, NOINVERT
+ "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "P", ID_MISC_PREVIOUSLEAKSPOT, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ VK_DELETE, ID_VIEW_ZZOOMIN, VIRTKEY, CONTROL, NOINVERT
+ VK_DOWN, ID_SELECTION_SELECT_NUDGEDOWN, VIRTKEY, ALT, NOINVERT
+ VK_INSERT, ID_VIEW_ZZOOMOUT, VIRTKEY, CONTROL, NOINVERT
+ "X", ID_FILE_EXIT, VIRTKEY, CONTROL, NOINVERT
+END
+
+IDR_ACCEL_SURFACE ACCELERATORS DISCARDABLE
+BEGIN
+ VK_ESCAPE, ID_BYEBYE, VIRTKEY, NOINVERT
+END
+
+IDR_MINIACCEL ACCELERATORS DISCARDABLE
+BEGIN
+ VK_DOWN, ID_SELECTION_SELECT_NUDGEDOWN, VIRTKEY, ALT, NOINVERT
+ VK_LEFT, ID_SELECTION_SELECT_NUDGELEFT, VIRTKEY, ALT, NOINVERT
+ VK_RIGHT, ID_SELECTION_SELECT_NUDGERIGHT, VIRTKEY, ALT, NOINVERT
+ VK_UP, ID_SELECTION_SELECT_NUDGEUP, VIRTKEY, ALT, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_FINDTEXTURE DIALOG DISCARDABLE 0, 0, 129, 53
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Find Texture"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,10,30,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,70,30,50,14
+ EDITTEXT IDC_EDIT1,10,10,110,14,ES_AUTOHSCROLL
+END
+
+IDD_ENTITY DIALOGEX 0, 0, 234, 355
+STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS |
+ WS_CAPTION | WS_THICKFRAME
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+CAPTION "Entity"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LISTBOX IDC_E_LIST,5,5,180,94,LBS_SORT | LBS_NOINTEGRALHEIGHT |
+ LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP,
+ WS_EX_CLIENTEDGE
+ EDITTEXT IDC_E_COMMENT,5,102,180,45,ES_MULTILINE | ES_READONLY |
+ WS_VSCROLL,WS_EX_CLIENTEDGE
+ PUSHBUTTON "135",IDC_E_135,5,276,15,15
+ PUSHBUTTON "180",IDC_E_180,5,292,15,15
+ PUSHBUTTON "225",IDC_E_225,5,306,15,15
+ PUSHBUTTON "270",IDC_E_270,21,306,15,15
+ PUSHBUTTON "90",IDC_E_90,21,276,15,15
+ PUSHBUTTON "45",IDC_E_45,35,276,15,15
+ PUSHBUTTON "360",IDC_E_0,35,292,15,15
+ PUSHBUTTON "315",IDC_E_315,35,306,15,15
+ PUSHBUTTON "Up",IDC_E_UP,60,281,15,15
+ PUSHBUTTON "Dn",IDC_E_DOWN,60,297,15,15
+ CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,151,50,8
+ CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,161,50,8
+ CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,171,50,8
+ CONTROL "",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,181,50,8
+ CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,151,50,8
+ CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,161,50,8
+ CONTROL "",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,171,50,8
+ CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,181,50,8
+ CONTROL "!Easy",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 125,151,50,8
+ CONTROL "!Medium",IDC_CHECK10,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,125,161,50,8
+ CONTROL "!Hard",IDC_CHECK11,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,125,171,50,10
+ CONTROL "!DeathMatch",IDC_CHECK12,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,125,181,55,10
+ LISTBOX IDC_E_PROPS,5,192,180,50,LBS_SORT | LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
+ WS_VSCROLL | WS_TABSTOP,WS_EX_CLIENTEDGE
+ PUSHBUTTON "Del Key/Pair",IDC_E_DELPROP,105,281,45,15
+ EDITTEXT IDC_E_STATUS,83,298,95,30,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
+ LTEXT "Key",IDC_STATIC_KEY,5,246,25,10
+ LTEXT "Value",IDC_STATIC_VALUE,5,262,25,10
+ EDITTEXT IDC_E_KEY_FIELD,40,245,145,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_E_VALUE_FIELD,40,261,145,12,ES_AUTOHSCROLL
+ PUSHBUTTON "Hide",IDC_BTN_HIDE,190,328,7,6
+ PUSHBUTTON "Sound...",IDC_BTN_ASSIGNSOUND,198,247,36,11
+ PUSHBUTTON "Model...",IDC_BTN_ASSIGNMODEL,198,264,36,11
+ CONTROL "Tab1",IDC_TAB_MODE,"SysTabControl32",TCS_BOTTOM |
+ WS_BORDER,3,338,223,14
+END
+
+IDD_GAMMA DIALOGEX 0, 0, 135, 94
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Gamma"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_G_EDIT,5,8,46,13,ES_AUTOHSCROLL,WS_EX_CLIENTEDGE
+ DEFPUSHBUTTON "OK",IDOK,91,5,39,14
+ PUSHBUTTON "Cancel",IDCANCEL,91,23,39,14
+ LTEXT "0.0 is brightest\n1.0 is darkest\n\nYou must restart for the settings to take effect",
+ IDC_STATIC,7,25,61,55
+END
+
+IDD_FINDBRUSH DIALOGEX 0, 0, 127, 76
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Find brush"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,5,55,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,65,55,50,14
+ EDITTEXT IDC_FIND_ENTITY,80,15,46,13,ES_AUTOHSCROLL,
+ WS_EX_CLIENTEDGE
+ EDITTEXT IDC_FIND_BRUSH,80,30,46,13,ES_AUTOHSCROLL,
+ WS_EX_CLIENTEDGE
+ LTEXT "Entity number",IDC_STATIC,10,15,60,8
+ LTEXT "Brush number",IDC_STATIC,10,30,65,8
+END
+
+IDD_ROTATE DIALOG DISCARDABLE 0, 0, 129, 65
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Arbitrary rotation"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_ROTX,23,3,29,14,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,52,3,11,14
+ EDITTEXT IDC_ROTY,23,21,29,14,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN2,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,53,21,11,14
+ EDITTEXT IDC_ROTZ,23,39,29,14,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN3,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,53,39,11,14
+ DEFPUSHBUTTON "OK",IDOK,82,3,39,14
+ PUSHBUTTON "Cancel",IDCANCEL,82,19,39,14
+ PUSHBUTTON "Apply",ID_APPLY,82,39,39,14
+ RTEXT "X",IDC_STATIC,8,6,8,8
+ RTEXT "Y",IDC_STATIC,8,24,8,8
+ RTEXT "Z",IDC_STATIC,8,42,8,8
+END
+
+IDD_SIDES DIALOGEX 0, 0, 130, 47
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Arbitrrary sides"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_SIDES,27,6,40,14,ES_AUTOHSCROLL,WS_EX_CLIENTEDGE
+ DEFPUSHBUTTON "OK",IDOK,85,4,41,14
+ PUSHBUTTON "Cancel",IDCANCEL,85,22,41,14
+ LTEXT "Sides:",IDC_STATIC,6,8,20,8
+END
+
+IDD_ABOUT DIALOG DISCARDABLE 0, 0, 275, 223
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Q3Radiant"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,236,7,35,14
+ CONTROL 127,IDC_STATIC,"Static",SS_BITMAP | SS_CENTERIMAGE |
+ SS_REALSIZEIMAGE | SS_SUNKEN | WS_BORDER,7,7,87,80
+ GROUPBOX "OpenGL Properties",IDC_STATIC,5,93,265,56
+ LTEXT "Vendor:\t\tWHOEVER",IDC_ABOUT_GLVENDOR,10,101,253,10
+ LTEXT "Version:\t\t1.1",IDC_ABOUT_GLVERSION,10,111,249,10
+ LTEXT "Renderer:\tWHATEVER",IDC_ABOUT_GLRENDERER,10,121,253,24
+ GROUPBOX "OpenGL Extensions",IDC_STATIC,5,152,265,65
+ CONTROL "Q3 Radiant 1.0 Beta build 200f\nCopyright ©1999, 2005 Id Software, Inc.\n\n",
+ IDC_STATIC,"Static",SS_LEFTNOWORDWRAP,99,7,132,78
+ EDITTEXT IDC_ABOUT_GLEXTENSIONS,10,162,256,53,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_READONLY | WS_DISABLED | NOT
+ WS_BORDER
+END
+
+IDD_SURFACE DIALOGEX 400, 100, 412, 213
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Surface inspector"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_TEXTURE,59,7,107,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_HSHIFT,121,25,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_HSHIFT,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,155,25,11,14
+ EDITTEXT IDC_VSHIFT,121,41,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_VSHIFT,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,155,41,11,14
+ EDITTEXT IDC_HSCALE,121,58,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_HSCALE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,155,58,11,14
+ EDITTEXT IDC_VSCALE,121,75,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_VSCALE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,155,75,11,14
+ EDITTEXT IDC_ROTATE,121,92,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_ROTATE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,155,91,11,14
+ EDITTEXT IDC_VALUE,104,110,62,12,ES_AUTOHSCROLL
+ PUSHBUTTON "CAP",IDC_BTN_PATCHDETAILS,11,174,34,12
+ CONTROL "light",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,10,41,8
+ CONTROL "slick",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,22,41,8
+ CONTROL "sky",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,34,41,8
+ CONTROL "warp",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,46,41,8
+ CONTROL "trans33",IDC_CHECK5,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,184,58,41,8
+ CONTROL "trans66",IDC_CHECK6,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,184,70,41,8
+ CONTROL "flowing",IDC_CHECK7,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,184,82,41,8
+ CONTROL "nodraw",IDC_CHECK8,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,184,94,41,8
+ CONTROL "hint",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,106,41,8
+ CONTROL "skip",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,118,41,8
+ CONTROL "400",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,130,41,8
+ CONTROL "800",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,142,41,8
+ CONTROL "1000",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,154,41,8
+ CONTROL "2000",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,166,41,8
+ CONTROL "4000",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,178,41,8
+ CONTROL "8000",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 184,190,41,8
+ CONTROL "10000",IDC_CHECK17,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,10,48,8
+ CONTROL "20000",IDC_CHECK18,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,22,50,8
+ CONTROL "40000",IDC_CHECK19,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,34,41,8
+ CONTROL "80000",IDC_CHECK20,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,46,41,8
+ CONTROL "100000",IDC_CHECK21,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,58,41,8
+ CONTROL "200000",IDC_CHECK22,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,70,41,8
+ CONTROL "400000",IDC_CHECK23,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,82,41,8
+ CONTROL "800000",IDC_CHECK24,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,94,41,8
+ CONTROL "1000000",IDC_CHECK25,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,106,41,8
+ CONTROL "2000000",IDC_CHECK26,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,118,41,8
+ CONTROL "4000000",IDC_CHECK27,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,130,41,8
+ CONTROL "8000000",IDC_CHECK28,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,142,41,8
+ CONTROL "10000000",IDC_CHECK29,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,154,40,8
+ CONTROL "20000000",IDC_CHECK30,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,166,45,8
+ CONTROL "40000000",IDC_CHECK31,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,178,45,8
+ CONTROL "80000000",IDC_CHECK32,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,234,190,45,8
+ CONTROL "solid",IDC_CHECK33,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,304,10,41,8
+ CONTROL "window",IDC_CHECK34,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,304,22,41,8
+ CONTROL "aux",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,34,41,8
+ CONTROL "lava",IDC_CHECK36,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,46,41,8
+ CONTROL "slime",IDC_CHECK37,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,304,58,41,8
+ CONTROL "water",IDC_CHECK38,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,304,70,41,8
+ CONTROL "mist",IDC_CHECK39,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,82,41,8
+ CONTROL "80",IDC_CHECK40,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,94,41,8
+ CONTROL "100",IDC_CHECK41,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,106,41,8
+ CONTROL "200",IDC_CHECK42,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,118,41,8
+ CONTROL "400",IDC_CHECK43,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,130,41,8
+ CONTROL "800",IDC_CHECK44,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,142,41,8
+ CONTROL "1000",IDC_CHECK45,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,154,41,8
+ CONTROL "2000",IDC_CHECK46,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,166,41,8
+ CONTROL "4000",IDC_CHECK47,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,178,41,8
+ CONTROL "8000",IDC_CHECK48,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 304,190,41,8
+ CONTROL "playerclip",IDC_CHECK49,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,10,41,8
+ CONTROL "monsterclip",IDC_CHECK50,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,22,50,8
+ CONTROL "current_0",IDC_CHECK51,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,34,50,8
+ CONTROL "current_90",IDC_CHECK52,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,46,50,8
+ CONTROL "current_180",IDC_CHECK53,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,58,50,8
+ CONTROL "current_270",IDC_CHECK54,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,70,50,8
+ CONTROL "current_up",IDC_CHECK55,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,82,50,8
+ CONTROL "current_dn",IDC_CHECK56,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,94,50,8
+ CONTROL "origin",IDC_CHECK57,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,106,41,8
+ CONTROL "monster",IDC_CHECK58,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,118,41,8
+ CONTROL "corpse",IDC_CHECK59,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,130,41,8
+ CONTROL "detail",IDC_CHECK60,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,142,41,8
+ CONTROL "translucent",IDC_CHECK61,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,154,50,8
+ CONTROL "ladder",IDC_CHECK62,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,166,45,8
+ CONTROL "40000000",IDC_CHECK63,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,178,45,8
+ CONTROL "80000000",IDC_CHECK64,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,354,190,45,8
+ DEFPUSHBUTTON "OK",IDOK,5,194,40,14
+ PUSHBUTTON "Apply",IDAPPLY,55,194,40,14
+ PUSHBUTTON "Cancel",ID_BTN_CANCEL,105,194,40,14
+ RTEXT "Vertical shift",IDC_STATIC,51,43,65,8
+ RTEXT "Horizontal stretch",IDC_STATIC,51,60,65,8
+ RTEXT "Vertical stretch",IDC_STATIC,51,77,65,8
+ RTEXT "Rotate",IDC_STATIC,86,94,30,8
+ RTEXT "Value",IDC_STATIC,75,112,25,8
+ LTEXT "Texture",IDC_STATIC,27,9,28,8
+ GROUPBOX "Surf flags",IDC_STATIC,174,0,115,204
+ GROUPBOX "Content flags",IDC_STATIC,294,0,115,204
+ RTEXT "Horizontal shift",IDC_STATIC,51,28,65,8
+ GROUPBOX "Texturing",IDC_STATIC,5,124,161,65
+ PUSHBUTTON "Set...",IDC_BTN_PATCHRESET,50,174,34,12
+ PUSHBUTTON "Natural",IDC_BTN_PATCHNATURAL,89,174,34,12
+ PUSHBUTTON "Fit",IDC_BTN_PATCHFIT,128,174,34,12
+ LTEXT "Patch",IDC_STATIC,12,161,20,8
+ LTEXT "Brush",IDC_STATIC,12,135,19,8
+ PUSHBUTTON "Axial",IDC_BTN_AXIAL,12,145,34,12
+ PUSHBUTTON "Fit",IDC_BTN_FACEFIT,51,145,34,12
+ EDITTEXT IDC_EDIT_WIDTH,93,146,30,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN_WIDTH,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,117,143,11,18
+ EDITTEXT IDC_EDIT_HEIGHT,131,146,30,12,ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN_HEIGHT,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,153,140,11,18
+ LTEXT "Width",IDC_STATIC,94,136,20,8
+ LTEXT "Height",IDC_STATIC,131,136,22,8
+END
+
+IDD_DLG_PREFS DIALOG DISCARDABLE 0, 0, 386, 327
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Q3Radiant Preferences"
+FONT 8, "MS Sans Serif"
+BEGIN
+ COMBOBOX IDC_COMBO_WHATGAME,13,18,157,76,CBS_DROPDOWN | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ CONTROL "&2 button",IDC_RADIO_MOUSE,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP,188,17,42,10
+ CONTROL "&3 button",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,235,
+ 17,42,10
+ CONTROL "",IDC_RADIO_VIEWTYPE,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP,18,69,10,10
+ CONTROL "",IDC_RADIO_VIEWTYPE2,"Button",BS_AUTORADIOBUTTON,45,69,
+ 11,10
+ CONTROL "",IDC_RADIO_VIEWTYPE3,"Button",BS_AUTORADIOBUTTON,73,69,
+ 11,10
+ CONTROL "",IDC_RADIO_VIEWTYPE4,"Button",BS_AUTORADIOBUTTON,99,69,
+ 11,10
+ CONTROL "Use SGI OpenGL",IDC_CHECK_SGIOPENGL,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,15,79,71,10
+ CONTROL "Buggy ICD",IDC_CHECK_BUGGYICD,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,15,90,50,10
+ CONTROL "OpenGL display lists",IDC_CHECK_DISPLAYLISTS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,15,101,79,10
+ CONTROL "Solid selection boxes",IDC_CHECK_NOSTIPPLE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,15,112,82,10
+ CONTROL "Slider1",IDC_SLIDER_CAMSPEED,"msctls_trackbar32",
+ WS_TABSTOP,128,57,92,11
+ CONTROL "Update XY views during\nmouse drags",
+ IDC_CHECK_CAMXYUPDATE,"Button",BS_AUTOCHECKBOX |
+ BS_MULTILINE | WS_TABSTOP,130,82,91,18
+ CONTROL "QE4 update model",IDC_CHECK_QE4PAINTING,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,130,102,75,10
+ CONTROL "Slider1",IDC_SLIDER_TEXTUREQUALITY,"msctls_trackbar32",
+ TBS_AUTOTICKS | WS_TABSTOP,237,68,127,11
+ CONTROL "Texture toolbar",IDC_CHECK_TEXTURETOOLBAR,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,236,94,63,10
+ CONTROL "Texture scrollbar",IDC_CHECK_TEXTURESCROLLBAR,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,236,105,68,10
+ CONTROL "Texture subset",IDC_CHECK_TEXTUREWINDOW,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,308,94,63,10
+ CONTROL "Right click to drop entities",IDC_CHECK_RIGHTCLICK,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,137,95,10
+ CONTROL "Face selection",IDC_CHECK_FACE,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,13,149,62,10
+ EDITTEXT IDC_EDIT_ROTATION,58,161,24,12,ES_AUTOHSCROLL
+ CONTROL "ALT + multi-drag",IDC_CHECK_ALTDRAG,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,114,137,68,10
+ CONTROL "Snap T to Grid",IDC_CHECK_SNAPT,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,114,149,62,10
+ CONTROL "Mouse chaser",IDC_CHECK_MOUSECHASE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,114,160,68,10
+ CONTROL "Patch Toolbar",IDC_CHECK_WIDETOOLBAR,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,193,137,61,10
+ CONTROL "Light drawing",IDC_CHECK_LIGHTDRAW,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,193,149,58,10
+ CONTROL "Paint sizing info",IDC_CHECK_SIZEPAINT,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,193,160,65,10
+ CONTROL "Hi Color Textures",IDC_CHECK_HICOLOR,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,281,137,70,10
+ LTEXT "Startup Shaders:",IDC_STATIC,281,150,54,8
+ COMBOBOX IDC_COMBO_SHADERS,281,160,82,54,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_EDIT_QUAKE2,13,189,229,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BTN_BROWSE,248,190,16,11
+ CONTROL "Use internal (DLL) QBSP....",IDC_CHECK_INTERNALBSP,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,208,102,10
+ CONTROL "Don't clamp plane points",IDC_CHECK_NOCLAMP,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,220,93,10
+ CONTROL "Snapshots",IDC_CHECK_SNAPSHOTS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,13,232,49,10
+ CONTROL "Use +setgame for run",IDC_CHECK_SETGAME,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,244,83,10
+ CONTROL "Run game after QBSP3...",IDC_CHECK_RUNQUAKE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,121,208,96,10
+ CONTROL "Load last project on open",IDC_CHECK_LOADLAST,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,121,220,96,10
+ CONTROL "Load last map on open",IDC_CHECK_LOADLASTMAP,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,121,232,88,10
+ CONTROL "Auto save every ",IDC_CHECK_AUTOSAVE,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,121,244,66,10
+ EDITTEXT IDC_EDIT_AUTOSAVE,188,244,27,12,ES_AUTOHSCROLL |
+ ES_NUMBER
+ CONTROL "Spin1",IDC_SPIN_AUTOSAVE,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,212,242,11,14
+ LTEXT "Status point size:",IDC_STATIC,258,209,54,8
+ EDITTEXT IDC_EDIT_STATUSPOINTSIZE,315,207,29,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_POINTSIZE,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,344,206,11,14
+ LTEXT "Undo Levels:",IDC_STATIC,258,222,43,8
+ EDITTEXT IDC_EDIT_UNDOLEVELS,315,220,29,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_UNDO,"msctls_updown32",UDS_WRAP |
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
+ UDS_ARROWKEYS,344,220,11,14
+ CONTROL "Use PAK/PK3 file(s):",IDC_CHECK_PAK,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,263,81,10
+ EDITTEXT IDC_EDIT_PAKFILE,95,262,227,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BTN_BROWSEPAK,328,263,16,11
+ EDITTEXT IDC_EDIT_PREFABPATH,95,279,227,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BTN_BROWSEPREFAB,328,280,16,11
+ EDITTEXT IDC_EDIT_USERPATH,95,296,227,12,ES_AUTOHSCROLL
+ PUSHBUTTON "...",IDC_BTN_BROWSEUSERINI,328,297,16,11
+ DEFPUSHBUTTON "OK",IDOK,341,7,38,14
+ PUSHBUTTON "Cancel",IDCANCEL,341,24,38,14
+ CONTROL "Entities are DLL based",IDC_CHECK_DLLENTITIES,"Button",
+ BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | NOT WS_VISIBLE |
+ WS_DISABLED | WS_TABSTOP,277,241,88,12
+ CONTROL "Write face color info",IDC_CHECK_FACECOLOR,"Button",
+ BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED |
+ WS_TABSTOP,279,242,79,10
+ LTEXT "minutes",IDC_STATIC,216,245,25,8
+ CONTROL "Vertex editing",IDC_CHECK_VERTEX,"Button",
+ BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED |
+ WS_TABSTOP,296,243,83,10
+ GROUPBOX "Mouse",IDC_STATIC,179,7,103,28
+ GROUPBOX "Views / Rendering",IDC_STATIC,7,38,372,86
+ GROUPBOX "Game path / Tool settings / Stuff that wouldn't fit anywhere else",
+ IDC_STATIC,7,179,372,139
+ CONTROL 147,IDB_VIEWDEFAULT,"Static",SS_BITMAP,13,48,21,19
+ CONTROL 148,IDB_VIEWDEFAULT2,"Static",SS_BITMAP,40,48,21,19
+ CONTROL 149,IDB_VIEWDEFAULT3,"Static",SS_BITMAP,67,48,21,19
+ GROUPBOX "New functionality:",IDC_STATIC,7,126,372,52
+ CONTROL 150,IDB_VIEWDEFAULT_Z,"Static",SS_BITMAP,93,48,21,19
+ LTEXT "slow",IDC_STATIC,131,69,15,8
+ LTEXT "fast",IDC_STATIC,204,69,12,8
+ GROUPBOX "Camera ",IDC_STATIC,126,47,100,72
+ LTEXT "Prefab path:",IDC_STATIC,54,280,40,8
+ GROUPBOX "Optimize interface for",IDC_STATIC,7,7,170,28
+ LTEXT "User INI path:",IDC_STATIC,49,298,45,8
+ LTEXT "Rotation inc:",IDC_STATIC,15,163,41,8
+ CONTROL "Use Shaders",IDC_CHECK_USESHADERS,"Button",
+ BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED |
+ WS_TABSTOP,289,242,57,10
+ GROUPBOX "Texturing",IDC_STATIC,231,47,141,72
+ LTEXT "Quality",IDC_STATIC,237,57,22,8
+ LTEXT "Low",IDC_STATIC,239,81,14,8
+ LTEXT "High",IDC_STATIC,347,82,16,8
+END
+
+IDD_DLG_MAPINFO DIALOG DISCARDABLE 0, 0, 181, 183
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Map Info"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Close",IDOK,138,7,36,14
+ LTEXT "Total Brushes",IDC_STATIC,7,14,50,8
+ EDITTEXT IDC_EDIT_TOTALBRUSHES,66,12,40,12,ES_RIGHT |
+ ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Total Entities",IDC_STATIC,7,30,50,8
+ EDITTEXT IDC_EDIT_TOTALENTITIES,66,28,40,12,ES_RIGHT |
+ ES_AUTOHSCROLL | ES_NUMBER
+ LTEXT "Net brush count\n(non entity)",IDC_STATIC,7,49,57,17
+ EDITTEXT IDC_EDIT_NET,66,47,40,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_NUMBER
+ LISTBOX IDC_LIST_ENTITIES,7,81,167,95,LBS_SORT | LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Entity breakdown",IDC_STATIC,7,71,56,8
+END
+
+IDD_DLG_ENTITYLIST DIALOG DISCARDABLE 0, 0, 294, 226
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Entities"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Close",IDOK,248,205,39,14
+ CONTROL "Tree1",IDC_TREE_ENTITY,"SysTreeView32",TVS_HASBUTTONS |
+ TVS_HASLINES | TVS_LINESATROOT | WS_BORDER | WS_TABSTOP,
+ 7,7,148,212
+ DEFPUSHBUTTON "Select",IDSELECT,161,205,39,14
+ CONTROL "List2",IDC_LIST_ENTITY,"SysListView32",LVS_REPORT |
+ LVS_SINGLESEL | LVS_EDITLABELS | LVS_NOSORTHEADER |
+ WS_BORDER | WS_TABSTOP,161,7,126,187
+END
+
+IDD_DLG_SCRIPTS DIALOG DISCARDABLE 0, 0, 212, 215
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Available Scripts"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "New...",ID_NEW,166,74,39,14,WS_DISABLED
+ PUSHBUTTON "Close",IDOK,168,194,37,14
+ LISTBOX IDC_LIST_SCRIPTS,7,56,146,152,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "Edit...",ID_EDIT,166,90,39,14,WS_DISABLED
+ DEFPUSHBUTTON "Run",ID_RUN,166,56,39,14
+ LTEXT "WARNING: BrushScripting is in a highly experimental state and is far from complete. If you attempt to use them it is VERY LIKELY that Q3Radiant will crash. Save your work before attempting to make use of any scripting features.",
+ IDC_STATIC,7,7,198,38
+END
+
+IDD_DLG_NEWPROJECT DIALOG DISCARDABLE 0, 0, 246, 74
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "New project"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT_NAME,57,28,116,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,189,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,189,24,50,14
+ LTEXT "This will create a new directory beneath your Quake2 path based on the project name you give.",
+ IDC_STATIC,7,7,165,19
+ LTEXT "Project name:",IDC_STATIC,7,30,44,8
+ CONTROL "Include game dll files",IDC_CHECK1,"Button",
+ BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,7,49,81,10
+END
+
+IDD_DLG_COMMANDLIST DIALOG DISCARDABLE 0, 0, 283, 223
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Mapped Commands"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Close",IDOK,241,202,35,14
+ LISTBOX IDC_LIST_COMMANDS,7,7,221,209,LBS_SORT | LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_DIALOG_SCALE DIALOG DISCARDABLE 0, 0, 122, 74
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Scale"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,79,7,36,14
+ PUSHBUTTON "Cancel",IDCANCEL,79,23,36,14
+ LTEXT "X:",IDC_STATIC,7,15,8,8
+ LTEXT "Y:",IDC_STATIC,7,32,8,8
+ LTEXT "Z:",IDC_STATIC,7,49,8,8
+ EDITTEXT IDC_EDIT_X,22,13,32,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_Y,22,30,32,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_Z,22,47,32,12,ES_AUTOHSCROLL
+END
+
+IDD_DIALOG_FINDREPLACE DIALOGEX 0, 0, 222, 98
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CONTROLPARENT
+CAPTION "Find replace texture(s)"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_EDIT_FIND,27,16,132,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_REPLACE,45,31,114,12,ES_AUTOHSCROLL
+ CONTROL "Replace within selected brushes only",
+ IDC_CHECK_SELECTED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 7,51,133,10
+ CONTROL "Force replacement (ignore current texture name)",
+ IDC_CHECK_FORCE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,
+ 63,167,10
+ DEFPUSHBUTTON "OK",IDOK,175,7,40,14
+ PUSHBUTTON "Close",IDCANCEL,175,77,40,14
+ LTEXT "Find:",IDC_STATIC,7,18,16,8
+ LTEXT "Replace:",IDC_STATIC,7,33,30,8
+ DEFPUSHBUTTON "Apply",ID_BTN_APPLY,175,25,40,14
+ CONTROL "Live updates from Texture/Camera Windows",
+ IDC_CHECK_LIVE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,
+ 79,157,10
+END
+
+IDD_DIALOG_STAIRS DIALOG DISCARDABLE 0, 0, 196, 143
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Stairs"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,147,7,42,14
+ PUSHBUTTON "Cancel",IDCANCEL,136,24,42,14
+ LTEXT "This creates a set of stairs using the selected brush as a template. You may optionally specify a rotation angle to be applied to each new step",
+ IDC_STATIC,7,7,120,37
+ LTEXT "After pressing OK, left click to select a ""height"" point for the stairs. Enough stairs will be created to consume the hieght (Z) between the selected brush and the point you specify",
+ IDC_STATIC,7,46,116,53
+ LTEXT "Rotation per step:",IDC_STATIC,7,104,57,8
+ EDITTEXT IDC_EDIT_ROTATION,69,102,40,12,ES_AUTOHSCROLL
+END
+
+IDD_DIALOG_INPUT DIALOG DISCARDABLE 0, 0, 171, 173
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "BrushScript Input"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,127,7,37,14
+ PUSHBUTTON "Cancel",IDCANCEL,127,24,37,14
+ LTEXT "Field1:",IDC_STATIC_FIELD1,7,13,96,8
+ EDITTEXT IDC_EDIT_FIELD1,7,23,47,14,ES_AUTOHSCROLL
+ LTEXT "Field1:",IDC_STATIC_FIELD2,7,41,105,8
+ EDITTEXT IDC_EDIT_FIELD2,7,51,47,14,ES_AUTOHSCROLL
+ LTEXT "Field1:",IDC_STATIC_FIELD3,7,71,115,8
+ EDITTEXT IDC_EDIT_FIELD3,7,81,47,14,ES_AUTOHSCROLL
+ LTEXT "Field1:",IDC_STATIC_FIELD4,7,103,129,8
+ EDITTEXT IDC_EDIT_FIELD4,7,113,47,14,ES_AUTOHSCROLL
+ LTEXT "Field1:",IDC_STATIC_FIELD5,7,133,135,8
+ EDITTEXT IDC_EDIT_FIELD5,7,142,47,14,ES_AUTOHSCROLL
+END
+
+IDD_DLG_INFORMATION DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE WS_POPUP | WS_CAPTION
+CAPTION "Information"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT1,7,7,172,81,ES_MULTILINE | WS_DISABLED |
+ WS_VSCROLL
+END
+
+IDD_PROJECT DIALOGEX 250, 100, 341, 335
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Project Settings"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT IDC_PRJBASEPATH,75,20,205,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_PRJMAPSPATH,75,40,205,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_PRJRSHCMD,75,60,205,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_PRJREMOTEBASE,75,80,205,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_PRJENTITYPATH,75,100,205,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_PRJTEXPATH,75,120,205,12,ES_AUTOHSCROLL
+ LISTBOX IDC_CMD_LIST,10,157,270,90,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP,
+ WS_EX_CLIENTEDGE
+ PUSHBUTTON "Add...",IDC_ADDCMD,290,150,45,13
+ PUSHBUTTON "Change...",IDC_EDITCMD,290,167,45,13
+ PUSHBUTTON "Remove",IDC_REMCMD,290,184,45,13
+ CONTROL "Use brush primitives in MAP files",IDC_CHECK_BPRIMIT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,270,136,9
+ DEFPUSHBUTTON "OK",IDOK,290,10,45,13
+ PUSHBUTTON "Cancel",IDCANCEL,290,26,45,13
+ GROUPBOX "Project settings",IDC_STATIC,5,7,280,133
+ LTEXT "basepath",IDC_STATIC,42,22,30,8
+ LTEXT "rshcmd",IDC_STATIC,48,62,24,8
+ LTEXT "remotebasepath",IDC_STATIC,20,82,52,8
+ LTEXT "entitypath",IDC_STATIC,40,102,32,8
+ LTEXT "texturepath",IDC_STATIC,36,122,36,8
+ GROUPBOX "Menu commands",IDC_STATIC,5,146,280,105
+ LTEXT "mapspath",IDC_STATIC,40,42,32,8
+ GROUPBOX "Misc settings",IDC_STATIC,5,258,280,73
+END
+
+IDD_ADDCMD DIALOG DISCARDABLE 300, 200, 312, 65
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Add command"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,116,44,37,13
+ PUSHBUTTON "Cancel",IDCANCEL,159,44,37,13
+ EDITTEXT IDC_CMDMENUTEXT,44,8,254,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_CMDCOMMAND,44,26,254,12,ES_AUTOHSCROLL
+ LTEXT "Menu text",IDC_STATIC,5,10,32,8
+ LTEXT "Command",IDC_STATIC,5,28,32,8
+END
+
+IDD_TEXTUREBAR DIALOG DISCARDABLE 0, 0, 313, 19
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_HSHIFT,33,4,32,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_HSHIFT,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,56,3,10,14
+ EDITTEXT IDC_VSHIFT,76,4,32,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_VSHIFT,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,97,3,11,14
+ EDITTEXT IDC_HSCALE,143,4,32,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_HSCALE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,164,3,11,14
+ EDITTEXT IDC_VSCALE,188,4,32,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_VSCALE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,210,3,11,14
+ EDITTEXT IDC_ROTATE,252,4,32,12,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_ROTATE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,272,3,11,14
+ LTEXT "Shift H",IDC_STATIC,7,6,22,8
+ LTEXT "V",IDC_STATIC,68,6,8,8
+ LTEXT "Scale H",IDC_STATIC,112,6,26,8
+ LTEXT "V",IDC_STATIC,180,6,8,8
+ LTEXT "Rotate",IDC_STATIC,226,6,22,8
+ DEFPUSHBUTTON "Button1",IDC_BTN_APPLYTEXTURESTUFF,278,2,11,8,NOT
+ WS_VISIBLE | NOT WS_TABSTOP
+ EDITTEXT IDC_EDIT_ROTATEAMT,287,4,20,12,ES_AUTOHSCROLL
+END
+
+IDD_DIALOG_TEXTURELIST DIALOG DISCARDABLE 0, 0, 257, 279
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Textures"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "&Load",IDOK,205,7,45,14
+ PUSHBUTTON "Close",IDCANCEL,205,23,45,14
+ LISTBOX IDC_LIST_TEXTURES,7,7,189,265,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_DIALOG_NEWPATCH DIALOG DISCARDABLE 0, 0, 129, 58
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Patch density"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,90,7,32,14
+ PUSHBUTTON "Cancel",IDCANCEL,90,24,32,14
+ LTEXT "Width:",IDC_STATIC,9,9,22,8
+ LTEXT "Height:",IDC_STATIC,7,27,24,8
+ COMBOBOX IDC_COMBO_WIDTH,38,7,33,51,CBS_DROPDOWNLIST | WS_VSCROLL |
+ WS_TABSTOP
+ COMBOBOX IDC_COMBO_HEIGHT,38,25,33,51,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_DIALOG_TEXTURELAYOUT DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Patch texture layout"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,141,7,38,14
+ PUSHBUTTON "Cancel",IDCANCEL,141,24,38,14
+ LTEXT "Texture will be fit across the patch based on the x and y values given. Values of 1x1 will ""fit"" the texture. 2x2 will repeat it twice, etc.",
+ IDC_STATIC,7,7,122,36
+ LTEXT "Texture x:",IDC_STATIC,7,48,32,8
+ EDITTEXT IDC_EDIT_X,42,46,30,12,ES_AUTOHSCROLL
+ LTEXT "Texture y:",IDC_STATIC,7,64,32,8
+ EDITTEXT IDC_EDIT_Y,42,62,30,12,ES_AUTOHSCROLL
+END
+
+IDD_DIALOG_CAP DIALOG DISCARDABLE 0, 0, 171, 84
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Cap"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,123,7,41,14
+ PUSHBUTTON "Cancel",IDCANCEL,123,25,41,14
+ CONTROL "Bevel",IDC_RADIO_CAP,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP,31,10,50,10
+ CONTROL "Endcap",IDC_RADIO_CAP2,"Button",BS_AUTORADIOBUTTON,31,
+ 28,50,10
+ CONTROL "Inverted Bevel",IDC_RADIO_CAP3,"Button",
+ BS_AUTORADIOBUTTON,31,47,68,10
+ CONTROL "Inverted Endcap",IDC_RADIO_CAP4,"Button",
+ BS_AUTORADIOBUTTON,31,65,75,10
+ CONTROL 177,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE |
+ SS_SUNKEN,7,7,18,15
+ CONTROL 178,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE |
+ SS_SUNKEN,7,44,18,15
+ CONTROL 176,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE |
+ SS_SUNKEN,7,26,18,15
+ CONTROL 175,IDC_STATIC,"Static",SS_BITMAP | SS_REALSIZEIMAGE |
+ SS_SUNKEN,7,63,17,14
+END
+
+IDD_DIALOG_THICKEN DIALOG DISCARDABLE 0, 0, 204, 63
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Thicken Patch"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,158,7,39,14
+ PUSHBUTTON "Cancel",IDCANCEL,158,24,39,14
+ LTEXT "This produces a func_grouped set of patches that contains the original patch along with the 'thick' patch and an optional set of seam patches. ",
+ IDC_STATIC,7,7,145,33
+ EDITTEXT IDC_EDIT_AMOUNT,38,42,26,12,ES_AUTOHSCROLL
+ LTEXT "Amount:",IDC_STATIC,7,44,27,8
+ CONTROL "Seams",IDC_CHECK_SEAMS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,74,43,37,10
+END
+
+IDD_DIALOG_PATCH DIALOG DISCARDABLE 0, 0, 272, 178
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Patch Properties"
+FONT 8, "MS Sans Serif"
+BEGIN
+ COMBOBOX IDC_COMBO_ROW,15,29,34,79,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_COMBO_COL,54,29,34,84,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_EDIT_X,34,49,54,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_Y,33,64,55,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_Z,33,81,55,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_S,33,98,55,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_EDIT_T,33,115,55,12,ES_AUTOHSCROLL
+ COMBOBOX IDC_COMBO_TYPE,33,134,55,79,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_EDIT_NAME,106,29,144,12,ES_AUTOHSCROLL
+ EDITTEXT IDC_HSHIFT,107,48,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_HSHIFT,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,141,48,11,14
+ EDITTEXT IDC_VSHIFT,107,64,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_VSHIFT,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,141,64,11,14
+ EDITTEXT IDC_HSCALE,107,81,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_HSCALE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,141,81,11,14
+ EDITTEXT IDC_VSCALE,107,98,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_VSCALE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,141,98,11,14
+ EDITTEXT IDC_ROTATE,107,115,45,12,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SPIN_ROTATE,"msctls_updown32",UDS_ALIGNRIGHT |
+ UDS_AUTOBUDDY | UDS_ARROWKEYS,141,114,11,14
+ PUSHBUTTON "CAP",IDC_BTN_PATCHDETAILS,109,134,32,13
+ PUSHBUTTON "Set...",IDC_BTN_PATCHRESET,148,134,32,13
+ PUSHBUTTON "Natural",IDC_BTN_PATCHNATURAL,185,134,32,13
+ PUSHBUTTON "Fit",IDC_BTN_PATCHFIT,225,134,32,13
+ PUSHBUTTON "Apply",ID_APPLY,184,159,38,12
+ DEFPUSHBUTTON "Done",IDOK,227,159,38,12
+ LTEXT "Row:",IDC_STATIC,15,17,18,8
+ LTEXT "Column:",IDC_STATIC,54,17,26,8
+ LTEXT "X:",IDC_STATIC,21,51,8,8
+ LTEXT "Y:",IDC_STATIC,21,66,8,8
+ LTEXT "Z:",IDC_STATIC,21,83,8,8
+ LTEXT "S:",IDC_STATIC,21,100,8,8
+ LTEXT "T:",IDC_STATIC,21,117,8,8
+ LTEXT "Name:",IDC_STATIC,106,17,22,8
+ LTEXT "Vertical shift",IDC_STATIC,157,66,65,8
+ LTEXT "Horizontal stretch",IDC_STATIC,157,83,65,8
+ LTEXT "Vertical stretch",IDC_STATIC,157,100,65,8
+ LTEXT "Rotate",IDC_STATIC,157,117,30,8
+ LTEXT "Horizontal shift",IDC_STATIC,157,51,65,8
+ GROUPBOX "Texturing",IDC_STATIC,99,7,166,148
+ GROUPBOX "Details",IDC_STATIC,7,7,87,148
+ LTEXT "Type:",IDC_STATIC,13,136,19,8
+END
+
+IDD_PLAYWAVE DIALOG DISCARDABLE 0, 0, 33, 15
+STYLE WS_CHILD
+FONT 8, "MS Sans Serif"
+BEGIN
+ PUSHBUTTON "Play",IDC_BTN_PLAY,0,0,33,15
+END
+
+IDD_TEXLIST DIALOG DISCARDABLE 0, 0, 251, 273
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Load multiple texture paths"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Load",IDOK,194,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,194,24,50,14
+ LISTBOX IDC_LIST_TEXTURES,7,7,179,259,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_DLG_GROUP DIALOG DISCARDABLE 0, 0, 194, 241
+STYLE DS_CONTROL | WS_CHILD | WS_BORDER
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Tree1",IDC_TREE_GROUP,"SysTreeView32",TVS_HASBUTTONS |
+ TVS_HASLINES | TVS_LINESATROOT | TVS_EDITLABELS |
+ WS_BORDER | WS_TABSTOP,7,7,180,209
+ PUSHBUTTON "Add...",IDC_BTN_ADD,7,221,33,12
+ PUSHBUTTON "Delete",IDC_BTN_DEL,83,221,33,12
+ PUSHBUTTON "Edit...",IDC_BTN_EDIT,44,221,33,12
+END
+
+IDD_NEWNAME DIALOG DISCARDABLE 0, 0, 186, 46
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "New"
+FONT 8, "MS Sans Serif"
+BEGIN
+ EDITTEXT IDC_EDIT_NAME,31,10,106,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,143,7,36,14
+ PUSHBUTTON "Cancel",IDCANCEL,143,24,36,14
+ LTEXT "Name:",IDC_STATIC,7,12,22,8
+END
+
+IDD_DLG_CAMERA DIALOG DISCARDABLE 0, 0, 277, 295
+STYLE DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Camera Inspector"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "Close",IDOK,220,274,50,14
+ LTEXT "Name",IDC_STATIC,7,14,24,8
+ EDITTEXT IDC_EDIT_CAM_NAME,32,12,154,12,ES_AUTOHSCROLL
+ LTEXT "Edit >",IDC_STATIC,11,70,20,8
+ COMBOBOX IDC_COMBO_SPLINES,33,68,154,81,CBS_DROPDOWNLIST |
+ WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Add Target...",IDC_BTN_ADDTARGET,34,54,53,11
+ SCROLLBAR IDC_SCROLLBAR_SEGMENT,14,168,165,10
+ LTEXT "Length ( seconds )",IDC_STATIC,14,140,60,8
+ EDITTEXT IDC_EDIT_LENGTH,75,138,30,12,ES_AUTOHSCROLL
+ LTEXT "Current Time:",IDC_STATIC,14,156,43,8
+ LISTBOX IDC_LIST_EVENTS,14,207,152,65,LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Time",IDC_STATIC,7,129,200,159
+ EDITTEXT IDC_EDIT_SEGMENT,61,154,40,12,ES_RIGHT | ES_AUTOHSCROLL |
+ ES_READONLY
+ LTEXT "Events",IDC_STATIC,14,195,23,8
+ PUSHBUTTON "Add...",IDC_BTN_ADDEVENT,171,207,32,11
+ PUSHBUTTON "Del",IDC_BTN_DELEVENT,171,221,32,11
+ DEFPUSHBUTTON "Apply",IDAPPLY,220,91,50,14
+ DEFPUSHBUTTON "Load...",ID_FILE_OPEN,220,26,50,14
+ DEFPUSHBUTTON "Save...",ID_FILE_SAVE,220,42,50,14
+ DEFPUSHBUTTON "New",ID_FILE_NEW,220,7,50,14
+ DEFPUSHBUTTON "Preview",ID_TESTCAMERA,220,109,50,14
+ CONTROL "Track Camera",IDC_CHECK_TRACKCAMERA,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,14,180,61,10
+ LTEXT "of",IDC_STATIC,109,155,11,9
+ EDITTEXT IDC_EDIT_TOTALSEGMENTS,122,154,35,12,ES_RIGHT |
+ ES_AUTOHSCROLL | ES_READONLY
+ GROUPBOX "Path and Target editing",IDC_STATIC,7,43,201,83
+ CONTROL "Edit Points",IDC_RADIO_EDITPOINTS,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,13,86,52,9
+ CONTROL "Add Points",IDC_RADIO_EDITPOINTS2,"Button",
+ BS_AUTORADIOBUTTON,13,97,52,9
+ PUSHBUTTON "Delete Selected",IDC_BTN_DELETEPOINTS,13,109,61,11
+ LTEXT "Type:",IDC_STATIC,7,30,20,9
+ EDITTEXT IDC_EDIT_TYPE,32,28,48,12,ES_AUTOHSCROLL | ES_READONLY
+ PUSHBUTTON "Select All",IDC_BTN_SELECTALL,78,109,61,11
+END
+
+IDD_DLG_CAMERAEVENT DIALOG DISCARDABLE 0, 0, 166, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Camera Event"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Wait",IDC_RADIO_EVENT,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP,14,18,31,10
+ CONTROL "Target wait",IDC_RADIO9,"Button",BS_AUTORADIOBUTTON,14,
+ 28,51,10
+ CONTROL "Speed",IDC_RADIO10,"Button",BS_AUTORADIOBUTTON,14,38,37,
+ 10
+ CONTROL "Change target",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON,
+ 14,48,61,10
+ CONTROL "Snap target",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON,14,
+ 58,53,10
+ CONTROL "FOV",IDC_RADIO7,"Button",BS_AUTORADIOBUTTON,14,68,30,10
+ CONTROL "Run script",IDC_RADIO8,"Button",BS_AUTORADIOBUTTON,14,
+ 78,48,10
+ CONTROL "Trigger",IDC_RADIO11,"Button",BS_AUTORADIOBUTTON,14,88,
+ 38,10
+ CONTROL "Stop",IDC_RADIO12,"Button",BS_AUTORADIOBUTTON,15,99,31,
+ 10
+ EDITTEXT IDC_EDIT_PARAM,7,133,124,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,124,7,35,14
+ PUSHBUTTON "Cancel",IDCANCEL,123,24,35,14
+ GROUPBOX "Type",IDC_STATIC,7,7,81,109
+ LTEXT "Paremeter:",IDC_STATIC,7,121,35,8
+END
+
+IDD_DLG_CAMERATARGET DIALOG DISCARDABLE 0, 0, 194, 93
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Camera Target"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CONTROL "Fixed",IDC_RADIO_FIXED,"Button",BS_AUTORADIOBUTTON |
+ WS_GROUP,15,38,37,10
+ CONTROL "Interpolated",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,15,
+ 49,60,11
+ CONTROL "Spline",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,15,61,60,
+ 11
+ DEFPUSHBUTTON "OK",IDOK,146,7,41,11
+ PUSHBUTTON "Cancel",IDCANCEL,146,21,41,11
+ LTEXT "Name:",IDC_STATIC,7,7,23,10
+ EDITTEXT IDC_EDIT_NAME,32,7,105,12,ES_AUTOHSCROLL
+ GROUPBOX "Type",IDC_STATIC,7,26,130,53
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "Radiant MFC Application\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "Radiant\0"
+ VALUE "LegalCopyright", "Copyright (C) 1997\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "Radiant.EXE\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "Radiant Application\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_GAMMA, DIALOG
+ BEGIN
+ RIGHTMARGIN, 127
+ BOTTOMMARGIN, 76
+ END
+
+ IDD_SIDES, DIALOG
+ BEGIN
+ RIGHTMARGIN, 126
+ BOTTOMMARGIN, 45
+ END
+
+ IDD_DLG_PREFS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 379
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 320
+ END
+
+ IDD_DLG_MAPINFO, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 174
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 176
+ END
+
+ IDD_DLG_ENTITYLIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 287
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 219
+ END
+
+ IDD_DLG_SCRIPTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 205
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 208
+ END
+
+ IDD_DLG_NEWPROJECT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 239
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 67
+ END
+
+ IDD_DLG_COMMANDLIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 276
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 216
+ END
+
+ IDD_DIALOG_SCALE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 115
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 67
+ END
+
+ IDD_DIALOG_FINDREPLACE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 215
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 80
+ END
+
+ IDD_DIALOG_STAIRS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 189
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 136
+ END
+
+ IDD_DIALOG_INPUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 164
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 166
+ END
+
+ IDD_DLG_INFORMATION, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+
+ IDD_ADDCMD, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 60
+ END
+
+ IDD_DIALOG_TEXTURELIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 250
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 272
+ END
+
+ IDD_DIALOG_NEWPATCH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 122
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 51
+ END
+
+ IDD_DIALOG_TEXTURELAYOUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+
+ IDD_DIALOG_CAP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 164
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 77
+ END
+
+ IDD_DIALOG_THICKEN, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 197
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 56
+ END
+
+ IDD_DIALOG_PATCH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 265
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 171
+ END
+
+ IDD_TEXLIST, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 266
+ END
+
+ IDD_DLG_GROUP, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 187
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 233
+ END
+
+ IDD_NEWNAME, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 39
+ END
+
+ IDD_DLG_CAMERA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 270
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 288
+ END
+
+ IDD_DLG_CAMERAEVENT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 159
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 151
+ END
+
+ IDD_DLG_CAMERATARGET, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 187
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 86
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog Info
+//
+
+IDD_DIALOG_NEWPATCH DLGINIT
+BEGIN
+ IDC_COMBO_WIDTH, 0x403, 2, 0
+0x0033,
+ IDC_COMBO_WIDTH, 0x403, 2, 0
+0x0035,
+ IDC_COMBO_WIDTH, 0x403, 2, 0
+0x0037,
+ IDC_COMBO_WIDTH, 0x403, 2, 0
+0x0039,
+ IDC_COMBO_WIDTH, 0x403, 3, 0
+0x3131, "\000"
+ IDC_COMBO_WIDTH, 0x403, 3, 0
+0x3331, "\000"
+ IDC_COMBO_WIDTH, 0x403, 3, 0
+0x3531, "\000"
+ IDC_COMBO_HEIGHT, 0x403, 2, 0
+0x0033,
+ IDC_COMBO_HEIGHT, 0x403, 2, 0
+0x0035,
+ IDC_COMBO_HEIGHT, 0x403, 2, 0
+0x0037,
+ IDC_COMBO_HEIGHT, 0x403, 2, 0
+0x0039,
+ IDC_COMBO_HEIGHT, 0x403, 3, 0
+0x3131, "\000"
+ IDC_COMBO_HEIGHT, 0x403, 3, 0
+0x3331, "\000"
+ IDC_COMBO_HEIGHT, 0x403, 3, 0
+0x3531, "\000"
+ 0
+END
+
+IDD_DLG_PREFS DLGINIT
+BEGIN
+ IDC_COMBO_SHADERS, 0x403, 5, 0
+0x6f4e, 0x656e, "\000"
+ IDC_COMBO_SHADERS, 0x403, 7, 0
+0x6f43, 0x6d6d, 0x6e6f, "\000"
+ IDC_COMBO_SHADERS, 0x403, 4, 0
+0x6c41, 0x006c,
+ 0
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ IDR_MAINFRAME "Q3Radiant"
+ IDR_RADIANTYPE "\nRadian\nRadian\n\n\nRadiant.Document\nRadian Document"
+ IDS_STRING1 "DOOM"
+END
+
+STRINGTABLE PRELOAD DISCARDABLE
+BEGIN
+ AFX_IDS_APP_TITLE "Radiant"
+ AFX_IDS_IDLEMESSAGE "Ready"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_INDICATOR_EXT "EXT"
+ ID_INDICATOR_CAPS "CAP"
+ ID_INDICATOR_NUM "NUM"
+ ID_INDICATOR_SCRL "SCRL"
+ ID_INDICATOR_OVR "OVR"
+ ID_INDICATOR_REC "REC"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_NEW "Create a new document\nNew"
+ ID_FILE_OPEN "Open an existing map\nOpen"
+ ID_FILE_CLOSE "Close the active document\nClose"
+ ID_FILE_SAVE "Save the active map\nSave"
+ ID_FILE_SAVE_AS "Save the active document with a new name\nSave As"
+ ID_FILE_PAGE_SETUP "Change the printing options\nPage Setup"
+ ID_FILE_PRINT_SETUP "Change the printer and printing options\nPrint Setup"
+ ID_FILE_PRINT "Print the active document\nPrint"
+ ID_FILE_PRINT_PREVIEW "Display full pages\nPrint Preview"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_APP_ABOUT "Display program information, version number and copyright\nAbout"
+ ID_APP_EXIT "Quit the application; prompts to save documents\nExit"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_MRU_FILE1 "Open this document"
+ ID_FILE_MRU_FILE2 "Open this document"
+ ID_FILE_MRU_FILE3 "Open this document"
+ ID_FILE_MRU_FILE4 "Open this document"
+ ID_FILE_MRU_FILE5 "Open this document"
+ ID_FILE_MRU_FILE6 "Open this document"
+ ID_FILE_MRU_FILE7 "Open this document"
+ ID_FILE_MRU_FILE8 "Open this document"
+ ID_FILE_MRU_FILE9 "Open this document"
+ ID_FILE_MRU_FILE10 "Open this document"
+ ID_FILE_MRU_FILE11 "Open this document"
+ ID_FILE_MRU_FILE12 "Open this document"
+ ID_FILE_MRU_FILE13 "Open this document"
+ ID_FILE_MRU_FILE14 "Open this document"
+ ID_FILE_MRU_FILE15 "Open this document"
+ ID_FILE_MRU_FILE16 "Open this document"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_NEXT_PANE "Switch to the next window pane\nNext Pane"
+ ID_PREV_PANE "Switch back to the previous window pane\nPrevious Pane"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_WINDOW_NEW "Open another window for the active document\nNew Window"
+ ID_WINDOW_ARRANGE "Arrange icons at the bottom of the window\nArrange Icons"
+ ID_WINDOW_CASCADE "Arrange windows so they overlap\nCascade Windows"
+ ID_WINDOW_TILE_HORZ "Arrange windows as non-overlapping tiles\nTile Windows"
+ ID_WINDOW_TILE_VERT "Arrange windows as non-overlapping tiles\nTile Windows"
+ ID_WINDOW_SPLIT "Split the active window into panes\nSplit"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_EDIT_CLEAR "Erase the selection\nErase"
+ ID_EDIT_CLEAR_ALL "Erase everything\nErase All"
+ ID_EDIT_COPY "Copy the selection and put it on the Clipboard\nCopy"
+ ID_EDIT_CUT "Cut the selection and put it on the Clipboard\nCut"
+ ID_EDIT_FIND "Find the specified text\nFind"
+ ID_EDIT_PASTE "Insert Clipboard contents\nPaste"
+ ID_EDIT_REPEAT "Repeat the last action\nRepeat"
+ ID_EDIT_REPLACE "Replace specific text with different text\nReplace"
+ ID_EDIT_SELECT_ALL "Select the entire document\nSelect All"
+ ID_EDIT_UNDO "Undo the last action\nUndo"
+ ID_EDIT_REDO "Redo the previously undone action\nRedo"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar"
+ ID_VIEW_STATUS_BAR "Show or hide the status bar\nToggle StatusBar"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_SCSIZE "Change the window size"
+ AFX_IDS_SCMOVE "Change the window position"
+ AFX_IDS_SCMINIMIZE "Reduce the window to an icon"
+ AFX_IDS_SCMAXIMIZE "Enlarge the window to full size"
+ AFX_IDS_SCNEXTWINDOW "Switch to the next document window"
+ AFX_IDS_SCPREVWINDOW "Switch to the previous document window"
+ AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_SCRESTORE "Restore the window to normal size"
+ AFX_IDS_SCTASKLIST "Activate Task List"
+ AFX_IDS_MDICHILD "Activate this window"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ AFX_IDS_PREVIEW_CLOSE "Close print preview mode\nCancel Preview"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_XY "View original layout (Top)"
+ ID_VIEW_SIDE "Side view"
+ ID_VIEW_FRONT "Front view"
+ ID_VIEW_CAMERATOGGLE "Toggle full time camera preview\nCamera preview"
+ ID_TEXTURES_POPUP "Texture view mode\nTexture view mode"
+ ID_POPUP_SELECTION "Selection\nSelection"
+ ID_VIEW_CHANGE "Change views\nChange views"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_ENTITY "Toggle entity inspector\nEntity inspector"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_BRUSH_FLIPX "Flip selected brushes along x-axis\nx-axis Flip"
+ ID_BRUSH_FLIPY "Flip selected brushes along y-axis\ny-axis Flip"
+ ID_BRUSH_FLIPZ "Flip selected brushes along z-axis\nz-axis Flip"
+ ID_BRUSH_ROTATEX "Rotate selected brushes along x-axis\nx-axis Rotate"
+ ID_BRUSH_ROTATEY "Rotate selected brushes along y-axis\ny-axis Rotate"
+ ID_BRUSH_ROTATEZ "Rotate selected brushes along z-axis\nz-axis Rotate"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SELECTION_SELECTCOMPLETETALL "Complete Tall\nComplete Tall"
+ ID_SELECTION_CSGSUBTRACT "CSG Subtract\nCSG Subtract"
+ ID_SELECTION_SELECTTOUCHING "Select Touching\nSelect Touching"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SELECTION_MAKEHOLLOW "Hollow Selection\nHollow"
+ ID_SELECTION_SELECTPARTIALTALL "Select Partial Tall\nSelect Partial Tall"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_CAMERAUPDATE "Update Camera\nUpdate Camera"
+ ID_VIEW_CLIPPER "Set clipper mode\nClipper"
+ ID_PREFS "Preferences\nPreferences"
+ ID_EDIT_MAPINFO "Entity Information\nEntity list"
+ ID_BRUSH_SCRIPTS "Define and run BrushScripts\nBrushScripts"
+ ID_HELP_COMMANDLIST "Provides a list of the currently bound commands"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SELECT_MOUSEROTATE "Free rotation\nFree Rotation"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TEXTURE_REPLACESELECTED
+ "Find and replace texture names in selected brushes/faces"
+ ID_TEXTURE_REPLACEALL "Find and replace texture names in all brushes/faces"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SELECT_MOUSESCALE "Free Scaling\nFree Scaling"
+ ID_SCALELOCKX "Lock X\nLock X"
+ ID_SCALELOCKY "Lock Y\nLock Y"
+ ID_SCALELOCKZ "Lock Z\nLock Z"
+ ID_VIEW_CUBICCLIPPING "Cubic clip the camera view\nCubic clip the camera view"
+ ID_FILE_PROJECTSETTINGS "View and edit project attributes"
+ ID_VIEW_CUBEOUT "Zoom cubic clip out"
+ ID_VIEW_CUBEIN "Zoom cubic clip in"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_SAVEREGION "Save defined region"
+ ID_FILE_LOADREGION "Load saved region"
+ ID_TOOLBAR_MAIN "Standard toolbar"
+ ID_TOOLBAR_TEXTURE "Texture control toolbar"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TEXTURES_LOAD "Load from a specific directory"
+ ID_CURVE_CYLINDER "Create a cylinder"
+ ID_FILE_IMPORTMAP "Load map, leaving current map intact"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SELECTION_SELECTINSIDE "Select Inside\nSelect Inside"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_FILE_EXPORTMAP "Save selection into map file"
+ ID_EDIT_LOADPREFAB "Load .map from prefab path"
+ ID_VIEW_SHOWCURVES "Show Curved brushes"
+ ID_TEXTURES_LOADLIST "Loads from a list. (Good in case there are too many for the menu)"
+ ID_DONTSELECTCURVE "Don't select curved brushes\nDon't select curved brushes"
+ ID_CONVERTCURVES "Turns selected brush into a new test curve"
+ ID_PATCH_SHOWBOUNDINGBOX
+ "Show patch bounding box\nShow patch bounding box"
+ ID_CURVE_SIMPLEPATCHMESH "Builds a flat patch mesh, you specify the size"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_PATCH_WIREFRAME "Show patches as wireframes\nShow patches as wireframes"
+ ID_PATCH_WELD "Welds equal patch points during moves\nWelds equal patch points during moves"
+ ID_CURVE_PATCHTUBE "Create a cylinder"
+ ID_CURVE_PATCHENDCAP "Create an endcap"
+ ID_CURVE_PATCHBEVEL "Create a bevel"
+ ID_PATCH_DRILLDOWN "Selects drill down rows and columns\nSelects drill down rows and columns"
+ ID_CURVE_LOADPATCHFILE "Load corresponding .patch file\nLoad corresponding .patch file"
+ ID_CURVE_INSERTROW "Inserts a row in the selected patch(s)\nInserts a row in the selected patch(s)"
+ ID_CURVE_INSERTCOLUMN "Inserts a column in the selected patch(s)\nInserts a column in the selected patch(s)"
+ ID_CURVE_DELETEROW "Deletes a row in the current patch(s)\nDeletes a row in the current patch(s)"
+ ID_CURVE_DELETECOLUMN "Deletes a column in the current Patch(s)\nDeletes a column in the current Patch(s)"
+ ID_PATCH_INSDEL "Redisperse patch points\nRedisperse patch points"
+ ID_CURVE_INSERT_ADDCOLUMN
+ "Add a column to the end of the patch\nAdd a column to the end of the patch"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_CURVE_INSERT_INSERTCOLUMN
+ "Insert a column at the beginning of the patch\nInsert a column at the beginning of the patch"
+ ID_CURVE_INSERT_ADDROW "Add a row at the end of the patch\nAdd a row at the end of the patch"
+ ID_CURVE_INSERT_INSERTROW
+ "Insert a row at the beginning of the patch\nInsert a row at the beginning of the patch"
+ ID_CURVE_DELETE_FIRSTCOLUMN
+ "Delete the first (2) columns\nDelete the first (2) columns"
+ ID_CURVE_DELETE_LASTCOLUMN
+ "Delete the last (2) columns\nDelete the last (2) columns"
+ ID_CURVE_DELETE_FIRSTROW
+ "Delete the first (2) rows\nDelete the first (2) rows"
+ ID_CURVE_DELETE_LASTROW "Delete the last (2) rows\nDelete the last (2) rows"
+ ID_CURVE_NEGATIVE "Toggle negative flag\nToggle negative flag"
+ ID_PATCH_BEND "Patch Bend mode\nPatch Bend mode"
+ ID_CURVE_PATCHDENSETUBE "Create a dense tube"
+ ID_CURVE_PATCHVERYDENSETUBE "Create a very dense cylinder"
+ ID_CURVE_CAP "Put caps on the current patch\nPut caps on the current patch"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_CURVE_REDISPERSE_ROWS
+ "Re-disperse rows across the dimensions of the patch"
+ ID_CURVE_REDISPERSE_COLS
+ "Re-disperse columns across the dimensions of the patch"
+ ID_CURVE_PATCHSQUARE "Create a very square cylinder"
+ ID_TEXTURES_FLUSH "Flush texture palette"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_TEXTURES_RELOADSHADERS
+ "Reload Shaders and apply visual changes to current map"
+ ID_SHOW_ENTITIES "Show Entities as\nShow Entities as"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDR_SHADERTYPE "\nUntitled\nSHADER Document\nShader Files (*.shader)\n.shader\nShaderFileType\nSHADER File Type\nSHADER\nShader Files\n"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_VIEW_OPENGLLIGHTING "Toggle OpenGL Lighting"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ ID_SELECTION_CSGMERGE "CSG Merge\nCSG Merge"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "res\Radiant.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#include "afxprint.rc" // printing/print preview resources
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/q3radiant/Radiant.sln b/q3radiant/Radiant.sln
new file mode 100755
index 0000000..ec12c7e
--- /dev/null
+++ b/q3radiant/Radiant.sln
@@ -0,0 +1,95 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Radiant", "Radiant.vcproj", "{D92DD0A3-9D6B-4183-992C-0FF42BC59A62}"
+ ProjectSection(ProjectDependencies) = postProject
+ {EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F} = {EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F}
+ {63F2947A-5BD9-48C2-8BEA-7AB341F6B48F} = {63F2947A-5BD9-48C2-8BEA-7AB341F6B48F}
+ {B80E7E95-566D-4CB0-8151-0567CB206D5A} = {B80E7E95-566D-4CB0-8151-0567CB206D5A}
+ {706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE} = {706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Splines", "splines\Splines.vcproj", "{63F2947A-5BD9-48C2-8BEA-7AB341F6B48F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cmdlib", "..\libs\cmdlib\cmdlib.vcproj", "{EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg6", "..\libs\jpeg6\jpeg6.vcproj", "{B80E7E95-566D-4CB0-8151-0567CB206D5A}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "..\libs\pak\pak.vcproj", "{706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3map", "..\q3map\q3map.vcproj", "{4D768C46-A503-48DE-BD4C-14D2B50C2739}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SourceCodeControl) = preSolution
+ SccNumberOfProjects = 6
+ SccProjectUniqueName0 = Radiant.vcproj
+ SccProjectName0 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
+ SccLocalPath0 = .
+ SccProvider0 = MSSCCI:Perforce\u0020SCM
+ SccProjectUniqueName1 = splines\\Splines.vcproj
+ SccProjectName1 = \u0022$/source/q3radiant/splines\u0022,\u0020XINAAAAA
+ SccLocalPath1 = splines
+ SccProvider1 = MSSCCI:Perforce\u0020SCM
+ SccProjectUniqueName2 = ..\\libs\\cmdlib\\cmdlib.vcproj
+ SccProjectName2 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
+ SccLocalPath2 = .
+ SccProvider2 = MSSCCI:Perforce\u0020SCM
+ SccProjectFilePathRelativizedFromConnection2 = ..\\libs\\cmdlib\\
+ SccProjectUniqueName3 = ..\\libs\\jpeg6\\jpeg6.vcproj
+ SccProjectName3 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
+ SccLocalPath3 = .
+ SccProvider3 = MSSCCI:Perforce\u0020SCM
+ SccProjectFilePathRelativizedFromConnection3 = ..\\libs\\jpeg6\\
+ SccProjectUniqueName4 = ..\\libs\\pak\\pak.vcproj
+ SccProjectName4 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA
+ SccLocalPath4 = .
+ SccProvider4 = MSSCCI:Perforce\u0020SCM
+ SccProjectFilePathRelativizedFromConnection4 = ..\\libs\\pak\\
+ SccProjectUniqueName5 = ..\\q3map\\q3map.vcproj
+ SccProjectName5 = \u0022$/source/q3map\u0022,\u0020PADAAAAA
+ SccLocalPath5 = ..\\q3map
+ SccProvider5 = MSSCCI:Perforce\u0020SCM
+ EndGlobalSection
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {D92DD0A3-9D6B-4183-992C-0FF42BC59A62}.Debug.ActiveCfg = Debug|Win32
+ {D92DD0A3-9D6B-4183-992C-0FF42BC59A62}.Debug.Build.0 = Debug|Win32
+ {D92DD0A3-9D6B-4183-992C-0FF42BC59A62}.Release.ActiveCfg = Release|Win32
+ {D92DD0A3-9D6B-4183-992C-0FF42BC59A62}.Release.Build.0 = Release|Win32
+ {63F2947A-5BD9-48C2-8BEA-7AB341F6B48F}.Debug.ActiveCfg = Debug|Win32
+ {63F2947A-5BD9-48C2-8BEA-7AB341F6B48F}.Debug.Build.0 = Debug|Win32
+ {63F2947A-5BD9-48C2-8BEA-7AB341F6B48F}.Release.ActiveCfg = Release|Win32
+ {63F2947A-5BD9-48C2-8BEA-7AB341F6B48F}.Release.Build.0 = Release|Win32
+ {EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F}.Debug.ActiveCfg = Debug|Win32
+ {EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F}.Debug.Build.0 = Debug|Win32
+ {EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F}.Release.ActiveCfg = Release|Win32
+ {EFB1E65A-E86F-4E0D-845A-E5C7A3DF016F}.Release.Build.0 = Release|Win32
+ {B80E7E95-566D-4CB0-8151-0567CB206D5A}.Debug.ActiveCfg = Debug|Win32
+ {B80E7E95-566D-4CB0-8151-0567CB206D5A}.Debug.Build.0 = Debug|Win32
+ {B80E7E95-566D-4CB0-8151-0567CB206D5A}.Release.ActiveCfg = Release|Win32
+ {B80E7E95-566D-4CB0-8151-0567CB206D5A}.Release.Build.0 = Release|Win32
+ {706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE}.Debug.ActiveCfg = Debug|Win32
+ {706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE}.Debug.Build.0 = Debug|Win32
+ {706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE}.Release.ActiveCfg = Release|Win32
+ {706CF09C-D767-4ECD-8CA6-EE7CA6CDA3AE}.Release.Build.0 = Release|Win32
+ {4D768C46-A503-48DE-BD4C-14D2B50C2739}.Debug.ActiveCfg = Debug|Win32
+ {4D768C46-A503-48DE-BD4C-14D2B50C2739}.Debug.Build.0 = Debug|Win32
+ {4D768C46-A503-48DE-BD4C-14D2B50C2739}.Release.ActiveCfg = Release|Win32
+ {4D768C46-A503-48DE-BD4C-14D2B50C2739}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/q3radiant/Radiant.vcproj b/q3radiant/Radiant.vcproj
new file mode 100755
index 0000000..090a4ff
--- /dev/null
+++ b/q3radiant/Radiant.vcproj
@@ -0,0 +1,3381 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="Radiant"
+ SccProjectName="&quot;$/source/q3radiant&quot;, FEFAAAAA"
+ SccLocalPath="."
+ Keyword="MFCProj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../libs,../common,c:\quake3\common,c:\quake3\libs"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;QUAKE3;Q3RADIANT"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Release/Radiant.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="2"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib ..\libs\jpeg6.lib ..\libs\pak.lib ..\libs\cmdlib.lib"
+ OutputFile="Release\q3radiant.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ IgnoreDefaultLibraryNames="libc.lib msvcrtd.lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Release/q3radiant.pdb"
+ SubSystem="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/Radiant.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="ReleaseTTimo|Win32"
+ OutputDirectory=".\Radiant___Win32_ReleaseTTimo"
+ IntermediateDirectory=".\Radiant___Win32_ReleaseTTimo"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="..\Libs,../libs,../common,c:\quake3\common,c:\quake3\libs"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;QUAKE3;Q3RADIANT"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="TRUE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Radiant___Win32_ReleaseTTimo/Radiant.pch"
+ AssemblerListingLocation=".\Radiant___Win32_ReleaseTTimo/"
+ ObjectFile=".\Radiant___Win32_ReleaseTTimo/"
+ ProgramDataBaseFileName=".\Radiant___Win32_ReleaseTTimo/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="2"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib jpeg6.lib pak.lib cmdlib.lib"
+ OutputFile="Radiant___Win32_ReleaseTTimo\q3radiant.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\Libs"
+ IgnoreDefaultLibraryNames="libc.lib msvcrtd.lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Radiant___Win32_ReleaseTTimo/q3radiant.pdb"
+ SubSystem="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Radiant___Win32_ReleaseTTimo/Radiant.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copy to dir..."
+ CommandLine="copy Radiant___Win32_ReleaseTTimo\q3radiant.exe E:\home\quake3\q3radiant"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../libs,../common,c:\quake3\common,c:\quake3\libs"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;QUAKE3;Q3RADIANT"
+ RuntimeLibrary="1"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Debug/Radiant.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib ..\libs\jpeg6d.lib ..\libs\pakd.lib ..\libs\cmdlibd.lib"
+ OutputFile="Debug\q3radiant.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ IgnoreDefaultLibraryNames="libc.lib msvcrtd.lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/q3radiant.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\Debug/q3radiant.map"
+ SubSystem="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/Radiant.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="DebugTTimo|Win32"
+ OutputDirectory=".\Radiant___Win32_DebugTTimo"
+ IntermediateDirectory=".\Radiant___Win32_DebugTTimo"
+ ConfigurationType="1"
+ UseOfMFC="1"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\Libs,../libs,../common,c:\quake3\common,c:\quake3\libs"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;QUAKE3;Q3RADIANT"
+ RuntimeLibrary="1"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="stdafx.h"
+ PrecompiledHeaderFile=".\Radiant___Win32_DebugTTimo/Radiant.pch"
+ AssemblerListingLocation=".\Radiant___Win32_DebugTTimo/"
+ ObjectFile=".\Radiant___Win32_DebugTTimo/"
+ ProgramDataBaseFileName=".\Radiant___Win32_DebugTTimo/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="winmm.lib jpeg6d.lib pakd.lib cmdlibd.lib"
+ OutputFile="Radiant___Win32_DebugTTimo\q3radiant.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ AdditionalLibraryDirectories="..\Libs"
+ IgnoreDefaultLibraryNames="libc.lib msvcrtd.lib"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Radiant___Win32_DebugTTimo/q3radiant.pdb"
+ GenerateMapFile="TRUE"
+ MapFileName=".\Radiant___Win32_DebugTTimo/q3radiant.map"
+ SubSystem="2"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Radiant___Win32_DebugTTimo/Radiant.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ Description="Copy to dir..."
+ CommandLine="copy Radiant___Win32_DebugTTimo\q3radiant.exe E:\home\quake3\q3radiant"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="BrushScript.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="BSInput.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="cameratargetdlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="CamWnd.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="CapDialog.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="cbrushstub.cpp">
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32"
+ ExcludedFromBuild="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32"
+ ExcludedFromBuild="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="CommandsDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="DialogInfo.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="DialogTextures.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="DialogThick.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dlgcamera.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="DlgEvent.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="EditWnd.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="EntityListDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="FindTextureDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="GroupDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="LstToolBar.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="MainFrm.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="MapInfo.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="NameDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="NewProjDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PatchDensityDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PatchDialog.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PlugIn.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PlugInManager.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PMESH.CPP">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PrefsDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qgl_win.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="radbsp.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="RADEditWnd.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Radiant.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Radiant.rc">
+ </File>
+ <File
+ RelativePath="RotateDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ScaleDialog.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ScriptDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ShaderInfo.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="StdAfx.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="SurfaceDlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="TexEdit.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="TextureBar.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="TextureLayout.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="TexWnd.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Undo.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="WaveOpen.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Winding.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="XYWnd.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="ZWnd.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <Filter
+ Name="QE4 Files"
+ Filter="">
+ <File
+ RelativePath="Bmp.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="brush.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="csg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="drag.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="eclass.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="entity.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="lbmlib.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="map.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mathlib.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mru.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="parse.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="points.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="qe3.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="select.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="terrain.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="terrain.h">
+ </File>
+ <File
+ RelativePath="vertsel.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="win_dlg.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="win_ent.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="win_main.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="win_qe3.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="z.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Brush Primitives"
+ Filter="">
+ <File
+ RelativePath="brush_primit.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="interfaces"
+ Filter="">
+ <File
+ RelativePath="GLInterface.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="IEpairs.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="IShaders.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Messaging.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="PluginEntities.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="SelectedFace.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="SurfacePlugin.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="ReleaseTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="DebugTTimo|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="BSInput.h">
+ </File>
+ <File
+ RelativePath="cameratargetdlg.h">
+ </File>
+ <File
+ RelativePath="CamWnd.h">
+ </File>
+ <File
+ RelativePath="CapDialog.h">
+ </File>
+ <File
+ RelativePath="ChildFrm.h">
+ </File>
+ <File
+ RelativePath="CommandsDlg.h">
+ </File>
+ <File
+ RelativePath="DialogInfo.h">
+ </File>
+ <File
+ RelativePath="DialogTextures.h">
+ </File>
+ <File
+ RelativePath="DialogThick.h">
+ </File>
+ <File
+ RelativePath="dlgcamera.h">
+ </File>
+ <File
+ RelativePath="DlgEvent.h">
+ </File>
+ <File
+ RelativePath="EditWnd.h">
+ </File>
+ <File
+ RelativePath="EntityListDlg.h">
+ </File>
+ <File
+ RelativePath="FindTextureDlg.h">
+ </File>
+ <File
+ RelativePath="GroupBar.h">
+ </File>
+ <File
+ RelativePath="GroupDlg.h">
+ </File>
+ <File
+ RelativePath="LstToolBar.h">
+ </File>
+ <File
+ RelativePath="MainFrm.h">
+ </File>
+ <File
+ RelativePath="MapInfo.h">
+ </File>
+ <File
+ RelativePath="NameDlg.h">
+ </File>
+ <File
+ RelativePath="NewProjDlg.h">
+ </File>
+ <File
+ RelativePath="PatchDensityDlg.h">
+ </File>
+ <File
+ RelativePath="PatchDialog.h">
+ </File>
+ <File
+ RelativePath="PlugIn.h">
+ </File>
+ <File
+ RelativePath="PlugInManager.h">
+ </File>
+ <File
+ RelativePath="PrefsDlg.h">
+ </File>
+ <File
+ RelativePath="qe3.h">
+ </File>
+ <File
+ RelativePath="QEDEFS.H">
+ </File>
+ <File
+ RelativePath="qerplugin.h">
+ </File>
+ <File
+ RelativePath="QERTYPES.H">
+ </File>
+ <File
+ RelativePath="QFILES.H">
+ </File>
+ <File
+ RelativePath="RADEditWnd.h">
+ </File>
+ <File
+ RelativePath="Radiant.h">
+ </File>
+ <File
+ RelativePath="RadiantDoc.h">
+ </File>
+ <File
+ RelativePath="RadiantView.h">
+ </File>
+ <File
+ RelativePath="Resource.h">
+ </File>
+ <File
+ RelativePath="RotateDlg.h">
+ </File>
+ <File
+ RelativePath="ScaleDialog.h">
+ </File>
+ <File
+ RelativePath="ScriptDlg.h">
+ </File>
+ <File
+ RelativePath="SELECT.H">
+ </File>
+ <File
+ RelativePath="ShaderInfo.h">
+ </File>
+ <File
+ RelativePath="StdAfx.h">
+ </File>
+ <File
+ RelativePath="SurfaceDlg.h">
+ </File>
+ <File
+ RelativePath="TexEdit.h">
+ </File>
+ <File
+ RelativePath="TextureBar.h">
+ </File>
+ <File
+ RelativePath="TextureLayout.h">
+ </File>
+ <File
+ RelativePath="TexWnd.h">
+ </File>
+ <File
+ RelativePath="WaveOpen.h">
+ </File>
+ <File
+ RelativePath="XYWnd.h">
+ </File>
+ <File
+ RelativePath="ZWnd.h">
+ </File>
+ <Filter
+ Name="interface headers"
+ Filter="">
+ <File
+ RelativePath="IEpairs.h">
+ </File>
+ <File
+ RelativePath="igl.h">
+ </File>
+ <File
+ RelativePath="IMessaging.h">
+ </File>
+ <File
+ RelativePath="IPluginEntities.h">
+ </File>
+ <File
+ RelativePath="ISelectedFace.h">
+ </File>
+ <File
+ RelativePath="IShaders.h">
+ </File>
+ <File
+ RelativePath="isurfaceplugin.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="internal interface headers"
+ Filter="">
+ <File
+ RelativePath="EpairsWrapper.h">
+ </File>
+ <File
+ RelativePath="Messaging.h">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe">
+ <File
+ RelativePath="res\bevel.bmp">
+ </File>
+ <File
+ RelativePath="res\bitmap2.bmp">
+ </File>
+ <File
+ RelativePath="res\bmp00001.bmp">
+ </File>
+ <File
+ RelativePath="res\bmp00002.bmp">
+ </File>
+ <File
+ RelativePath="RES\bmp00003.bmp">
+ </File>
+ <File
+ RelativePath="res\endcap.bmp">
+ </File>
+ <File
+ RelativePath="res\ibevel.bmp">
+ </File>
+ <File
+ RelativePath="RES\icon2.ico">
+ </File>
+ <File
+ RelativePath="res\iendcap.bmp">
+ </File>
+ <File
+ RelativePath="res\logo_sm3dfx.bmp">
+ </File>
+ <File
+ RelativePath="res\q.bmp">
+ </File>
+ <File
+ RelativePath="q.bmp">
+ </File>
+ <File
+ RelativePath="res\Radiant.ico">
+ </File>
+ <File
+ RelativePath="res\Radiant.rc2">
+ </File>
+ <File
+ RelativePath="res\RadiantDoc.ico">
+ </File>
+ <File
+ RelativePath="RES\shaderbar.bmp">
+ </File>
+ <File
+ RelativePath="RES\shaderdoc.ico">
+ </File>
+ <File
+ RelativePath="RES\shaderframe.ico">
+ </File>
+ <File
+ RelativePath="res\Toolbar.bmp">
+ </File>
+ <File
+ RelativePath="toolbar1.bmp">
+ </File>
+ <File
+ RelativePath="res\toolbar1.bmp">
+ </File>
+ <File
+ RelativePath="res\toolbar2.bmp">
+ </File>
+ <File
+ RelativePath="res\viewdefa.bmp">
+ </File>
+ <File
+ RelativePath="res\viewoppo.bmp">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/q3radiant/RadiantDoc.cpp b/q3radiant/RadiantDoc.cpp
new file mode 100755
index 0000000..00b66fe
--- /dev/null
+++ b/q3radiant/RadiantDoc.cpp
@@ -0,0 +1,105 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RadiantDoc.cpp : implementation of the CRadiantDoc class
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+
+#include "RadiantDoc.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantDoc
+
+IMPLEMENT_DYNCREATE(CRadiantDoc, CDocument)
+
+BEGIN_MESSAGE_MAP(CRadiantDoc, CDocument)
+ //{{AFX_MSG_MAP(CRadiantDoc)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantDoc construction/destruction
+
+CRadiantDoc::CRadiantDoc()
+{
+ // TODO: add one-time construction code here
+
+}
+
+CRadiantDoc::~CRadiantDoc()
+{
+}
+
+BOOL CRadiantDoc::OnNewDocument()
+{
+ if (!CDocument::OnNewDocument())
+ return FALSE;
+
+ // TODO: add reinitialization code here
+ // (SDI documents will reuse this document)
+
+ return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantDoc serialization
+
+void CRadiantDoc::Serialize(CArchive& ar)
+{
+ if (ar.IsStoring())
+ {
+ // TODO: add storing code here
+ }
+ else
+ {
+ // TODO: add loading code here
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantDoc diagnostics
+
+#ifdef _DEBUG
+void CRadiantDoc::AssertValid() const
+{
+ CDocument::AssertValid();
+}
+
+void CRadiantDoc::Dump(CDumpContext& dc) const
+{
+ CDocument::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantDoc commands
diff --git a/q3radiant/RadiantDoc.h b/q3radiant/RadiantDoc.h
new file mode 100755
index 0000000..fc51b92
--- /dev/null
+++ b/q3radiant/RadiantDoc.h
@@ -0,0 +1,78 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RadiantDoc.h : interface of the CRadiantDoc class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_RADIANTDOC_H__330BBF0E_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+#define AFX_RADIANTDOC_H__330BBF0E_731C_11D1_B539_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+
+class CRadiantDoc : public CDocument
+{
+protected: // create from serialization only
+ CRadiantDoc();
+ DECLARE_DYNCREATE(CRadiantDoc)
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRadiantDoc)
+ public:
+ virtual BOOL OnNewDocument();
+ virtual void Serialize(CArchive& ar);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CRadiantDoc();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CRadiantDoc)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_RADIANTDOC_H__330BBF0E_731C_11D1_B539_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/RadiantView.cpp b/q3radiant/RadiantView.cpp
new file mode 100755
index 0000000..f89b72c
--- /dev/null
+++ b/q3radiant/RadiantView.cpp
@@ -0,0 +1,126 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RadiantView.cpp : implementation of the CRadiantView class
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+
+#include "RadiantDoc.h"
+#include "RadiantView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantView
+
+IMPLEMENT_DYNCREATE(CRadiantView, CView)
+
+BEGIN_MESSAGE_MAP(CRadiantView, CView)
+ //{{AFX_MSG_MAP(CRadiantView)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG_MAP
+ // Standard printing commands
+ ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
+ ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
+ ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantView construction/destruction
+
+CRadiantView::CRadiantView()
+{
+ // TODO: add construction code here
+
+}
+
+CRadiantView::~CRadiantView()
+{
+}
+
+BOOL CRadiantView::PreCreateWindow(CREATESTRUCT& cs)
+{
+ // TODO: Modify the Window class or styles here by modifying
+ // the CREATESTRUCT cs
+
+ return CView::PreCreateWindow(cs);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantView drawing
+
+void CRadiantView::OnDraw(CDC* pDC)
+{
+ CRadiantDoc* pDoc = GetDocument();
+ ASSERT_VALID(pDoc);
+
+ // TODO: add draw code for native data here
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantView printing
+
+BOOL CRadiantView::OnPreparePrinting(CPrintInfo* pInfo)
+{
+ // default preparation
+ return DoPreparePrinting(pInfo);
+}
+
+void CRadiantView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
+{
+ // TODO: add extra initialization before printing
+}
+
+void CRadiantView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
+{
+ // TODO: add cleanup after printing
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantView diagnostics
+
+#ifdef _DEBUG
+void CRadiantView::AssertValid() const
+{
+ CView::AssertValid();
+}
+
+void CRadiantView::Dump(CDumpContext& dc) const
+{
+ CView::Dump(dc);
+}
+
+CRadiantDoc* CRadiantView::GetDocument() // non-debug version is inline
+{
+ ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CRadiantDoc)));
+ return (CRadiantDoc*)m_pDocument;
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CRadiantView message handlers
diff --git a/q3radiant/RadiantView.h b/q3radiant/RadiantView.h
new file mode 100755
index 0000000..4c42a37
--- /dev/null
+++ b/q3radiant/RadiantView.h
@@ -0,0 +1,87 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RadiantView.h : interface of the CRadiantView class
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_RADIANTVIEW_H__330BBF10_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+#define AFX_RADIANTVIEW_H__330BBF10_731C_11D1_B539_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+class CRadiantView : public CView
+{
+protected: // create from serialization only
+ CRadiantView();
+ DECLARE_DYNCREATE(CRadiantView)
+
+// Attributes
+public:
+ CRadiantDoc* GetDocument();
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRadiantView)
+ public:
+ virtual void OnDraw(CDC* pDC); // overridden to draw this view
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ protected:
+ virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
+ virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
+ virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CRadiantView();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CRadiantView)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#ifndef _DEBUG // debug version in RadiantView.cpp
+inline CRadiantDoc* CRadiantView::GetDocument()
+ { return (CRadiantDoc*)m_pDocument; }
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_RADIANTVIEW_H__330BBF10_731C_11D1_B539_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/RotateDlg.cpp b/q3radiant/RotateDlg.cpp
new file mode 100755
index 0000000..8bda1de
--- /dev/null
+++ b/q3radiant/RotateDlg.cpp
@@ -0,0 +1,130 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// RotateDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "RotateDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CRotateDlg dialog
+
+
+CRotateDlg::CRotateDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CRotateDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CRotateDlg)
+ m_strX = _T("");
+ m_strY = _T("");
+ m_strZ = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CRotateDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CRotateDlg)
+ DDX_Control(pDX, IDC_SPIN3, m_wndSpin3);
+ DDX_Control(pDX, IDC_SPIN2, m_wndSpin2);
+ DDX_Control(pDX, IDC_SPIN1, m_wndSpin1);
+ DDX_Text(pDX, IDC_ROTX, m_strX);
+ DDX_Text(pDX, IDC_ROTY, m_strY);
+ DDX_Text(pDX, IDC_ROTZ, m_strZ);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CRotateDlg, CDialog)
+ //{{AFX_MSG_MAP(CRotateDlg)
+ ON_BN_CLICKED(ID_APPLY, OnApply)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN1, OnDeltaposSpin1)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN2, OnDeltaposSpin2)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN3, OnDeltaposSpin3)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CRotateDlg message handlers
+
+void CRotateDlg::OnOK()
+{
+ OnApply();
+ CDialog::OnOK();
+}
+
+void CRotateDlg::OnApply()
+{
+ UpdateData(TRUE);
+ float f = atof(m_strX);
+ if (f != 0.0)
+ Select_RotateAxis(0,f);
+ f = atof(m_strY);
+ if (f != 0.0)
+ Select_RotateAxis(1,f);
+ f = atof(m_strZ);
+ if (f != 0.0)
+ Select_RotateAxis(2,f);
+}
+
+BOOL CRotateDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ m_wndSpin1.SetRange(0, 359);
+ m_wndSpin2.SetRange(0, 359);
+ m_wndSpin3.SetRange(0, 359);
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CRotateDlg::OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ Select_RotateAxis(0, pNMUpDown->iDelta);
+ *pResult = 0;
+}
+
+void CRotateDlg::OnDeltaposSpin2(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ Select_RotateAxis(1, pNMUpDown->iDelta);
+ *pResult = 0;
+}
+
+void CRotateDlg::OnDeltaposSpin3(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ Select_RotateAxis(2, pNMUpDown->iDelta);
+ *pResult = 0;
+}
+
+void CRotateDlg::ApplyNoPaint()
+{
+
+}
diff --git a/q3radiant/RotateDlg.h b/q3radiant/RotateDlg.h
new file mode 100755
index 0000000..d9b00c0
--- /dev/null
+++ b/q3radiant/RotateDlg.h
@@ -0,0 +1,78 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_ROTATEDLG_H__D4B79152_7A7E_11D1_B541_00AA00A410FC__INCLUDED_)
+#define AFX_ROTATEDLG_H__D4B79152_7A7E_11D1_B541_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// RotateDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CRotateDlg dialog
+
+class CRotateDlg : public CDialog
+{
+// Construction
+public:
+ CRotateDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CRotateDlg)
+ enum { IDD = IDD_ROTATE };
+ CSpinButtonCtrl m_wndSpin3;
+ CSpinButtonCtrl m_wndSpin2;
+ CSpinButtonCtrl m_wndSpin1;
+ CString m_strX;
+ CString m_strY;
+ CString m_strZ;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CRotateDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ void ApplyNoPaint();
+
+ // Generated message map functions
+ //{{AFX_MSG(CRotateDlg)
+ virtual void OnOK();
+ afx_msg void OnApply();
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDeltaposSpin1(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDeltaposSpin2(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDeltaposSpin3(NMHDR* pNMHDR, LRESULT* pResult);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ROTATEDLG_H__D4B79152_7A7E_11D1_B541_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/SELECT.CPP b/q3radiant/SELECT.CPP
new file mode 100755
index 0000000..8ccf7f0
--- /dev/null
+++ b/q3radiant/SELECT.CPP
@@ -0,0 +1,1800 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// select.c
+#include "stdafx.h"
+#include "qe3.h"
+
+
+// externs
+CPtrArray g_SelectedFaces;
+CPtrArray g_SelectedFaceBrushes;
+CPtrArray& g_ptrSelectedFaces = g_SelectedFaces;
+CPtrArray& g_ptrSelectedFaceBrushes = g_SelectedFaceBrushes;
+
+
+void clearSelection() {
+ g_qeglobals.d_select_mode = sel_brush;
+ g_qeglobals.selectObject = NULL;
+}
+
+/*
+===========
+Test_Ray
+===========
+*/
+#define DIST_START 999999
+trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags)
+{
+ brush_t *brush;
+ face_t *face;
+ float dist;
+ trace_t t;
+
+ memset (&t, 0, sizeof(t));
+ t.dist = DIST_START;
+
+ if (flags & SF_CYCLE)
+ {
+ CPtrArray array;
+ brush_t *pToSelect = (selected_brushes.next != &selected_brushes) ? selected_brushes.next : NULL;
+ Select_Deselect();
+
+ // go through active brushes and accumulate all "hit" brushes
+ for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
+ {
+ //if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity)
+ // continue;
+
+ if (FilterBrush (brush))
+ continue;
+
+ if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush)
+ continue;
+
+ if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush )
+ continue;
+
+ //if (!g_bShowPatchBounds && brush->patchBrush)
+ // continue;
+
+ face = Brush_Ray (origin, dir, brush, &dist);
+
+ if (face)
+ {
+ if ( brush->terrainBrush )
+ {
+ Terrain_Ray( origin, dir, brush, &dist );
+ if( dist == 0 )
+ {
+ // didn't actually hit the terrain
+ continue;
+ }
+ }
+ array.Add(brush);
+ }
+ }
+
+ int nSize = array.GetSize();
+ if (nSize > 0)
+ {
+ bool bFound = false;
+ for (int i = 0; i < nSize; i++)
+ {
+ brush_t *b = reinterpret_cast<brush_t*>(array.GetAt(i));
+ // did we hit the last one selected yet ?
+ if (b == pToSelect)
+ {
+ // yes we want to select the next one in the list
+ int n = (i > 0) ? i-1 : nSize-1;
+ pToSelect = reinterpret_cast<brush_t*>(array.GetAt(n));
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound)
+ pToSelect = reinterpret_cast<brush_t*>(array.GetAt(0));
+ }
+ if (pToSelect)
+ {
+ face = Brush_Ray (origin, dir, pToSelect, &dist);
+ if ( pToSelect->terrainBrush )
+ {
+ t.terraface = Terrain_Ray( origin, dir, pToSelect, &dist );
+ }
+
+ t.dist = dist;
+ t.brush = pToSelect;
+ t.face = face;
+ t.selected = false;
+ return t;
+ }
+ }
+
+ if (! (flags & SF_SELECTED_ONLY) )
+ {
+ for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
+ {
+ if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity)
+ continue;
+
+ if (FilterBrush (brush))
+ continue;
+
+ if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush)
+ continue;
+
+ if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush )
+ continue;
+
+ //if (!g_bShowPatchBounds && brush->patchBrush)
+ // continue;
+
+ face = Brush_Ray (origin, dir, brush, &dist);
+ if ( face ) {
+ if ( brush->terrainBrush )
+ {
+ t.terraface = Terrain_Ray( origin, dir, brush, &dist );
+ }
+ }
+ if (dist > 0 && dist < t.dist)
+ {
+ t.dist = dist;
+ t.brush = brush;
+ t.face = face;
+ t.selected = false;
+ }
+ }
+ }
+
+
+ for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
+ {
+ if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity)
+ continue;
+
+ if (FilterBrush (brush))
+ continue;
+
+ if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush)
+ continue;
+
+ if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush )
+ continue;
+
+ face = Brush_Ray (origin, dir, brush, &dist);
+ if ( face ) {
+ if ( brush->terrainBrush )
+ {
+ t.terraface = Terrain_Ray( origin, dir, brush, &dist );
+ }
+ }
+ if (dist > 0 && dist < t.dist)
+ {
+ t.dist = dist;
+ t.brush = brush;
+ t.face = face;
+ t.selected = true;
+ }
+ }
+
+ // if entites first, but didn't find any, check regular
+
+ if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL)
+ return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST);
+
+ return t;
+
+}
+
+
+/*
+============
+Select_Brush
+
+============
+*/
+void Select_Brush (brush_t *brush, bool bComplete, bool bStatus)
+{
+ brush_t *b;
+ entity_t *e;
+
+ g_ptrSelectedFaces.RemoveAll();
+ g_ptrSelectedFaceBrushes.RemoveAll();
+ //selected_face = NULL;
+ if (g_qeglobals.d_select_count < 2)
+ g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush;
+ g_qeglobals.d_select_count++;
+
+ //if (brush->patchBrush)
+ // Patch_Select(brush->nPatchID);
+
+ e = brush->owner;
+ if (e)
+ {
+ // select complete entity on first click
+ if (e != world_entity && bComplete == true)
+ {
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ if (b->owner == e)
+ goto singleselect;
+ for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+ }
+ else
+ {
+singleselect:
+ Brush_RemoveFromList (brush);
+ Brush_AddToList (brush, &selected_brushes);
+ UpdateSurfaceDialog();
+ UpdatePatchInspector();
+ }
+
+ if (e->eclass)
+ {
+ UpdateEntitySel(brush->owner->eclass);
+ }
+ }
+ if (bStatus)
+ {
+ vec3_t vMin, vMax, vSize;
+ Select_GetBounds (vMin, vMax);
+ VectorSubtract(vMax, vMin, vSize);
+ CString strStatus;
+ strStatus.Format("Selection X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
+ g_pParentWnd->SetStatusText(2, strStatus);
+ }
+}
+
+
+/*
+============
+Select_Ray
+
+If the origin is inside a brush, that brush will be ignored.
+============
+*/
+void Select_Ray (vec3_t origin, vec3_t dir, int flags)
+{
+ trace_t t;
+
+ t = Test_Ray (origin, dir, flags);
+ if (!t.brush)
+ return;
+
+ if (flags == SF_SINGLEFACE)
+ {
+ int nCount = g_SelectedFaces.GetSize();
+ bool bOk = true;
+ for (int i = 0; i < nCount; i++)
+ {
+ if (t.face == reinterpret_cast<face_t*>(g_SelectedFaces.GetAt(i)))
+ {
+ bOk = false;
+ // need to move remove i'th entry
+ g_SelectedFaces.RemoveAt(i, 1);
+ g_SelectedFaceBrushes.RemoveAt(i, 1);
+ }
+ }
+ if (bOk)
+ {
+ g_SelectedFaces.Add(t.face);
+ g_SelectedFaceBrushes.Add(t.brush);
+ }
+ //selected_face = t.face;
+ //selected_face_brush = t.brush;
+ Sys_UpdateWindows (W_ALL);
+ clearSelection();
+ // Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2 height=2 texture
+ brushprimit_texdef_t brushprimit_texdef;
+ ConvertTexMatWithQTexture ( &t.face->brushprimit_texdef, t.face->d_texture, &brushprimit_texdef, NULL );
+ Texture_SetTexture ( &t.face->texdef, &brushprimit_texdef, false, GETPLUGINTEXDEF(t.face), false );
+ UpdateSurfaceDialog();
+ return;
+ }
+
+ // move the brush to the other list
+
+ clearSelection();
+
+ if (t.selected)
+ {
+ Brush_RemoveFromList (t.brush);
+ Brush_AddToList (t.brush, &active_brushes);
+ UpdatePatchInspector();
+ }
+ else
+ {
+ Select_Brush (t.brush, !(GetKeyState(VK_MENU) & 0x8000));
+ }
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+void Select_Delete (void)
+{
+ brush_t *brush;
+
+ g_ptrSelectedFaces.RemoveAll();
+ g_ptrSelectedFaceBrushes.RemoveAll();
+ //selected_face = NULL;
+
+ clearSelection();
+
+ g_qeglobals.d_select_count = 0;
+ g_qeglobals.d_num_move_points = 0;
+ while (selected_brushes.next != &selected_brushes)
+ {
+ brush = selected_brushes.next;
+ if (brush->patchBrush)
+ {
+ //Patch_Delete(brush->nPatchID);
+ Patch_Delete(brush->pPatch);
+ }
+ if (brush->terrainBrush)
+ {
+ Terrain_Delete(brush->pTerrain );
+ }
+
+ Brush_Free (brush);
+ }
+
+ // FIXME: remove any entities with no brushes
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_Deselect (bool bDeselectFaces)
+{
+ brush_t *b;
+
+ Patch_Deselect();
+
+ g_pParentWnd->ActiveXY()->UndoClear();
+
+ g_qeglobals.d_workcount++;
+ g_qeglobals.d_select_count = 0;
+ g_qeglobals.d_num_move_points = 0;
+ b = selected_brushes.next;
+
+ if (b == &selected_brushes)
+ {
+ if (bDeselectFaces)
+ {
+ g_ptrSelectedFaces.RemoveAll();
+ g_ptrSelectedFaceBrushes.RemoveAll();
+ //selected_face = NULL;
+ }
+ Sys_UpdateWindows (W_ALL);
+ return;
+ }
+
+ if (bDeselectFaces)
+ {
+ g_ptrSelectedFaces.RemoveAll();
+ g_ptrSelectedFaceBrushes.RemoveAll();
+ //selected_face = NULL;
+ }
+
+ clearSelection();
+
+ // grab top / bottom height for new brushes
+ if (b->mins[2] < b->maxs[2])
+ {
+ g_qeglobals.d_new_brush_bottom_z = b->mins[2];
+ g_qeglobals.d_new_brush_top_z = b->maxs[2];
+ }
+
+ selected_brushes.next->prev = &active_brushes;
+ selected_brushes.prev->next = active_brushes.next;
+ active_brushes.next->prev = selected_brushes.prev;
+ active_brushes.next = selected_brushes.next;
+ selected_brushes.prev = selected_brushes.next = &selected_brushes;
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+/*
+============
+Select_Move
+============
+*/
+void Select_Move (vec3_t delta, bool bSnap)
+{
+ brush_t *b;
+
+
+// actually move the selected brushes
+ for (b = selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ Brush_Move (b, delta, bSnap);
+
+ vec3_t vMin, vMax;
+ Select_GetBounds (vMin, vMax);
+ CString strStatus;
+ strStatus.Format("Origin X:: %.1f Y:: %.1f Z:: %.1f", vMin[0], vMax[1], vMax[2]);
+ g_pParentWnd->SetStatusText(2, strStatus);
+
+// Sys_UpdateWindows (W_ALL);
+}
+
+/*
+============
+Select_Clone
+
+Creates an exact duplicate of the selection in place, then moves
+the selected brushes off of their old positions
+============
+*/
+void Select_Clone (void)
+{
+#if 1
+ ASSERT(g_pParentWnd->ActiveXY());
+ g_bScreenUpdates = false;
+ g_pParentWnd->ActiveXY()->Copy();
+ g_pParentWnd->ActiveXY()->Paste();
+ g_pParentWnd->NudgeSelection(2, g_qeglobals.d_gridsize);
+ g_pParentWnd->NudgeSelection(3, g_qeglobals.d_gridsize);
+ g_bScreenUpdates = true;
+ Sys_UpdateWindows(W_ALL);
+#else
+
+ brush_t *b, *b2, *n, *next, *next2;
+ vec3_t delta;
+ entity_t *e;
+
+ g_qeglobals.d_workcount++;
+ clearSelection();
+
+ delta[0] = g_qeglobals.d_gridsize;
+ delta[1] = g_qeglobals.d_gridsize;
+ delta[2] = 0;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=next)
+ {
+ next = b->next;
+ // if the brush is a world brush, handle simply
+ if (b->owner == world_entity)
+ {
+ n = Brush_Clone (b);
+ Brush_AddToList (n, &active_brushes);
+ Entity_LinkBrush (world_entity, n);
+ Brush_Build( n );
+ Brush_Move (b, delta);
+ continue;
+ }
+
+ e = Entity_Clone (b->owner);
+ // clear the target / targetname
+ DeleteKey (e, "target");
+ DeleteKey (e, "targetname");
+
+ // if the brush is a fixed size entity, create a new entity
+ if (b->owner->eclass->fixedsize)
+ {
+ n = Brush_Clone (b);
+ Brush_AddToList (n, &active_brushes);
+ Entity_LinkBrush (e, n);
+ Brush_Build( n );
+ Brush_Move (b, delta);
+ continue;
+ }
+
+ // brush is a complex entity, grab all the other ones now
+
+ next = &selected_brushes;
+
+ for ( b2 = b ; b2 != &selected_brushes ; b2=next2)
+ {
+ next2 = b2->next;
+ if (b2->owner != b->owner)
+ {
+ if (next == &selected_brushes)
+ next = b2;
+ continue;
+ }
+
+ // move b2 to the start of selected_brushes,
+ // so it won't be hit again
+ Brush_RemoveFromList (b2);
+ Brush_AddToList (b2, &selected_brushes);
+
+ n = Brush_Clone (b2);
+ Brush_AddToList (n, &active_brushes);
+ Entity_LinkBrush (e, n);
+ Brush_Build( n );
+ Brush_Move (b2, delta, true);
+ }
+
+ }
+ Sys_UpdateWindows (W_ALL);
+#endif
+}
+
+
+
+/*
+============
+Select_SetTexture
+Timo : bFitScale to compute scale on the plane and counteract plane / axial plane snapping
+Timo : brush primitive texturing
+ the brushprimit_texdef given must be understood as a qtexture_t width=2 height=2 ( HiRes )
+Timo : texture plugin, added an IPluginTexdef* parameter
+ must be casted to an IPluginTexdef!
+ if not NULL, get ->Copy() of it into each face or brush ( and remember to hook )
+ if NULL, means we have no information, ask for a default
+============
+*/
+void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef )
+{
+ brush_t *b;
+ int nCount = g_ptrSelectedFaces.GetSize();
+ if (nCount > 0)
+ {
+ Undo_Start("set face textures");
+ ASSERT(g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize());
+ for (int i = 0; i < nCount; i++)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
+ brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
+ Undo_AddBrush(selBrush);
+ SetFaceTexdef (selBrush, selFace, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef *>(pPlugTexdef) );
+ Brush_Build(selBrush, bFitScale);
+ Undo_EndBrush(selBrush);
+ }
+ Undo_End();
+ }
+ else if (selected_brushes.next != &selected_brushes)
+ {
+ Undo_Start("set brush textures");
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ if (!b->owner->eclass->fixedsize)
+ {
+ Undo_AddBrush(b);
+ Brush_SetTexture (b, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef *>(pPlugTexdef) );
+ Undo_EndBrush(b);
+ }
+ Undo_End();
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+================================================================
+
+ TRANSFORMATIONS
+
+================================================================
+*/
+
+void Select_GetBounds (vec3_t mins, vec3_t maxs)
+{
+ brush_t *b;
+ int i;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ mins[i] = 99999;
+ maxs[i] = -99999;
+ }
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ for (i=0 ; i<3 ; i++)
+ {
+ if (b->mins[i] < mins[i])
+ mins[i] = b->mins[i];
+ if (b->maxs[i] > maxs[i])
+ maxs[i] = b->maxs[i];
+ }
+}
+
+
+void Select_GetTrueMid (vec3_t mid)
+{
+ vec3_t mins, maxs;
+ Select_GetBounds (mins, maxs);
+
+ for (int i=0 ; i<3 ; i++)
+ mid[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
+}
+
+
+void Select_GetMid (vec3_t mid)
+{
+ vec3_t mins, maxs;
+ int i;
+
+ if (g_PrefsDlg.m_bNoClamp)
+ {
+ Select_GetTrueMid(mid);
+ return;
+ }
+
+ Select_GetBounds (mins, maxs);
+
+ for (i=0 ; i<3 ; i++)
+ mid[i] = g_qeglobals.d_gridsize*floor ( ( (mins[i] + maxs[i])*0.5 )/g_qeglobals.d_gridsize );
+
+}
+
+vec3_t select_origin;
+vec3_t select_matrix[3];
+qboolean select_fliporder;
+
+void Select_ApplyMatrix (bool bSnap, bool bRotation, int nAxis, float fDeg)
+{
+ brush_t *b;
+ face_t *f;
+ int i, j;
+ vec3_t temp;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ for (i=0 ; i<3 ; i++)
+ {
+ VectorSubtract (f->planepts[i], select_origin, temp);
+ for (j=0 ; j<3 ; j++)
+ f->planepts[i][j] = DotProduct(temp, select_matrix[j]) + select_origin[j];
+ }
+ if (select_fliporder)
+ {
+ VectorCopy (f->planepts[0], temp);
+ VectorCopy (f->planepts[2], f->planepts[0]);
+ VectorCopy (temp, f->planepts[2]);
+ }
+ }
+
+ if(b->owner->eclass->fixedsize)
+ {
+ if (bRotation && b->owner->md3Class)
+ {
+ b->owner->vRotation[nAxis] += fDeg;
+ }
+ }
+
+ Brush_Build(b, bSnap);
+
+ if (b->patchBrush)
+ {
+ //Patch_ApplyMatrix(b->nPatchID, select_origin, select_matrix);
+ Patch_ApplyMatrix(b->pPatch, select_origin, select_matrix, bSnap);
+ }
+
+ if (b->terrainBrush)
+ {
+ Terrain_ApplyMatrix(b->pTerrain, select_origin, select_matrix, bSnap);
+ }
+
+ }
+}
+
+void ProjectOnPlane(vec3_t& normal,float dist,vec3_t& ez, vec3_t& p)
+{
+ if (fabs(ez[0]) == 1)
+ p[0] = (dist - normal[1] * p[1] - normal[2] * p[2]) / normal[0];
+ else if (fabs(ez[1]) == 1)
+ p[1] = (dist - normal[0] * p[0] - normal[2] * p[2]) / normal[1];
+ else
+ p[2] = (dist - normal[0] * p[0] - normal[1] * p[1]) / normal[2];
+}
+
+void Back(vec3_t& dir, vec3_t& p)
+{
+ if (fabs(dir[0]) == 1)
+ p[0] = 0;
+ else if (fabs(dir[1]) == 1)
+ p[1] = 0;
+ else p[2] = 0;
+}
+
+
+
+// using scale[0] and scale[1]
+void ComputeScale(vec3_t& rex, vec3_t& rey, vec3_t& p, face_t* f)
+{
+ float px = DotProduct(rex, p);
+ float py = DotProduct(rey, p);
+ px *= f->texdef.scale[0];
+ py *= f->texdef.scale[1];
+ vec3_t aux;
+ VectorCopy(rex, aux);
+ VectorScale(aux, px, aux);
+ VectorCopy(aux, p);
+ VectorCopy(rey, aux);
+ VectorScale(aux, py, aux);
+ VectorAdd(p, aux, p);
+}
+
+void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3)
+{
+ vec3_t ex,ey,ez; // local axis base
+
+#ifdef _DEBUG
+ if (g_qeglobals.m_bBrushPrimitMode)
+ Sys_Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n");
+#endif
+
+ // compute first local axis base
+ TextureAxisFromPlane(&f->plane, ex, ey);
+ CrossProduct(ex, ey, ez);
+
+ vec3_t aux;
+ VectorCopy(ex, aux);
+ VectorScale(aux, -f->texdef.shift[0], aux);
+ VectorCopy(aux, p1);
+ VectorCopy(ey, aux);
+ VectorScale(aux, -f->texdef.shift[1], aux);
+ VectorAdd(p1, aux, p1);
+ VectorCopy(p1, p2);
+ VectorAdd(p2, ex, p2);
+ VectorCopy(p1, p3);
+ VectorAdd(p3, ey, p3);
+ VectorCopy(ez, aux);
+ VectorScale(aux, -f->texdef.rotate, aux);
+ VectorRotate(p1, aux, p1);
+ VectorRotate(p2, aux, p2);
+ VectorRotate(p3, aux, p3);
+ // computing rotated local axis base
+ vec3_t rex,rey;
+ VectorCopy(ex, rex);
+ VectorRotate(rex, aux, rex);
+ VectorCopy(ey, rey);
+ VectorRotate(rey, aux, rey);
+
+ ComputeScale(rex,rey,p1,f);
+ ComputeScale(rex,rey,p2,f);
+ ComputeScale(rex,rey,p3,f);
+
+ // project on normal plane
+ // along ez
+ // assumes plane normal is normalized
+ ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p1);
+ ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p2);
+ ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p3);
+};
+
+
+void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3)
+{
+ vec3_t ex,ey,ez;
+
+#ifdef _DEBUG
+ if (g_qeglobals.m_bBrushPrimitMode)
+ Sys_Printf("Warning : illegal call of AbsoluteToLocal in brush primitive mode\n");
+#endif
+
+ // computing new local axis base
+ TextureAxisFromPlane(&normal2, ex, ey);
+ CrossProduct(ex, ey, ez);
+
+ // projecting back on (ex,ey)
+ Back(ez,p1);
+ Back(ez,p2);
+ Back(ez,p3);
+
+ vec3_t aux;
+ // rotation
+ VectorCopy(p2, aux);
+ VectorSubtract(aux, p1,aux);
+
+ float x = DotProduct(aux,ex);
+ float y = DotProduct(aux,ey);
+ f->texdef.rotate = 180 * atan2(y,x) / Q_PI;
+
+ vec3_t rex,rey;
+ // computing rotated local axis base
+ VectorCopy(ez, aux);
+ VectorScale(aux, f->texdef.rotate, aux);
+ VectorCopy(ex, rex);
+ VectorRotate(rex, aux, rex);
+ VectorCopy(ey, rey);
+ VectorRotate(rey, aux, rey);
+
+ // scale
+ VectorCopy(p2, aux);
+ VectorSubtract(aux, p1, aux);
+ f->texdef.scale[0] = DotProduct(aux, rex);
+ VectorCopy(p3, aux);
+ VectorSubtract(aux, p1, aux);
+ f->texdef.scale[1] = DotProduct(aux, rey);
+
+ // shift
+ // only using p1
+ x = DotProduct(rex,p1);
+ y = DotProduct(rey,p1);
+ x /= f->texdef.scale[0];
+ y /= f->texdef.scale[1];
+
+ VectorCopy(rex, p1);
+ VectorScale(p1, x, p1);
+ VectorCopy(rey, aux);
+ VectorScale(aux, y, aux);
+ VectorAdd(p1, aux, p1);
+ VectorCopy(ez, aux);
+ VectorScale(aux, -f->texdef.rotate, aux);
+ VectorRotate(p1, aux, p1);
+ f->texdef.shift[0] = -DotProduct(p1, ex);
+ f->texdef.shift[1] = -DotProduct(p1, ey);
+
+ // stored rot is good considering local axis base
+ // change it if necessary
+ f->texdef.rotate = -f->texdef.rotate;
+
+ Clamp(f->texdef.shift[0], f->d_texture->width);
+ Clamp(f->texdef.shift[1], f->d_texture->height);
+ Clamp(f->texdef.rotate, 360);
+
+}
+
+void RotateFaceTexture(face_t* f, int nAxis, float fDeg)
+{
+ vec3_t p1,p2,p3, rota;
+ p1[0] = p1[1] = p1[2] = 0;
+ VectorCopy(p1, p2);
+ VectorCopy(p1, p3);
+ VectorCopy(p1, rota);
+ ComputeAbsolute(f, p1, p2, p3);
+
+ rota[nAxis] = fDeg;
+ VectorRotate(p1, rota, select_origin, p1);
+ VectorRotate(p2, rota, select_origin, p2);
+ VectorRotate(p3, rota, select_origin, p3);
+
+ plane_t normal2;
+ vec3_t vNormal;
+ vNormal[0] = f->plane.normal[0];
+ vNormal[1] = f->plane.normal[1];
+ vNormal[2] = f->plane.normal[2];
+ VectorRotate(vNormal, rota, vNormal);
+ normal2.normal[0] = vNormal[0];
+ normal2.normal[1] = vNormal[1];
+ normal2.normal[2] = vNormal[2];
+ AbsoluteToLocal(normal2, f, p1, p2 ,p3);
+
+}
+
+void RotateTextures(int nAxis, float fDeg, vec3_t vOrigin)
+{
+ for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (face_t* f=b->brush_faces ; f ; f=f->next)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ RotateFaceTexture_BrushPrimit( f, nAxis, fDeg, vOrigin );
+ else
+ RotateFaceTexture(f, nAxis, fDeg);
+ //++timo removed that call .. works fine .. ???????
+// Brush_Build(b, false);
+ }
+ Brush_Build(b, false);
+ }
+}
+
+
+void Select_FlipAxis (int axis)
+{
+ int i;
+
+ Select_GetMid (select_origin);
+ for (i=0 ; i<3 ; i++)
+ {
+ VectorCopy (vec3_origin, select_matrix[i]);
+ select_matrix[i][i] = 1;
+ }
+ select_matrix[axis][axis] = -1;
+
+ select_fliporder = true;
+ Select_ApplyMatrix (true, false, 0, 0);
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+void Select_Scale(float x, float y, float z)
+{
+ Select_GetMid (select_origin);
+ for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (face_t* f=b->brush_faces ; f ; f=f->next)
+ {
+ for (int i=0 ; i<3 ; i++)
+ {
+ f->planepts[i][0] -= select_origin[0];
+ f->planepts[i][1] -= select_origin[1];
+ f->planepts[i][2] -= select_origin[2];
+ f->planepts[i][0] *= x;
+ //f->planepts[i][0] = floor(f->planepts[i][0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+
+ f->planepts[i][1] *= y;
+ //f->planepts[i][1] = floor(f->planepts[i][1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+
+ f->planepts[i][2] *= z;
+ //f->planepts[i][2] = floor(f->planepts[i][2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+
+ f->planepts[i][0] += select_origin[0];
+ f->planepts[i][1] += select_origin[1];
+ f->planepts[i][2] += select_origin[2];
+ }
+ }
+ Brush_Build(b, false);
+ if (b->patchBrush)
+ {
+ vec3_t v;
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ //Patch_Scale(b->nPatchID, select_origin, v);
+ Patch_Scale(b->pPatch, select_origin, v);
+ }
+ if (b->terrainBrush)
+ {
+ vec3_t v;
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ Terrain_Scale(b->pTerrain, select_origin, v);
+ }
+ }
+}
+
+void Select_RotateAxis (int axis, float deg, bool bPaint, bool bMouse)
+{
+ vec3_t temp;
+ int i, j;
+ vec_t c, s;
+
+ if (deg == 0)
+ {
+ //Sys_Printf("0 deg\n");
+ return;
+ }
+
+ if (bMouse)
+ {
+ VectorCopy(g_pParentWnd->ActiveXY()->RotateOrigin(), select_origin);
+ }
+ else
+ {
+ Select_GetMid (select_origin);
+ }
+
+ select_fliporder = false;
+
+ if (deg == 90)
+ {
+ for (i=0 ; i<3 ; i++)
+ {
+ VectorCopy (vec3_origin, select_matrix[i]);
+ select_matrix[i][i] = 1;
+ }
+ i = (axis+1)%3;
+ j = (axis+2)%3;
+ VectorCopy (select_matrix[i], temp);
+ VectorCopy (select_matrix[j], select_matrix[i]);
+ VectorSubtract (vec3_origin, temp, select_matrix[j]);
+ }
+ else
+ {
+ deg = -deg;
+ if (deg == -180.0)
+ {
+ c = -1;
+ s = 0;
+ }
+ else if (deg == -270.0)
+ {
+ c = 0;
+ s = -1;
+ }
+ else
+ {
+ c = cos(deg * Q_PI / 180.0);
+ s = sin(deg * Q_PI / 180.0);
+ }
+
+ for (i=0 ; i<3 ; i++)
+ {
+ VectorCopy (vec3_origin, select_matrix[i]);
+ select_matrix[i][i] = 1;
+ }
+
+ switch (axis)
+ {
+ case 0:
+ select_matrix[1][1] = c;
+ select_matrix[1][2] = -s;
+ select_matrix[2][1] = s;
+ select_matrix[2][2] = c;
+ break;
+ case 1:
+ select_matrix[0][0] = c;
+ select_matrix[0][2] = s;
+ select_matrix[2][0] = -s;
+ select_matrix[2][2] = c;
+ break;
+ case 2:
+ select_matrix[0][0] = c;
+ select_matrix[0][1] = -s;
+ select_matrix[1][0] = s;
+ select_matrix[1][1] = c;
+ break;
+ }
+ }
+
+ if (g_PrefsDlg.m_bRotateLock)
+ RotateTextures(axis, deg, select_origin);
+ Select_ApplyMatrix(!bMouse, true, axis, deg);
+
+ if (bPaint)
+ Sys_UpdateWindows (W_ALL);
+}
+
+/*
+================================================================
+
+GROUP SELECTIONS
+
+================================================================
+*/
+
+void Select_CompleteTall (void)
+{
+ brush_t *b, *next;
+ //int i;
+ vec3_t mins, maxs;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ clearSelection();
+
+ VectorCopy (selected_brushes.next->mins, mins);
+ VectorCopy (selected_brushes.next->maxs, maxs);
+ Select_Delete ();
+
+ int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
+ int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
+
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+
+ if ( (b->maxs[nDim1] > maxs[nDim1] || b->mins[nDim1] < mins[nDim1])
+ || (b->maxs[nDim2] > maxs[nDim2] || b->mins[nDim2] < mins[nDim2]) )
+ continue;
+
+ if (FilterBrush (b))
+ continue;
+
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+#if 0
+ // old stuff
+ for (i=0 ; i<2 ; i++)
+ if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i])
+ break;
+ if (i == 2)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+#endif
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_PartialTall (void)
+{
+ brush_t *b, *next;
+ //int i;
+ vec3_t mins, maxs;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ clearSelection();
+
+ VectorCopy (selected_brushes.next->mins, mins);
+ VectorCopy (selected_brushes.next->maxs, maxs);
+ Select_Delete ();
+
+ int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
+ int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
+
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+
+ if ( (b->mins[nDim1] > maxs[nDim1] || b->maxs[nDim1] < mins[nDim1])
+ || (b->mins[nDim2] > maxs[nDim2] || b->maxs[nDim2] < mins[nDim2]) )
+ continue;
+
+ if (FilterBrush (b))
+ continue;
+
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+
+
+#if 0
+// old stuff
+ for (i=0 ; i<2 ; i++)
+ if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i])
+ break;
+ if (i == 2)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+#endif
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_Touching (void)
+{
+ brush_t *b, *next;
+ int i;
+ vec3_t mins, maxs;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ clearSelection();
+
+ VectorCopy (selected_brushes.next->mins, mins);
+ VectorCopy (selected_brushes.next->maxs, maxs);
+
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+
+ if (FilterBrush (b))
+ continue;
+
+ for (i=0 ; i<3 ; i++)
+ if (b->mins[i] > maxs[i]+1 || b->maxs[i] < mins[i]-1)
+ break;
+
+ if (i == 3)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_Inside (void)
+{
+ brush_t *b, *next;
+ int i;
+ vec3_t mins, maxs;
+
+ if (!QE_SingleBrush ())
+ return;
+
+ clearSelection();
+
+ VectorCopy (selected_brushes.next->mins, mins);
+ VectorCopy (selected_brushes.next->maxs, maxs);
+ Select_Delete ();
+
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+
+ if (FilterBrush (b))
+ continue;
+
+ for (i=0 ; i<3 ; i++)
+ if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i])
+ break;
+ if (i == 3)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+/*
+=============
+Select_Ungroup
+
+Turn the currently selected entity back into normal brushes
+=============
+*/
+void Select_Ungroup(void)
+{
+ int numselectedgroups;
+ entity_t *e;
+ brush_t *b, *sb;
+
+ numselectedgroups = 0;
+ for (sb = selected_brushes.next; sb != &selected_brushes; sb = sb->next)
+ {
+ e = sb->owner;
+
+ if (!e || e == world_entity || e->eclass->fixedsize)
+ {
+ continue;
+ }
+
+ for (b = e->brushes.onext; b != &e->brushes; b = e->brushes.onext)
+ {
+ //Brush_RemoveFromList (b);
+ //Brush_AddToList (b, &active_brushes);
+ Entity_UnlinkBrush (b);
+ Entity_LinkBrush (world_entity, b);
+ Brush_Build( b );
+ b->owner = world_entity;
+ }
+ Entity_Free (e);
+ numselectedgroups++;
+ }
+
+ if (numselectedgroups <= 0)
+ {
+ Sys_Printf("No grouped entities selected.\n");
+ return;
+ }
+ Sys_Printf("Ungrouped %d entit%s.\n", numselectedgroups, (numselectedgroups == 1)?"y":"ies");
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+====================
+Select_MakeStructural
+====================
+*/
+void Select_MakeStructural (void)
+{
+ brush_t *b;
+ face_t *f;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ for (f=b->brush_faces ; f ; f=f->next)
+ f->texdef.contents &= ~CONTENTS_DETAIL;
+ Select_Deselect ();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_MakeDetail (void)
+{
+ brush_t *b;
+ face_t *f;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ for (f=b->brush_faces ; f ; f=f->next)
+ f->texdef.contents |= CONTENTS_DETAIL;
+ Select_Deselect ();
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_ShiftTexture(int x, int y)
+{
+ brush_t *b;
+ face_t *f;
+
+ int nFaceCount = g_ptrSelectedFaces.GetSize();
+
+ if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
+ return;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // use face normal to compute a true translation
+ Select_ShiftTexture_BrushPrimit( f, x, y );
+ }
+ else
+ {
+ f->texdef.shift[0] += x;
+ f->texdef.shift[1] += y;
+ }
+ }
+ Brush_Build(b);
+ if (b->patchBrush)
+ {
+ //Patch_ShiftTexture(b->nPatchID, x, y);
+ Patch_ShiftTexture(b->pPatch, x, y);
+ }
+ }
+
+ if (nFaceCount > 0)
+ {
+ for (int i = 0; i < nFaceCount; i++)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
+ brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+
+ // use face normal to compute a true translation
+ // Select_ShiftTexture_BrushPrimit( selected_face, x, y );
+ // use camera view to compute texture shift
+ g_pParentWnd->GetCamera()->ShiftTexture_BrushPrimit( selFace, x, y );
+ }
+ else
+ {
+ selFace->texdef.shift[0] += x;
+ selFace->texdef.shift[1] += y;
+ }
+ Brush_Build(selBrush);
+ }
+ }
+
+ Sys_UpdateWindows (W_CAMERA);
+}
+
+void Select_ScaleTexture(int x, int y)
+{
+ brush_t *b;
+ face_t *f;
+
+ int nFaceCount = g_ptrSelectedFaces.GetSize();
+
+ if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
+ {
+ return;
+ }
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // apply same scale as the spinner button of the surface inspector
+ float shift[2];
+ float rotate;
+ float scale[2];
+ brushprimit_texdef_t bp;
+ // compute normalized texture matrix
+ ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL );
+ // compute fake shift scale rot
+ TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
+ // update
+ scale[0]+=static_cast<float>(x)*0.1;
+ scale[1]+=static_cast<float>(y)*0.1;
+ // compute new normalized texture matrix
+ FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
+ // apply to face texture matrix
+ ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture );
+ }
+ else
+ {
+ f->texdef.scale[0] += x;
+ f->texdef.scale[1] += y;
+ }
+ }
+ Brush_Build(b);
+ if (b->patchBrush)
+ {
+ Patch_ScaleTexture(b->pPatch, x, y);
+ }
+ }
+
+ if (nFaceCount > 0)
+ {
+ for (int i = 0; i < nFaceCount; i++)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
+ brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ float shift[2];
+ float rotate;
+ float scale[2];
+ brushprimit_texdef_t bp;
+ ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL );
+ TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
+ scale[0]+=static_cast<float>(x)*0.1;
+ scale[1]+=static_cast<float>(y)*0.1;
+ FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
+ ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture );
+ }
+ else
+ {
+ selFace->texdef.scale[0] += x;
+ selFace->texdef.scale[1] += y;
+ }
+ Brush_Build(selBrush);
+ }
+ }
+
+ Sys_UpdateWindows (W_CAMERA);
+}
+
+void Select_RotateTexture(int amt)
+{
+ brush_t *b;
+ face_t *f;
+
+ int nFaceCount = g_ptrSelectedFaces.GetSize();
+
+ if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
+ {
+ return;
+ }
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // apply same scale as the spinner button of the surface inspector
+ float shift[2];
+ float rotate;
+ float scale[2];
+ brushprimit_texdef_t bp;
+ // compute normalized texture matrix
+ ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL );
+ // compute fake shift scale rot
+ TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
+ // update
+ rotate += amt;
+ // compute new normalized texture matrix
+ FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
+ // apply to face texture matrix
+ ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture );
+ }
+ else
+ {
+ f->texdef.rotate += amt;
+ f->texdef.rotate = static_cast<int>(f->texdef.rotate) % 360;
+ }
+ }
+ Brush_Build(b);
+ if (b->patchBrush)
+ {
+ //Patch_RotateTexture(b->nPatchID, amt);
+ Patch_RotateTexture(b->pPatch, amt);
+ }
+ }
+
+ if (nFaceCount > 0)
+ {
+ for (int i = 0; i < nFaceCount; i++)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
+ brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ float shift[2];
+ float rotate;
+ float scale[2];
+ brushprimit_texdef_t bp;
+ ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL );
+ TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
+ rotate += amt;
+ FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
+ ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture );
+ }
+ else
+ {
+ selFace->texdef.rotate += amt;
+ selFace->texdef.rotate = static_cast<int>(selFace->texdef.rotate) % 360;
+ }
+ Brush_Build(selBrush);
+ }
+ }
+
+ Sys_UpdateWindows (W_CAMERA);
+}
+
+
+void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce)
+{
+ brush_t* pList = (bSelected) ? &selected_brushes : &active_brushes;
+ if (!bSelected)
+ {
+ Select_Deselect();
+ }
+
+ for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next)
+ {
+ if (pBrush->patchBrush)
+ {
+ Patch_FindReplaceTexture(pBrush, pFind, pReplace, bForce);
+ }
+
+ if (pBrush->terrainBrush)
+ {
+ Terrain_FindReplaceTexture(pBrush->pTerrain, pFind, pReplace, bForce);
+ }
+ for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next)
+ {
+ if(bForce || strcmpi(pFace->texdef.name, pFind) == 0)
+ {
+ pFace->d_texture = Texture_ForName(pReplace);
+ //strcpy(pFace->texdef.name, pReplace);
+ pFace->texdef.SetName(pReplace);
+ }
+ }
+ Brush_Build(pBrush);
+ }
+ Sys_UpdateWindows (W_CAMERA);
+}
+
+
+void Select_AllOfType()
+{
+ brush_t *b, *next;
+ entity_t *e;
+ if ( (selected_brushes.next == &selected_brushes)
+ || (selected_brushes.next->next != &selected_brushes) )
+ {
+
+ CString strName;
+ if (g_ptrSelectedFaces.GetSize() == 0)
+ {
+ strName = g_qeglobals.d_texturewin.texdef.name;
+ }
+ else
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ strName = selFace->texdef.name;
+ }
+
+ Select_Deselect();
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+
+ if (FilterBrush (b))
+ continue;
+
+ if (b->patchBrush)
+ {
+ if (strcmpi(strName, b->pPatch->d_texture->name) == 0)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+ }
+ else
+ {
+ for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)
+ {
+ if (strcmpi(strName, pFace->texdef.name) == 0)
+ {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+ }
+ }
+ }
+ Sys_UpdateWindows(W_ALL);
+ return;
+ }
+
+
+ b = selected_brushes.next;
+ e = b->owner;
+
+ if (e != NULL)
+ {
+ if (e != world_entity)
+ {
+ CString strName = e->eclass->name;
+ CString strKey, strVal;
+ bool bCriteria = GetSelectAllCriteria(strKey, strVal);
+ Sys_Printf("Selecting all %s(s)\n", strName);
+ Select_Deselect();
+
+ for (b=active_brushes.next ; b != &active_brushes ; b=next)
+ {
+ next = b->next;
+
+ if (FilterBrush (b))
+ continue;
+
+ e = b->owner;
+ if (e != NULL)
+ {
+ if (strcmpi(e->eclass->name, strName) == 0)
+ {
+ bool doIt = true;
+ if (bCriteria) {
+ CString str = ValueForKey (e, strKey);
+ if (str.CompareNoCase(strVal) != 0) {
+ doIt = false;
+ }
+ }
+ if (doIt) {
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+ }
+ }
+ }
+ }
+ }
+ }
+ Sys_UpdateWindows (W_ALL);
+
+}
+
+void Select_Reselect()
+{
+ CPtrArray holdArray;
+ for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
+ {
+ holdArray.Add(reinterpret_cast<void*>(b));
+ }
+
+ int n = holdArray.GetSize();
+ while (n-- > 0)
+ {
+ b = reinterpret_cast<brush_t*>(holdArray.GetAt(n));
+ Select_Brush(b);
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+void Select_FitTexture(int nHeight, int nWidth)
+{
+ brush_t *b;
+
+ int nFaceCount = g_ptrSelectedFaces.GetSize();
+
+ if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
+ return;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ Brush_FitTexture(b, nHeight, nWidth);
+ Brush_Build(b);
+ }
+
+ if (nFaceCount > 0)
+ {
+ for (int i = 0; i < nFaceCount; i++)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
+ brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
+ Face_FitTexture(selFace, nHeight, nWidth);
+ Brush_Build(selBrush);
+ }
+ }
+
+ Sys_UpdateWindows (W_CAMERA);
+}
+
+void Select_AxialTexture()
+{
+
+}
+
+void Select_Hide()
+{
+ for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
+ {
+ b->hiddenBrush = true;
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+void Select_ShowAllHidden()
+{
+ brush_t* b;
+ for (b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
+ {
+ b->hiddenBrush = false;
+ }
+ for (b=active_brushes.next ; b && b != &active_brushes ; b=b->next)
+ {
+ b->hiddenBrush = false;
+ }
+ Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+============
+Select_Invert
+============
+*/
+void Select_Invert(void)
+{
+ brush_t *next, *prev;
+
+ Sys_Printf("inverting selection...\n");
+
+ next = active_brushes.next;
+ prev = active_brushes.prev;
+ if (selected_brushes.next != &selected_brushes)
+ {
+ active_brushes.next = selected_brushes.next;
+ active_brushes.prev = selected_brushes.prev;
+ active_brushes.next->prev = &active_brushes;
+ active_brushes.prev->next = &active_brushes;
+ }
+ else
+ {
+ active_brushes.next = &active_brushes;
+ active_brushes.prev = &active_brushes;
+ }
+ if (next != &active_brushes)
+ {
+ selected_brushes.next = next;
+ selected_brushes.prev = prev;
+ selected_brushes.next->prev = &selected_brushes;
+ selected_brushes.prev->next = &selected_brushes;
+ }
+ else
+ {
+ selected_brushes.next = &selected_brushes;
+ selected_brushes.prev = &selected_brushes;
+ }
+
+ Sys_UpdateWindows(W_ALL);
+
+ Sys_Printf("done.\n");
+}
+
+
+/*
+===========
+Select_Name
+===========
+*/
+void Select_Name(const char *pName)
+{
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
+ {
+ Brush_SetEpair(b, "Name", pName);
+ }
+ }
+}
+
+/*
+=================
+Select_AddToGroup
+add selected brushes to a group, update the tree
+=================
+*/
+void Select_AddToGroup(const char *pName)
+{
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
+ {
+ Brush_SetEpair(b, "group", pName);
+ Group_AddToProperGroup(b);
+ }
+ }
+}
diff --git a/q3radiant/SELECT.H b/q3radiant/SELECT.H
new file mode 100755
index 0000000..ee6e0dc
--- /dev/null
+++ b/q3radiant/SELECT.H
@@ -0,0 +1,91 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+typedef enum
+{
+ sel_brush,
+ // sel_sticky_brush,
+ // sel_face,
+ sel_vertex,
+ sel_edge,
+ sel_singlevertex,
+ sel_curvepoint,
+ sel_area,
+ sel_terrainpoint,
+ sel_terraintexture,
+ sel_addpoint, // for dropping points
+ sel_editpoint // for editing points
+
+} select_t;
+
+typedef struct
+{
+ brush_t *brush;
+ face_t *face;
+ terrainFace_t *terraface;
+ float dist;
+ qboolean selected;
+} trace_t;
+
+
+#define SF_SELECTED_ONLY 0x01
+#define SF_ENTITIES_FIRST 0x02
+#define SF_SINGLEFACE 0x04
+#define SF_IGNORECURVES 0x08
+#define SF_IGNOREGROUPS 0x10
+#define SF_CYCLE 0x20
+#define SF_CYCLEKEEP 0x40
+
+
+trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags);
+
+void Select_GetBounds (vec3_t mins, vec3_t maxs);
+void Select_Brush (brush_t *b, bool bComplete = true, bool bStatus = true);
+void Select_Ray (vec3_t origin, vec3_t dir, int flags);
+void Select_Delete (void);
+void Select_Deselect (bool bDeselectFaces = true);
+void Select_Invert(void);
+void Select_Clone (void);
+void Select_Move (vec3_t delta, bool bSnap = true);
+void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, void* pPlugTexdef = NULL);
+void Select_FlipAxis (int axis);
+void Select_RotateAxis (int axis, float deg, bool bPaint = true, bool bMouse = false);
+void Select_CompleteTall (void);
+void Select_PartialTall (void);
+void Select_Touching (void);
+void Select_Inside (void);
+void Select_MakeStructural (void);
+void Select_MakeDetail (void);
+void Select_AllOfType();
+void Select_Reselect();
+void Select_FitTexture(int nHeight = 1, int nWidth = 1);
+
+// absolute texture coordinates
+// TTimo NOTE: this is stuff for old brushes format and rotation texture lock .. sort of in-between with bush primitives
+void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3);
+void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3);
+void Select_Hide();
+void Select_ShowAllHidden();
+// add selected brushes to a group, update the tree
+void Select_AddToGroup(const char *pName);
+void Select_Name(const char *pName);
+void clearSelection();
diff --git a/q3radiant/ScaleDialog.cpp b/q3radiant/ScaleDialog.cpp
new file mode 100755
index 0000000..ef487a6
--- /dev/null
+++ b/q3radiant/ScaleDialog.cpp
@@ -0,0 +1,68 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ScaleDialog.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ScaleDialog.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CScaleDialog dialog
+
+
+CScaleDialog::CScaleDialog(CWnd* pParent /*=NULL*/)
+ : CDialog(CScaleDialog::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CScaleDialog)
+ m_fZ = 1.0f;
+ m_fX = 1.0f;
+ m_fY = 1.0f;
+ //}}AFX_DATA_INIT
+}
+
+
+void CScaleDialog::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CScaleDialog)
+ DDX_Text(pDX, IDC_EDIT_Z, m_fZ);
+ DDX_Text(pDX, IDC_EDIT_X, m_fX);
+ DDX_Text(pDX, IDC_EDIT_Y, m_fY);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CScaleDialog, CDialog)
+ //{{AFX_MSG_MAP(CScaleDialog)
+ // NOTE: the ClassWizard will add message map macros here
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CScaleDialog message handlers
diff --git a/q3radiant/ScaleDialog.h b/q3radiant/ScaleDialog.h
new file mode 100755
index 0000000..d7fe920
--- /dev/null
+++ b/q3radiant/ScaleDialog.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_SCALEDIALOG_H__8A9B33B2_9922_11D1_B568_00AA00A410FC__INCLUDED_)
+#define AFX_SCALEDIALOG_H__8A9B33B2_9922_11D1_B568_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// ScaleDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CScaleDialog dialog
+
+class CScaleDialog : public CDialog
+{
+// Construction
+public:
+ CScaleDialog(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CScaleDialog)
+ enum { IDD = IDD_DIALOG_SCALE };
+ float m_fZ;
+ float m_fX;
+ float m_fY;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CScaleDialog)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CScaleDialog)
+ // NOTE: the ClassWizard will add member functions here
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_SCALEDIALOG_H__8A9B33B2_9922_11D1_B568_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/ScriptDlg.cpp b/q3radiant/ScriptDlg.cpp
new file mode 100755
index 0000000..8774001
--- /dev/null
+++ b/q3radiant/ScriptDlg.cpp
@@ -0,0 +1,103 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ScriptDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ScriptDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CScriptDlg dialog
+
+
+CScriptDlg::CScriptDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CScriptDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CScriptDlg)
+ m_strScript = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CScriptDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CScriptDlg)
+ DDX_Control(pDX, IDC_LIST_SCRIPTS, m_lstScripts);
+ DDX_LBString(pDX, IDC_LIST_SCRIPTS, m_strScript);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CScriptDlg, CDialog)
+ //{{AFX_MSG_MAP(CScriptDlg)
+ ON_BN_CLICKED(ID_RUN, OnRun)
+ ON_LBN_DBLCLK(IDC_LIST_SCRIPTS, OnDblclkListScripts)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CScriptDlg message handlers
+
+void CScriptDlg::OnRun()
+{
+ UpdateData(TRUE);
+ EndDialog(IDOK);
+ RunScriptByName(m_strScript.GetBuffer(0), true);
+}
+
+BOOL CScriptDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ char* pBuff = new char[16384];
+ CString strINI = g_strAppPath;
+ strINI += "\\scripts.ini";
+ int n = GetPrivateProfileSectionNames(pBuff, 16384, strINI);
+
+ // CStringList list;
+ m_lstScripts.ResetContent();
+ char* pWorkBuff = pBuff;
+ while (*pWorkBuff != NULL)
+ {
+ m_lstScripts.AddString(pWorkBuff);
+ pWorkBuff += strlen(pWorkBuff) + 1;
+ }
+ delete []pBuff;
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+
+void CScriptDlg::OnDblclkListScripts()
+{
+ UpdateData(TRUE);
+ EndDialog(IDOK);
+ RunScriptByName(m_strScript.GetBuffer(0), true);
+}
diff --git a/q3radiant/ScriptDlg.h b/q3radiant/ScriptDlg.h
new file mode 100755
index 0000000..427ef95
--- /dev/null
+++ b/q3radiant/ScriptDlg.h
@@ -0,0 +1,70 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_SCRIPTDLG_H__C241B9A4_819F_11D1_B548_00AA00A410FC__INCLUDED_)
+#define AFX_SCRIPTDLG_H__C241B9A4_819F_11D1_B548_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// ScriptDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CScriptDlg dialog
+
+class CScriptDlg : public CDialog
+{
+// Construction
+public:
+ CScriptDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CScriptDlg)
+ enum { IDD = IDD_DLG_SCRIPTS };
+ CListBox m_lstScripts;
+ CString m_strScript;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CScriptDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CScriptDlg)
+ afx_msg void OnRun();
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDblclkListScripts();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_SCRIPTDLG_H__C241B9A4_819F_11D1_B548_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/SelectedFace.cpp b/q3radiant/SelectedFace.cpp
new file mode 100755
index 0000000..c1bd18b
--- /dev/null
+++ b/q3radiant/SelectedFace.cpp
@@ -0,0 +1,136 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:18:13 $
+// $Log: SelectedFace.cpp,v $
+// Revision 1.1.1.4 2000/01/18 00:18:13 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:43 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:12 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:45 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:41 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:45 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:47 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.4.2 1999/11/14 16:26:13 Timo & Christine
+// first beta of the ritualmap surface plugin
+//
+// Revision 1.1.4.1 1999/11/03 20:38:02 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+// Revision 1.1.2.1 1999/10/27 08:34:28 Timo & Christine
+// preview version of the texture tools plugin is ready
+// ( TexTool.dll plugin is in Q3Plugin module )
+// plugins can draw in their own window using Radiant's qgl bindings
+//
+//
+// DESCRIPTION:
+// Quick interface hack for selected face interface
+// this one really needs more work, but I'm in a hurry with TexTool
+
+#include "stdafx.h"
+
+HGLRC WINAPI QERApp_GetQeglobalsHGLRC()
+{
+ return g_qeglobals.d_hglrcBase;
+}
+
+// pWinding is supposed to have MAX_POINTS_ON_WINDING
+int WINAPI QERApp_GetFaceInfo(_QERFaceData *pFaceData, winding_t *pWinding)
+{
+ int size;
+
+ if (g_ptrSelectedFaces.GetSize() > 0)
+ {
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ Sys_Printf("Warning: unexpected QERApp_GetFaceInfo out of brush primitive mode\n");
+ return 0;
+ }
+ //++timo NOTE: let's put only what we need for now
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ strcpy( pFaceData->m_TextureName, selFace->texdef.name );
+ VectorCopy( selFace->planepts[0], pFaceData->m_v1 );
+ VectorCopy( selFace->planepts[1], pFaceData->m_v2 );
+ VectorCopy( selFace->planepts[2], pFaceData->m_v3 );
+ pFaceData->m_bBPrimit = true;
+ memcpy( &pFaceData->brushprimit_texdef, &selFace->brushprimit_texdef, sizeof(brushprimit_texdef_t) );
+ size = (int)((winding_t *)0)->points[selFace->face_winding->numpoints];
+ memcpy( pWinding, selFace->face_winding, size );
+ return 1;
+ }
+ return 0;
+}
+
+int WINAPI QERApp_SetFaceInfo(_QERFaceData *pFaceData)
+{
+ if (g_ptrSelectedFaces.GetSize() > 0)
+ {
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ Sys_Printf("Warning: unexpected QERApp_SetFaceInfo out of brush primitive mode\n");
+ return 0;
+ }
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(0));
+ //strcpy( selected_face->texdef.name, pFaceData->m_TextureName );
+ selFace->texdef.SetName(pFaceData->m_TextureName);
+ VectorCopy( pFaceData->m_v1, selFace->planepts[0] );
+ VectorCopy( pFaceData->m_v2, selFace->planepts[1] );
+ VectorCopy( pFaceData->m_v3, selFace->planepts[2] );
+ memcpy( &selFace->brushprimit_texdef, &pFaceData->brushprimit_texdef, sizeof(brushprimit_texdef_t) );
+ Brush_Build( selBrush );
+ Sys_UpdateWindows(W_ALL);
+ return 1;
+ }
+ return 0;
+}
+
+void WINAPI QERApp_GetTextureSize( int Size[2] )
+{
+ if (g_ptrSelectedFaces.GetSize() > 0)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ Size[0] = selFace->d_texture->width;
+ Size[1] = selFace->d_texture->height;
+ }
+ else
+ Sys_Printf("WARNING: unexpected call to QERApp_GetTextureSize with no selected_face\n");
+} \ No newline at end of file
diff --git a/q3radiant/ShaderEdit.cpp b/q3radiant/ShaderEdit.cpp
new file mode 100755
index 0000000..965b555
--- /dev/null
+++ b/q3radiant/ShaderEdit.cpp
@@ -0,0 +1,66 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ShaderEdit.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ShaderEdit.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CShaderEdit
+
+IMPLEMENT_DYNCREATE(CShaderEdit, CFrameWnd)
+
+CShaderEdit::CShaderEdit()
+{
+}
+
+CShaderEdit::~CShaderEdit()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CShaderEdit, CFrameWnd)
+ //{{AFX_MSG_MAP(CShaderEdit)
+ ON_WM_CREATE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CShaderEdit message handlers
+
+int CShaderEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ // TODO: Add your specialized creation code here
+
+ return 0;
+}
diff --git a/q3radiant/ShaderEdit.h b/q3radiant/ShaderEdit.h
new file mode 100755
index 0000000..cad8bbf
--- /dev/null
+++ b/q3radiant/ShaderEdit.h
@@ -0,0 +1,70 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_SHADEREDIT_H__CFE2CBF1_E980_11D2_A509_0020AFEB881A__INCLUDED_)
+#define AFX_SHADEREDIT_H__CFE2CBF1_E980_11D2_A509_0020AFEB881A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ShaderEdit.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CShaderEdit frame
+
+class CShaderEdit : public CFrameWnd
+{
+ DECLARE_DYNCREATE(CShaderEdit)
+protected:
+ CShaderEdit(); // protected constructor used by dynamic creation
+
+ CStatusBar m_StatusBar;
+ CToolBar m_ToolBar;
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CShaderEdit)
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ virtual ~CShaderEdit();
+
+ // Generated message map functions
+ //{{AFX_MSG(CShaderEdit)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_SHADEREDIT_H__CFE2CBF1_E980_11D2_A509_0020AFEB881A__INCLUDED_)
diff --git a/q3radiant/ShaderInfo.cpp b/q3radiant/ShaderInfo.cpp
new file mode 100755
index 0000000..d898865
--- /dev/null
+++ b/q3radiant/ShaderInfo.cpp
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ShaderInfo.cpp: implementation of the CShaderInfo class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ShaderInfo.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CShaderInfo::CShaderInfo()
+{
+ m_fTransValue = 1.0;
+ m_nFlags = 0;
+ m_pQTexture = NULL;
+}
+
+CShaderInfo::~CShaderInfo()
+{
+
+}
+
+void CShaderInfo::Parse(const char *pName)
+{
+
+}
+
+void CShaderInfo::setName(char *pName)
+{
+ //--char path[1024];
+ //--strcpy(path, pName);
+ //--DefaultExtension(path, ".tga");
+ m_strName = pName;
+ m_strName.MakeLower();
+ if (m_strName.Find("textures") == 0)
+ {
+ CString s = m_strName.Right(m_strName.GetLength() - strlen("textures") - 1);
+ m_strName = s;
+ }
+}
diff --git a/q3radiant/ShaderInfo.h b/q3radiant/ShaderInfo.h
new file mode 100755
index 0000000..bca4414
--- /dev/null
+++ b/q3radiant/ShaderInfo.h
@@ -0,0 +1,55 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ShaderInfo.h: interface for the CShaderInfo class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_SHADERINFO_H__93B64600_A208_11D2_803D_0020AFEB881A__INCLUDED_)
+#define AFX_SHADERINFO_H__93B64600_A208_11D2_803D_0020AFEB881A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CShaderInfo
+{
+public:
+ CString m_strName;
+ CString m_strShaderName;
+ CString m_strTextureName;
+ CStringList m_strEditorParams;
+ CStringList m_lstSurfaceParams;
+ float m_fTransValue;
+ int m_nFlags;
+ qtexture_t *m_pQTexture;
+
+
+ void Parse(const char *pName);
+ CShaderInfo();
+ virtual ~CShaderInfo();
+ void setName(char *pName);
+
+
+
+};
+
+#endif // !defined(AFX_SHADERINFO_H__93B64600_A208_11D2_803D_0020AFEB881A__INCLUDED_)
diff --git a/q3radiant/StdAfx.cpp b/q3radiant/StdAfx.cpp
new file mode 100755
index 0000000..dc9c067
--- /dev/null
+++ b/q3radiant/StdAfx.cpp
@@ -0,0 +1,27 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// stdafx.cpp : source file that includes just the standard includes
+// Radiant.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
diff --git a/q3radiant/StdAfx.h b/q3radiant/StdAfx.h
new file mode 100755
index 0000000..5a9e543
--- /dev/null
+++ b/q3radiant/StdAfx.h
@@ -0,0 +1,154 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__330BBF08_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+#define AFX_STDAFX_H__330BBF08_731C_11D1_B539_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#pragma warning(disable: 4305) // For: double to float
+#pragma warning(disable: 4800) // For: performance warning on bool conversions
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdisp.h> // MFC OLE automation classes
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__330BBF08_731C_11D1_B539_00AA00A410FC__INCLUDED_)
+
+#include "MainFrm.h"
+#include "PrefsDlg.h"
+#include "FindTextureDlg.h"
+
+
+extern CMainFrame* g_pParentWnd;
+extern CString g_strAppPath;
+extern CPrefsDlg& g_PrefsDlg;
+extern CFindTextureDlg& g_dlgFind;
+
+// layout styles
+#define QR_SPLIT 0
+#define QR_QE4 1
+#define QR_4WAY 2
+#define QR_SPLITZ 3
+
+
+// externs
+extern void AddSlash(CString&);
+extern void DLLBuildDone();
+extern void CleanUpEntities();
+extern void MFCCreate(HINSTANCE);
+extern BOOL Init3Dfx();
+extern void FindReplace(CString& strContents, const char* pTag, const char* pValue);
+extern void CheckBspProcess();
+extern void QE_CountBrushesAndUpdateStatusBar();
+extern void QE_CheckAutoSave();
+extern qtexture_t *notexture;
+extern qtexture_t *current_texture;
+extern BOOL SaveWindowState(HWND hWnd, const char *pszName);
+extern BOOL DoMru(HWND, WORD);
+extern void RunBsp (char *command);
+extern void Map_Snapshot();
+extern void WXY_Print();
+extern void AddProp( void );
+extern qboolean DoColor(int iIndex);
+extern entity_t *edit_entity;
+extern int inspector_mode;
+extern bool g_bRotateMode;
+extern bool g_bClipMode;
+extern bool g_bScaleMode;
+extern int g_nScaleHow;
+extern bool g_bPathMode;
+extern bool ByeByeSurfaceDialog();
+extern void RunScript(char* pBuffer);
+extern bool ExtractPath_and_Filename(const char* pPath, CString& strPath, CString& strFilename);
+extern HINSTANCE g_hOpenGL32;
+extern void Select_Scale(float x, float y, float z);
+extern void Select_RotateTexture(int amt);
+extern void Select_ScaleTexture(int x, int y);
+extern void Select_ShiftTexture(int x, int y);
+extern void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce);
+extern void DoProjectSettings();
+extern qboolean region_active;
+extern void Brush_Print(brush_t* b);
+extern void Texture_ShowDirectory (char* pPath, bool Linked = false);
+extern void Map_ImportFile (char *filename);
+extern void Map_SaveSelected(char* pFilename);
+extern void UpdateSurfaceDialog();
+extern bool g_bNewFace;
+extern void Select_GetTrueMid (vec3_t mid);
+extern bool g_bSwitch;
+extern brush_t g_brFrontSplits;
+extern brush_t g_brBackSplits;
+extern CClipPoint g_Clip1;
+extern CClipPoint g_Clip2;
+extern brush_t* g_pSplitList;
+extern CClipPoint g_PathPoints[256];
+extern void AcquirePath(int nCount, PFNPathCallback* pFunc);
+extern bool g_bScreenUpdates;
+extern SCommandInfo g_Commands[];
+extern int g_nCommandCount;
+extern SKeyInfo g_Keys[];
+extern int g_nKeyCount;
+extern int inspector_mode;
+extern char *bsp_commands[256];
+extern void RunScriptByName(char*, bool);
+extern void DoNewColor(int* i1, int* i2, int* i3);
+extern void UpdateSurfaceDialog();
+extern void CSG_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back);
+extern void HandlePopup(CWnd* pWindow, unsigned int uId);
+extern z_t z;
+extern void Select_Scale(float x, float y, float z);
+extern CString g_strProject;
+extern void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv);
+extern void VectorRotate (vec3_t va, vec3_t vb, vec3_t out);
+extern void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out);
+extern qboolean QE_SaveProject (const char* pProjectFile);
+extern void NewBSP(char* pCommandLine, HWND);
+extern void NewVIS(char* pCommandLine, HWND);
+extern void NewRAD(char* pCommandLine, HWND);
+extern void RunTools(char* pCommandLine, HWND, const char*);
+extern void Clamp(float& f, int nClamp);
+extern void MemFile_fprintf(CMemFile* pMemFile, const char* pText, ...);
+extern void SaveWindowPlacement(HWND hwnd, const char* pName);
+extern bool LoadWindowPlacement(HWND hwnd, const char* pName);
+extern qboolean ConfirmModified (void);
+extern void DoPatchInspector();
+void UpdatePatchInspector();
+extern int BuildShortPathName(const char* pPath, char* pBuffer, int nBufferLen);
+extern int g_nBrushId;
+
+
diff --git a/q3radiant/SurfaceDlg.cpp b/q3radiant/SurfaceDlg.cpp
new file mode 100755
index 0000000..6930126
--- /dev/null
+++ b/q3radiant/SurfaceDlg.cpp
@@ -0,0 +1,983 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// SurfaceDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "SurfaceDlg.h"
+#include "PrefsDlg.h"
+#include "mainfrm.h"
+#include "TextureLayout.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// surface properties plugin
+// global flag for surface properties plugin is g_qeglobals.bSurfacePropertiesPlugin
+_QERPlugSurfaceTable g_SurfaceTable;
+
+/////////////////////////////////////////////////////////////////////////////
+// CSurfaceDlg dialog
+
+CSurfaceDlg g_dlgSurface;
+
+
+CSurfaceDlg::CSurfaceDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CSurfaceDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CSurfaceDlg)
+ m_nHeight = 1;
+ m_nWidth = 1;
+ //}}AFX_DATA_INIT
+}
+
+
+void CSurfaceDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSurfaceDlg)
+ DDX_Control(pDX, IDC_SPIN_WIDTH, m_wndWidth);
+ DDX_Control(pDX, IDC_SPIN_HEIGHT, m_wndHeight);
+ DDX_Control(pDX, IDC_SPIN_VSHIFT, m_wndVShift);
+ DDX_Control(pDX, IDC_SPIN_VSCALE, m_wndVScale);
+ DDX_Control(pDX, IDC_SPIN_ROTATE, m_wndRotate);
+ DDX_Control(pDX, IDC_SPIN_HSHIFT, m_wndHShift);
+ DDX_Control(pDX, IDC_SPIN_HSCALE, m_wndHScale);
+ DDX_Text(pDX, IDC_EDIT_HEIGHT, m_nHeight);
+ DDV_MinMaxInt(pDX, m_nHeight, 1, 32);
+ DDX_Text(pDX, IDC_EDIT_WIDTH, m_nWidth);
+ DDV_MinMaxInt(pDX, m_nWidth, 1, 32);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CSurfaceDlg, CDialog)
+ //{{AFX_MSG_MAP(CSurfaceDlg)
+ ON_WM_HSCROLL()
+ ON_WM_KEYDOWN()
+ ON_WM_VSCROLL()
+ ON_BN_CLICKED(IDAPPLY, OnApply)
+ ON_WM_CLOSE()
+ ON_WM_DESTROY()
+ ON_BN_CLICKED(ID_BTN_CANCEL, OnBtnCancel)
+ ON_BN_CLICKED(IDC_BTN_COLOR, OnBtnColor)
+ ON_WM_CTLCOLOR()
+ ON_WM_CREATE()
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HSHIFT, OnDeltaPosSpin)
+ ON_BN_CLICKED(IDC_BTN_PATCHDETAILS, OnBtnPatchdetails)
+ ON_BN_CLICKED(IDC_BTN_PATCHNATURAL, OnBtnPatchnatural)
+ ON_BN_CLICKED(IDC_BTN_PATCHRESET, OnBtnPatchreset)
+ ON_BN_CLICKED(IDC_BTN_PATCHFIT, OnBtnPatchfit)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HSCALE, OnDeltaPosSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ROTATE, OnDeltaPosSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VSCALE, OnDeltaPosSpin)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VSHIFT, OnDeltaPosSpin)
+ ON_BN_CLICKED(IDC_BTN_AXIAL, OnBtnAxial)
+ ON_BN_CLICKED(IDC_BTN_BRUSHFIT, OnBtnBrushfit)
+ ON_BN_CLICKED(IDC_BTN_FACEFIT, OnBtnFacefit)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CSurfaceDlg message handlers
+
+
+/*
+===================================================
+
+ SURFACE INSPECTOR
+
+===================================================
+*/
+
+texdef_t g_old_texdef;
+texdef_t g_patch_texdef;
+HWND g_surfwin = NULL;
+qboolean g_changed_surface;
+
+int g_checkboxes[64] = {
+ IDC_CHECK1, IDC_CHECK2, IDC_CHECK3, IDC_CHECK4,
+ IDC_CHECK5, IDC_CHECK6, IDC_CHECK7, IDC_CHECK8,
+ IDC_CHECK9, IDC_CHECK10, IDC_CHECK11, IDC_CHECK12,
+ IDC_CHECK13, IDC_CHECK14, IDC_CHECK15, IDC_CHECK16,
+ IDC_CHECK17, IDC_CHECK18, IDC_CHECK19, IDC_CHECK20,
+ IDC_CHECK21, IDC_CHECK22, IDC_CHECK23, IDC_CHECK24,
+ IDC_CHECK25, IDC_CHECK26, IDC_CHECK27, IDC_CHECK28,
+ IDC_CHECK29, IDC_CHECK30, IDC_CHECK31, IDC_CHECK32,
+
+ IDC_CHECK33, IDC_CHECK34, IDC_CHECK35, IDC_CHECK36,
+ IDC_CHECK37, IDC_CHECK38, IDC_CHECK39, IDC_CHECK40,
+ IDC_CHECK41, IDC_CHECK42, IDC_CHECK43, IDC_CHECK44,
+ IDC_CHECK45, IDC_CHECK46, IDC_CHECK47, IDC_CHECK48,
+ IDC_CHECK49, IDC_CHECK50, IDC_CHECK51, IDC_CHECK52,
+ IDC_CHECK53, IDC_CHECK54, IDC_CHECK55, IDC_CHECK56,
+ IDC_CHECK57, IDC_CHECK58, IDC_CHECK59, IDC_CHECK60,
+ IDC_CHECK61, IDC_CHECK62, IDC_CHECK63, IDC_CHECK64
+ };
+
+/*
+==============
+SetTexMods
+
+Set the fields to the current texdef
+if one face selected -> will read this face texdef, else current texdef
+if only patches selected, will read the patch texdef
+===============
+*/
+
+bool g_bNewFace = false;
+bool g_bNewApplyHandling = false;
+bool g_bGatewayhack = false;
+
+void CSurfaceDlg::SetTexMods()
+{
+ char sz[128];
+ texdef_t *pt;
+ brushprimit_texdef_t *bpt;
+ // local copy if a width=2 height=2 qtetxture_t is needed
+ brushprimit_texdef_t local_bp;
+ int i;
+
+ if (!g_surfwin)
+ return;
+
+ m_bPatchMode = false;
+
+ if (OnlyPatchesSelected())
+ {
+ pt = &g_qeglobals.d_texturewin.texdef;
+ if (QE_SingleBrush())
+ {
+ //strcpy(g_patch_texdef.name, Patch_GetTextureName());
+ g_patch_texdef.SetName(Patch_GetTextureName());
+ }
+ else
+ {
+ //strcpy(g_patch_texdef.name, pt->name);
+ g_patch_texdef.SetName(pt->name);
+ }
+ g_patch_texdef.contents = pt->contents;
+ g_patch_texdef.flags = pt->flags;
+ g_patch_texdef.value = pt->value;
+ pt = &g_patch_texdef;
+ m_bPatchMode = true;
+ }
+ else
+ {
+ if (g_bNewFace && g_ptrSelectedFaces.GetSize() > 0)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ pt = &selFace->texdef;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // compute a texture matrix related to the default matrix width=2 height=2
+ ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &local_bp, NULL );
+ bpt = &local_bp;
+ }
+ }
+ else
+ {
+ pt = &g_qeglobals.d_texturewin.texdef;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ bpt = &g_qeglobals.d_texturewin.brushprimit_texdef;
+ }
+ }
+ // brush primitive mode : compute fake shift scale rot representation
+ if (g_qeglobals.m_bBrushPrimitMode)
+ TexMatToFakeTexCoords( bpt->coords, m_shift, &m_rotate, m_scale );
+ }
+
+ SendMessage (WM_SETREDRAW, 0, 0);
+
+ ::SetWindowText(GetDlgItem(IDC_TEXTURE)->GetSafeHwnd(), pt->name);
+
+ if (m_bPatchMode)
+ sprintf(sz, "%4.6f", pt->shift[0]);
+ else
+ if (g_qeglobals.m_bBrushPrimitMode)
+ sprintf(sz, "%d", (int)m_shift[0]);
+ else
+ sprintf(sz, "%d", (int)pt->shift[0]);
+ ::SetWindowText(GetDlgItem(IDC_HSHIFT)->GetSafeHwnd(), sz);
+
+ if (m_bPatchMode)
+ sprintf(sz, "%4.6f", pt->shift[1]);
+ else
+ if (g_qeglobals.m_bBrushPrimitMode)
+ sprintf(sz, "%d", (int)m_shift[1]);
+ else
+ sprintf(sz, "%d", (int)pt->shift[1]);
+ ::SetWindowText(GetDlgItem(IDC_VSHIFT)->GetSafeHwnd(), sz);
+
+ sprintf(sz, m_bPatchMode ? "%4.6f" : "%4.6f", g_qeglobals.m_bBrushPrimitMode ? m_scale[0] : pt->scale[0]);
+ ::SetWindowText(GetDlgItem(IDC_HSCALE)->GetSafeHwnd(), sz);
+
+ sprintf(sz, m_bPatchMode ? "%4.6f" : "%4.6f", g_qeglobals.m_bBrushPrimitMode ? m_scale[1] : pt->scale[1]);
+ ::SetWindowText(GetDlgItem(IDC_VSCALE)->GetSafeHwnd(), sz);
+
+ //++timo compute BProtate as int ..
+ sprintf(sz, "%d", g_qeglobals.m_bBrushPrimitMode ? (int)m_rotate : (int)pt->rotate);
+ ::SetWindowText(GetDlgItem(IDC_ROTATE)->GetSafeHwnd(), sz);
+
+ sprintf(sz, "%d", (int)pt->value);
+ ::SetWindowText(GetDlgItem(IDC_VALUE)->GetSafeHwnd(), sz);
+
+ for (i=0 ; i<32 ; i++)
+ ::SendMessage(GetDlgItem(g_checkboxes[i])->GetSafeHwnd(), BM_SETCHECK, !!(pt->flags&(1<<i)), 0 );
+ for (i=0 ; i<32 ; i++)
+ ::SendMessage(GetDlgItem(g_checkboxes[32+i])->GetSafeHwnd(), BM_SETCHECK, !!(pt->contents&(1<<i)), 0 );
+
+ SendMessage (WM_SETREDRAW, 1, 0);
+ InvalidateRect (NULL, true);
+}
+
+void CSurfaceDlg::GrabPatchMods()
+{
+ char sz[128];
+ int i;
+ bool b;
+ texdef_t *pt = & g_patch_texdef;
+
+ ::GetWindowText (GetDlgItem(IDC_HSHIFT)->GetSafeHwnd(), sz, 127);
+ pt->shift[0] = atof(sz);
+
+ ::GetWindowText (GetDlgItem(IDC_VSHIFT)->GetSafeHwnd(), sz, 127);
+ pt->shift[1] = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_HSCALE)->GetSafeHwnd(), sz, 127);
+ pt->scale[0] = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_VSCALE)->GetSafeHwnd(), sz, 127);
+ pt->scale[1] = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_ROTATE)->GetSafeHwnd(), sz, 127);
+ pt->rotate = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_VALUE)->GetSafeHwnd(), sz, 127);
+ pt->value = atof(sz);
+
+ pt->flags = 0;
+ for (i=0 ; i<32 ; i++)
+ {
+ b = ::SendMessage(GetDlgItem(g_checkboxes[i])->GetSafeHwnd(), BM_GETCHECK, 0, 0);
+ if (b != 1 && b != 0)
+ continue;
+ pt->flags |= b<<i;
+ }
+
+ pt->contents = 0;
+ for (i=0 ; i<32 ; i++)
+ {
+ b = ::SendMessage(GetDlgItem(g_checkboxes[32+i])->GetSafeHwnd(), BM_GETCHECK, 0, 0);
+ if (b != 1 && b != 0)
+ continue;
+ pt->contents |= b<<i;
+ }
+
+}
+
+/*
+==============
+GetTexMods
+
+Reads the fields to get the current texdef
+in brush primitive mode, grab the fake shift scale rot and compute a new texture matrix
+===============
+*/
+void CSurfaceDlg::GetTexMods()
+{
+ char sz[128];
+ texdef_t *pt;
+ int b;
+ int i;
+
+ m_bPatchMode = false;
+
+ if (OnlyPatchesSelected())
+ {
+ pt = &g_qeglobals.d_texturewin.texdef;
+ m_bPatchMode = true;
+ }
+ else
+ {
+ if (g_bNewFace && g_ptrSelectedFaces.GetSize() > 0)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ pt = &selFace->texdef;
+ }
+ else
+ {
+ pt = &g_qeglobals.d_texturewin.texdef;
+ }
+ }
+
+ ::GetWindowText (GetDlgItem(IDC_TEXTURE)->GetSafeHwnd(), sz, 127);
+ //strncpy (pt->name, sz, sizeof(pt->name)-1);
+ pt->SetName(sz);
+ if (pt->name[0] <= ' ')
+ {
+ //strcpy (pt->name, "none");
+ pt->SetName("none");
+ ::SetWindowText(GetDlgItem(IDC_TEXTURE)->GetSafeHwnd(), pt->name);
+ }
+
+ ::GetWindowText (GetDlgItem(IDC_HSHIFT)->GetSafeHwnd(), sz, 127);
+ ( g_qeglobals.m_bBrushPrimitMode ? m_shift[0] : pt->shift[0] ) = atof(sz);
+
+ ::GetWindowText (GetDlgItem(IDC_VSHIFT)->GetSafeHwnd(), sz, 127);
+ ( g_qeglobals.m_bBrushPrimitMode ? m_shift[1] : pt->shift[1] ) = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_HSCALE)->GetSafeHwnd(), sz, 127);
+ ( g_qeglobals.m_bBrushPrimitMode ? m_scale[0] : pt->scale[0] ) = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_VSCALE)->GetSafeHwnd(), sz, 127);
+ ( g_qeglobals.m_bBrushPrimitMode ? m_scale[1] : pt->scale[1] ) = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_ROTATE)->GetSafeHwnd(), sz, 127);
+ ( g_qeglobals.m_bBrushPrimitMode ? m_rotate : pt->rotate ) = atof(sz);
+
+ ::GetWindowText(GetDlgItem(IDC_VALUE)->GetSafeHwnd(), sz, 127);
+ pt->value = atof(sz);
+
+ pt->flags = 0;
+ for (i=0 ; i<32 ; i++)
+ {
+ b = ::SendMessage(GetDlgItem(g_checkboxes[i])->GetSafeHwnd(), BM_GETCHECK, 0, 0);
+ if (b != 1 && b != 0)
+ continue;
+ pt->flags |= b<<i;
+ }
+
+ pt->contents = 0;
+ for (i=0 ; i<32 ; i++)
+ {
+ b = ::SendMessage(GetDlgItem(g_checkboxes[32+i])->GetSafeHwnd(), BM_GETCHECK, 0, 0);
+ if (b != 1 && b != 0)
+ continue;
+ pt->contents |= b<<i;
+ }
+
+ g_changed_surface = true;
+
+ // a local copy of the texture matrix, given for a qtexture_t with width=2 height=2
+ brushprimit_texdef_t local_bp;
+ brushprimit_texdef_t *bpt;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ face_t *selFace = NULL;
+ if (g_bNewFace && g_ptrSelectedFaces.GetSize() > 0)
+ {
+ selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ bpt = &selFace->brushprimit_texdef;
+ }
+ else
+ {
+ bpt = &g_qeglobals.d_texturewin.brushprimit_texdef;
+ }
+ // compute texture matrix
+ // the matrix returned must be understood as a qtexture_t with width=2 height=2
+ FakeTexCoordsToTexMat( m_shift, m_rotate, m_scale, local_bp.coords );
+ // copy the texture matrix in the global struct
+ // fit the qtexture if we have a face selected, otherwise g_qeglobals.d_texturewin.brushprimit_texdef uses the basic qtexture_t with width=2 height=2
+
+ ConvertTexMatWithQTexture( &local_bp, NULL, bpt, ( ( g_bNewFace && selFace ) ? selFace->d_texture : NULL ) );
+ }
+ Select_SetTexture(pt,&local_bp);
+
+ //if (m_bPatchMode)
+ //{
+ // Patch_SetTextureInfo(pt);
+ //}
+
+}
+
+/*
+=================
+UpdateSpinners
+=================
+*/
+
+void CSurfaceDlg::UpdateSpinners(bool bUp, int nID)
+{
+ texdef_t *pt;
+ texdef_t td;
+
+ if (m_bPatchMode)
+ {
+ td.rotate = 0.0;
+ td.scale[0] = td.scale[1] = 0.0;
+ td.shift[0] = td.shift[1] = 0.0;
+ GrabPatchMods();
+
+ pt = &g_patch_texdef;
+ td.contents = pt->contents;
+ td.flags = pt->flags;
+ td.value = pt->value;
+
+ if (nID == IDC_SPIN_ROTATE)
+ {
+ if (bUp)
+ td.rotate = pt->rotate;
+ else
+ td.rotate = -pt->rotate;
+ }
+ else if (nID == IDC_SPIN_HSCALE)
+ {
+ if (bUp)
+ td.scale[0] = 1-pt->scale[0];
+ else
+ td.scale[0] = 1+pt->scale[0];
+ }
+ else if (nID == IDC_SPIN_VSCALE)
+ {
+ if (bUp)
+ td.scale[1] = 1-pt->scale[1];
+ else
+ td.scale[1] = 1+pt->scale[1];
+ }
+
+ else if (nID == IDC_SPIN_HSHIFT)
+ {
+ if (bUp)
+ td.shift[0] = pt->shift[0];
+ else
+ td.shift[0] = -pt->shift[0];
+ }
+ else if (nID == IDC_SPIN_VSHIFT)
+ {
+ if (bUp)
+ td.shift[1] = pt->shift[1];
+ else
+ td.shift[1] = -pt->shift[1];
+ }
+ pt = &g_qeglobals.d_texturewin.texdef;
+ Patch_SetTextureInfo(&td);
+ }
+ else
+ {
+ // in brush primitive mode, will read up-to-date m_shift m_rotate m_scale
+ GetTexMods ();
+ if (g_bNewFace && g_ptrSelectedFaces.GetSize() > 0)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ pt = &selFace->texdef;
+ }
+ else
+ {
+ pt = &g_qeglobals.d_texturewin.texdef;
+ }
+ if (nID == IDC_SPIN_ROTATE)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (bUp)
+ m_rotate += 45;
+ else
+ m_rotate -= 45;
+ }
+ else
+ {
+ if (bUp)
+ pt->rotate += 45;
+ else
+ pt->rotate -= 45;
+ if (pt->rotate < 0)
+ pt->rotate += 360;
+ if (pt->rotate >= 360)
+ pt->rotate -= 360;
+ }
+ }
+ else if (nID == IDC_SPIN_HSCALE)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (bUp)
+ m_scale[0] += 0.1;
+ else
+ m_scale[0] -= 0.1;
+ }
+ else
+ {
+ if (bUp)
+ pt->scale[0] += 0.1;
+ else
+ pt->scale[0] -= 0.1;
+ }
+ }
+ else if (nID == IDC_SPIN_VSCALE)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (bUp)
+ m_scale[1] += 0.1;
+ else
+ m_scale[1] -= 0.1;
+ }
+ else
+ {
+ if (bUp)
+ pt->scale[1] += 0.1;
+ else
+ pt->scale[1] -= 0.1;
+ }
+ }
+ else if (nID == IDC_SPIN_HSHIFT)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (bUp)
+ m_shift[0] += 8;
+ else
+ m_shift[0] -= 8;
+ }
+ else
+ {
+ if (bUp)
+ pt->shift[0] += 8;
+ else
+ pt->shift[0] -= 8;
+ }
+ }
+ else if (nID == IDC_SPIN_VSHIFT)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ if (bUp)
+ m_shift[1] += 8;
+ else
+ m_shift[1] -= 8;
+ }
+ else
+ {
+ if (bUp)
+ pt->shift[1] += 8;
+ else
+ pt->shift[1] -= 8;
+ }
+ }
+ }
+ // a local copy of the texture matrix, given for a qtexture_t with width=2 height=2
+ brushprimit_texdef_t local_bp;
+ brushprimit_texdef_t *bpt;
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ face_t *selFace = NULL;
+ if (g_bNewFace && g_ptrSelectedFaces.GetSize() > 0)
+ {
+ selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ bpt = &selFace->brushprimit_texdef;
+ }
+ else
+ {
+ bpt = &g_qeglobals.d_texturewin.brushprimit_texdef;
+ }
+ // compute texture matrix
+ // the matrix returned must be understood as a qtexture_t with width=2 height=2
+ FakeTexCoordsToTexMat( m_shift, m_rotate, m_scale, local_bp.coords );
+ // copy the texture matrix in the global struct
+ // fit the qtexture if we have a face selected, otherwise g_qeglobals.d_texturewin.brushprimit_texdef uses the basic qtexture_t with width=2 height=2
+ ConvertTexMatWithQTexture( &local_bp, NULL, bpt, ( ( g_bNewFace && selFace ) ? selFace->d_texture : NULL ) );
+ }
+ // brush primit : will update the widgets after reading back texture matrix and computing fake shift scale rot
+ SetTexMods();
+ g_changed_surface = true;
+ Select_SetTexture(pt,&local_bp);
+}
+
+void CSurfaceDlg::UpdateSpinners(int nScrollCode, int nPos, CScrollBar* pBar)
+{
+ texdef_t *pt;
+
+ GetTexMods ();
+ if (g_bNewFace && g_ptrSelectedFaces.GetSize() > 0)
+ {
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+ pt = &selFace->texdef;
+ }
+ else
+ {
+ pt = &g_qeglobals.d_texturewin.texdef;
+ }
+
+ if ((nScrollCode != SB_LINEUP) && (nScrollCode != SB_LINEDOWN))
+ return;
+
+ if (pBar->GetSafeHwnd() == ::GetDlgItem(GetSafeHwnd(), IDC_ROTATEA))
+ {
+ if (nScrollCode == SB_LINEUP)
+ pt->rotate += 45;
+ else
+ pt->rotate -= 45;
+
+ if (pt->rotate < 0)
+ pt->rotate += 360;
+
+ if (pt->rotate >= 360)
+ pt->rotate -= 360;
+ }
+
+ else if (pBar->GetSafeHwnd() == ::GetDlgItem(GetSafeHwnd(), IDC_HSCALEA))
+ {
+ if (nScrollCode == SB_LINEDOWN)
+ pt->scale[0] -= 0.1;
+ else
+ pt->scale[0] += 0.1;
+ }
+
+ else if (pBar->GetSafeHwnd() == ::GetDlgItem(GetSafeHwnd(), IDC_VSCALEA))
+ {
+ if (nScrollCode == SB_LINEUP)
+ pt->scale[1] += 0.1;
+ else
+ pt->scale[1] -= 0.1;
+ }
+
+ else if (pBar->GetSafeHwnd() == ::GetDlgItem(GetSafeHwnd(), IDC_HSHIFTA))
+ {
+ if (nScrollCode == SB_LINEDOWN)
+ pt->shift[0] -= 8;
+ else
+ pt->shift[0] += 8;
+ }
+
+ else if (pBar->GetSafeHwnd() == ::GetDlgItem(GetSafeHwnd(), IDC_VSHIFTA))
+ {
+ if (nScrollCode == SB_LINEUP)
+ pt->shift[1] += 8;
+ else
+ pt->shift[1] -= 8;
+ }
+
+ SetTexMods();
+ g_changed_surface = true;
+ //++timo if !g_qeglobals.m_bBrushPrimitMode send a NULL brushprimit_texdef
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ Sys_Printf("Warning : non brush primitive mode call to CSurfaceDlg::GetTexMods broken\n");
+ Sys_Printf(" ( Select_SetTexture not called )\n");
+ }
+// Select_SetTexture(pt);
+}
+
+void UpdateSurfaceDialog()
+{
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ g_SurfaceTable.m_pfnUpdateSurfaceDialog();
+ }
+ else
+ {
+ if (g_surfwin)
+ g_dlgSurface.SetTexMods();
+ }
+ g_pParentWnd->UpdateTextureBar();
+}
+
+bool ByeByeSurfaceDialog();
+
+void DoSurface (void)
+{
+ // surface properties plugin ?
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ g_SurfaceTable.m_pfnDoSurface();
+ return;
+ }
+
+ g_bNewFace = g_PrefsDlg.m_bFace;
+ g_bNewApplyHandling = g_PrefsDlg.m_bNewApplyHandling;
+ g_bGatewayhack = g_PrefsDlg.m_bGatewayHack;
+ // save current state for cancel
+ g_old_texdef = g_qeglobals.d_texturewin.texdef;
+ g_changed_surface = false;
+
+ if (g_surfwin == NULL && g_dlgSurface.GetSafeHwnd() == NULL)
+ {
+ g_patch_texdef.scale[0] = 0.05;
+ g_patch_texdef.scale[1] = 0.05;
+ g_patch_texdef.shift[0] = 0.05;
+ g_patch_texdef.shift[1] = 0.05;
+ // use rotation increment from preferences
+ g_patch_texdef.rotate = g_PrefsDlg.m_nRotation;
+
+ g_dlgSurface.Create(IDD_SURFACE);
+ CRect rct;
+ LONG lSize = sizeof(rct);
+ if (LoadRegistryInfo("Radiant::SurfaceWindow", &rct, &lSize))
+ g_dlgSurface.SetWindowPos(NULL, rct.left, rct.top, 0,0, SWP_NOSIZE | SWP_SHOWWINDOW);
+
+ Sys_UpdateWindows(W_ALL);
+ }
+ else
+ {
+ g_surfwin = g_dlgSurface.GetSafeHwnd();
+ g_dlgSurface.SetTexMods ();
+ g_dlgSurface.ShowWindow(SW_SHOW);
+ }
+}
+
+bool ByeByeSurfaceDialog()
+{
+ // surface properties plugin ?
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ return g_SurfaceTable.m_pfnByeByeSurfaceDialog();
+ }
+
+ if (g_surfwin)
+ {
+ if (g_bGatewayhack)
+ PostMessage(g_surfwin, WM_COMMAND, IDAPPLY, 0);
+ else
+ PostMessage(g_surfwin, WM_COMMAND, IDCANCEL, 0);
+ return true;
+ }
+ else return false;
+}
+
+BOOL CSurfaceDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ g_surfwin = GetSafeHwnd();
+ SetTexMods ();
+
+#ifdef QUAKE3
+ GetDlgItem(IDC_CHECK32)->SetWindowText("Curve");
+ GetDlgItem(IDC_CHECK64)->SetWindowText("Inverted");
+#endif
+
+ m_wndHScale.SetRange(0, 1000);
+ m_wndVScale.SetRange(0, 1000);
+ m_wndHShift.SetRange(0, 1000);
+ m_wndVShift.SetRange(0, 1000);
+ m_wndRotate.SetRange(0, 1000);
+ m_wndWidth.SetRange(1, 32);
+ m_wndHeight.SetRange(1, 32);
+
+ LPVOID lpv = g_pParentWnd->GetPlugInMgr().GetSurfaceFlags();
+ if (lpv != NULL)
+ {
+ int i = 0;
+ char* p = reinterpret_cast<char*>(lpv);
+ char* pBuff = new char[strlen(p)+1];
+ strcpy(pBuff, p);
+ char* pToken = strtok(pBuff, ";\0");
+ while (pToken != NULL)
+ {
+ GetDlgItem(g_checkboxes[i++])->SetWindowText(pToken);
+ pToken = strtok(NULL, ";\0");
+ }
+ }
+
+ if (strstr(g_PrefsDlg.m_strWhatGame, "Quake3") != NULL) {
+ for (int i=0 ; i < 64 ; i++) {
+ ::EnableWindow(GetDlgItem(g_checkboxes[i])->GetSafeHwnd(), FALSE);
+ }
+
+ }
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CSurfaceDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
+{
+ CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
+ UpdateSpinners(nSBCode, nPos, pScrollBar);
+ Sys_UpdateWindows(W_CAMERA);
+}
+
+void CSurfaceDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+
+ CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CSurfaceDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
+{
+ CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
+ UpdateSpinners(nSBCode, nPos, pScrollBar);
+ Sys_UpdateWindows(W_CAMERA);
+}
+
+void CSurfaceDlg::OnApply()
+{
+ GetTexMods ();
+ Sys_UpdateWindows(W_CAMERA);
+ if (g_bNewApplyHandling)
+ OnOK();
+}
+
+void CSurfaceDlg::OnOK()
+{
+ GetTexMods();
+ g_surfwin = NULL;
+ CDialog::OnOK();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnClose()
+{
+ g_surfwin = NULL;
+ CDialog::OnClose();
+}
+
+void CSurfaceDlg::OnCancel()
+{
+ if (g_bGatewayhack)
+ OnOK();
+ else
+ OnBtnCancel();
+}
+
+void CSurfaceDlg::OnDestroy()
+{
+ if (GetSafeHwnd())
+ {
+ CRect rct;
+ GetWindowRect(rct);
+ SaveRegistryInfo("Radiant::SurfaceWindow", &rct, sizeof(rct));
+ }
+ CDialog::OnDestroy();
+ g_surfwin = NULL;
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnBtnCancel()
+{
+ g_qeglobals.d_texturewin.texdef = g_old_texdef;
+ if (g_changed_surface)
+ {
+ //++timo if !g_qeglobals.m_bBrushPrimitMode send a NULL brushprimit_texdef
+ if (!g_qeglobals.m_bBrushPrimitMode)
+ {
+ Sys_Printf("Warning : non brush primitive mode call to CSurfaceDlg::GetTexMods broken\n");
+ Sys_Printf(" ( Select_SetTexture not called )\n");
+ }
+// Select_SetTexture(&g_qeglobals.d_texturewin.texdef);
+ }
+ g_surfwin = NULL;
+ DestroyWindow();
+}
+
+void CSurfaceDlg::OnBtnColor()
+{
+}
+
+HBRUSH CSurfaceDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
+{
+ HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
+ return hbr;
+}
+
+int CSurfaceDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CDialog::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ return 0;
+}
+
+BOOL CSurfaceDlg::PreCreateWindow(CREATESTRUCT& cs)
+{
+ // TODO: Add your specialized code here and/or call the base class
+
+ return CDialog::PreCreateWindow(cs);
+}
+
+
+void CSurfaceDlg::OnDeltaPosSpin(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ UpdateSpinners((pNMUpDown->iDelta > 0), pNMUpDown->hdr.idFrom);
+ *pResult = 0;
+}
+
+void CSurfaceDlg::OnBtnPatchdetails()
+{
+ Patch_NaturalizeSelected(true);
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnBtnPatchnatural()
+{
+ Patch_NaturalizeSelected();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnBtnPatchreset()
+{
+ CTextureLayout dlg;
+ if (dlg.DoModal() == IDOK)
+ {
+ Patch_ResetTexturing(dlg.m_fX, dlg.m_fY);
+ }
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnBtnPatchfit()
+{
+ Patch_FitTexturing();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnBtnAxial()
+{
+ Select_SetTexture (&g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, true);
+ g_changed_surface = true;
+ SetTexMods();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CSurfaceDlg::OnBtnBrushfit()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CSurfaceDlg::OnBtnFacefit()
+{
+ UpdateData(TRUE);
+ if (g_ptrSelectedFaces.GetSize() == 0)
+ {
+ brush_t *b;
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)
+ {
+ g_ptrSelectedFaces.Add(pFace);
+ g_ptrSelectedFaceBrushes.Add(b);
+ }
+ }
+ }
+ Select_FitTexture(m_nHeight, m_nWidth);
+ SetTexMods();
+ g_changed_surface = true;
+ Sys_UpdateWindows(W_ALL);
+}
diff --git a/q3radiant/SurfaceDlg.h b/q3radiant/SurfaceDlg.h
new file mode 100755
index 0000000..8b7c0fd
--- /dev/null
+++ b/q3radiant/SurfaceDlg.h
@@ -0,0 +1,107 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_SURFACEDLG_H__D84E0C22_9EEA_11D1_B570_00AA00A410FC__INCLUDED_)
+#define AFX_SURFACEDLG_H__D84E0C22_9EEA_11D1_B570_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// SurfaceDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CSurfaceDlg dialog
+
+class CSurfaceDlg : public CDialog
+{
+ bool m_bPatchMode;
+ // brush primitive fake shift scale rot coords
+ float m_shift[2];
+ float m_rotate;
+ float m_scale[2];
+
+ // Construction
+public:
+ CSurfaceDlg(CWnd* pParent = NULL); // standard constructor
+ void SetTexMods();
+ void GetTexMods();
+ void GrabPatchMods();
+
+// Dialog Data
+ //{{AFX_DATA(CSurfaceDlg)
+ enum { IDD = IDD_SURFACE };
+ CSpinButtonCtrl m_wndWidth;
+ CSpinButtonCtrl m_wndHeight;
+ CSpinButtonCtrl m_wndVShift;
+ CSpinButtonCtrl m_wndVScale;
+ CSpinButtonCtrl m_wndRotate;
+ CSpinButtonCtrl m_wndHShift;
+ CSpinButtonCtrl m_wndHScale;
+ int m_nHeight;
+ int m_nWidth;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CSurfaceDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ void UpdateSpinners(int nScrollCode, int nPos, CScrollBar* pBar);
+ void UpdateSpinners(bool bUp, int nID);
+ // Generated message map functions
+ //{{AFX_MSG(CSurfaceDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+ afx_msg void OnApply();
+ virtual void OnOK();
+ afx_msg void OnClose();
+ virtual void OnCancel();
+ afx_msg void OnDestroy();
+ afx_msg void OnBtnCancel();
+ afx_msg void OnBtnColor();
+ afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnDeltaPosSpin(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnBtnPatchdetails();
+ afx_msg void OnBtnPatchnatural();
+ afx_msg void OnBtnPatchreset();
+ afx_msg void OnBtnPatchfit();
+ afx_msg void OnBtnAxial();
+ afx_msg void OnBtnBrushfit();
+ afx_msg void OnBtnFacefit();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_SURFACEDLG_H__D84E0C22_9EEA_11D1_B570_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/SurfacePlugin.cpp b/q3radiant/SurfacePlugin.cpp
new file mode 100755
index 0000000..ad1cd31
--- /dev/null
+++ b/q3radiant/SurfacePlugin.cpp
@@ -0,0 +1,82 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:18:14 $
+// $Log: SurfacePlugin.cpp,v $
+// Revision 1.1.1.4 2000/01/18 00:18:14 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:43 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:12 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:46 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:42 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:46 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:46 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1 1999/12/02 16:11:05 Timo & Christine
+// commit before e-brain dump
+// TexTool v1.1 support
+//
+//
+//
+// DESCRIPTION:
+// implementation of isurfaceplugin-interface specifics
+//++timo FIXME: all the patch related stuff needs moving to qerplugin.h
+
+#include "stdafx.h"
+
+void WINAPI QERApp_GetTwoSelectedPatch( patchMesh_t **p1, patchMesh_t **p2 )
+{
+ *p1 = NULL; *p2 = NULL;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = pb->next)
+ {
+ if (pb->patchBrush)
+ {
+ if (!(*p1))
+ *p1 = pb->pPatch;
+ else if (!(*p2))
+ {
+ *p2 = pb->pPatch;
+ return;
+ }
+ }
+ }
+#ifdef _DEBUG
+ Sys_Printf("WARNING: QERApp_GetTwoSelectedPatch failed (did not find two patches)\n");
+#endif
+ return;
+
+}
diff --git a/q3radiant/TexEdit.cpp b/q3radiant/TexEdit.cpp
new file mode 100755
index 0000000..3726629
--- /dev/null
+++ b/q3radiant/TexEdit.cpp
@@ -0,0 +1,85 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// TexEdit.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "TexEdit.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTexEdit
+
+CTexEdit::CTexEdit()
+{
+ m_pTexWnd = NULL;
+}
+
+CTexEdit::~CTexEdit()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CTexEdit, CEdit)
+ //{{AFX_MSG_MAP(CTexEdit)
+ ON_WM_CTLCOLOR_REFLECT()
+ ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
+ ON_WM_CREATE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTexEdit message handlers
+
+HBRUSH CTexEdit::CtlColor(CDC* pDC, UINT nCtlColor)
+{
+ if (nCtlColor == CTLCOLOR_EDIT)
+ {
+ pDC->SetBkColor(RGB(192,192,192));
+ return (HBRUSH)GetStockObject(LTGRAY_BRUSH);
+ }
+ return NULL;
+}
+
+void CTexEdit::OnChange()
+{
+ CString str;
+ GetWindowText(str);
+ if (m_pTexWnd)
+ m_pTexWnd->UpdateFilter(str);
+}
+
+int CTexEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CEdit::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ m_Font.CreatePointFont(100, "Arial");
+ SetFont(&m_Font, FALSE);
+ return 0;
+}
diff --git a/q3radiant/TexEdit.h b/q3radiant/TexEdit.h
new file mode 100755
index 0000000..36a9710
--- /dev/null
+++ b/q3radiant/TexEdit.h
@@ -0,0 +1,76 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_TEXEDIT_H__913F6812_99CD_11D1_B568_00AA00A410FC__INCLUDED_)
+#define AFX_TEXEDIT_H__913F6812_99CD_11D1_B568_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// TexEdit.h : header file
+//
+/////////////////////////////////////////////////////////////////////////////
+// CTexEdit window
+
+class CTexWnd;
+
+class CTexEdit : public CEdit
+{
+// Construction
+public:
+ CTexEdit();
+
+// Attributes
+public:
+
+protected:
+ CTexWnd* m_pTexWnd;
+ CFont m_Font;
+// Operations
+public:
+ void SetTexWnd(CTexWnd* pTex) {m_pTexWnd = pTex;};
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTexEdit)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CTexEdit();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CTexEdit)
+ afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
+ afx_msg void OnChange();
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ //}}AFX_MSG
+
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TEXEDIT_H__913F6812_99CD_11D1_B568_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/TexWnd.cpp b/q3radiant/TexWnd.cpp
new file mode 100755
index 0000000..471ba0e
--- /dev/null
+++ b/q3radiant/TexWnd.cpp
@@ -0,0 +1,3186 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// TexWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include <assert.h>
+#include "Radiant.h"
+#include "TexWnd.h"
+#include "qe3.h"
+#include "io.h"
+#include "PrefsDlg.h"
+#include "shaderinfo.h"
+#include "pakstuff.h"
+#include "str.h"
+#include "PrefsDlg.h"
+
+Str m_gStr;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+qtexture_t *Texture_ForNamePath(char* name, char* pFullPath);
+#define TYP_MIPTEX 68
+static unsigned tex_palette[256];
+
+qtexture_t *notexture = NULL;
+qtexture_t *g_pluginTexture = NULL;
+
+static qboolean nomips = false;
+
+#define FONT_HEIGHT 10
+
+HGLRC s_hglrcTexture = NULL;
+HDC s_hdcTexture = NULL;
+
+//int texture_mode = GL_NEAREST;
+//int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+//int texture_mode = GL_LINEAR;
+//int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+// this is the global counter for GL bind numbers
+int texture_extension_number = 1;
+int g_nCurrentTextureMenuName;
+
+int g_nTextureOffset = 0;
+
+// current active texture directory. if empty, show textures in use
+char texture_directory[128]; // use if texture_showinuse is false
+qboolean texture_showinuse;
+
+bool g_bFilterEnabled = false;
+CString g_strFilter;
+
+// texture layout functions
+qtexture_t *current_texture = NULL;
+int current_x, current_y, current_row;
+
+int texture_nummenus;
+#define MAX_TEXTUREDIRS 128
+char texture_menunames[MAX_TEXTUREDIRS][128];
+
+qboolean g_dontuse = true; // set to true to load the texture but not flag as used
+
+// void SelectTexture (int mx, int my, bool bShift = false);
+void SelectTexture (int mx, int my, bool bShift, bool bFitScale=false);
+
+void Texture_MouseDown (int x, int y, int buttons);
+void Texture_MouseUp (int x, int y, int buttons);
+void Texture_MouseMoved (int x, int y, int buttons);
+
+CPtrArray g_lstShaders;
+CPtrArray g_lstSkinCache;
+
+struct SkinInfo
+{
+ CString m_strName;
+ int m_nTextureBind;
+ SkinInfo(const char *pName, int n)
+ {
+ m_strName = pName;
+ m_nTextureBind = n;
+ };
+ SkinInfo(){};
+};
+
+// checks wether a qtexture_t exists for a given name
+//++timo FIXME: is this really any use? redundant.
+bool ShaderQTextureExists(const char *pName)
+{
+ for (qtexture_t *q=g_qeglobals.d_qtextures ; q ; q=q->next)
+ {
+ if (!strcmp(q->name, pName))
+ {
+ return true;
+ }
+ }
+ return false;
+
+}
+
+CShaderInfo* hasShader(const char *pName)
+{
+ int nSize = g_lstShaders.GetSize();
+ for (int i = 0; i < nSize; i++)
+ {
+ CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
+ if (pInfo != NULL)
+ {
+ if (pInfo->m_strName.CompareNoCase(pName) == 0)
+ {
+ return pInfo;
+ }
+ }
+ }
+ return NULL;
+}
+
+// gets active texture extension
+//
+// FIXME: fix this to be generic from project file
+//
+int GetTextureExtensionCount()
+{
+ return 2;
+}
+
+const char* GetTextureExtension(int nIndex)
+{
+ if ( nIndex == 0)
+ {
+ _QERTextureInfo *pInfo = g_pParentWnd->GetPlugInMgr().GetTextureInfo();
+ const char *pTex = (pInfo != NULL) ? pInfo->m_TextureExtension : NULL;
+ return (pTex == NULL) ? (g_PrefsDlg.m_bHiColorTextures == FALSE) ? "wal" : "tga" : pTex;
+ }
+ // return jpg for 2nd extension
+ return "jpg";
+}
+
+void SortTextures(void)
+{
+ qtexture_t *q, *qtemp, *qhead, *qcur, *qprev;
+
+ // standard insertion sort
+ // Take the first texture from the list and
+ // add it to our new list
+ if ( g_qeglobals.d_qtextures == NULL)
+ return;
+
+ qhead = g_qeglobals.d_qtextures;
+ q = g_qeglobals.d_qtextures->next;
+ qhead->next = NULL;
+
+ // while there are still things on the old
+ // list, keep adding them to the new list
+ while (q)
+ {
+ qtemp = q;
+ q = q->next;
+
+ qprev = NULL;
+ qcur = qhead;
+
+ while (qcur)
+ {
+ // Insert it here?
+ if (strcmp(qtemp->name, qcur->name) < 0)
+ {
+ qtemp->next = qcur;
+ if (qprev)
+ qprev->next = qtemp;
+ else
+ qhead = qtemp;
+ break;
+ }
+
+ // Move on
+
+ qprev = qcur;
+ qcur = qcur->next;
+
+
+ // is this one at the end?
+
+ if (qcur == NULL)
+ {
+ qprev->next = qtemp;
+ qtemp->next = NULL;
+ }
+ }
+
+
+ }
+
+ g_qeglobals.d_qtextures = qhead;
+}
+
+/*
+==============
+Texture_InitPalette
+==============
+*/
+void Texture_InitPalette (byte *pal)
+{
+ int r,g,b,v;
+ int i;
+ int inf;
+ byte gammatable[256];
+ float gamma;
+
+ gamma = g_qeglobals.d_savedinfo.fGamma;
+
+ if (gamma == 1.0)
+ {
+ for (i=0 ; i<256 ; i++)
+ gammatable[i] = i;
+ }
+ else
+ {
+ for (i=0 ; i<256 ; i++)
+ {
+ inf = 255 * pow ( (float)( (i+0.5)/255.5 ), gamma ) + 0.5;
+ if (inf < 0)
+ inf = 0;
+ if (inf > 255)
+ inf = 255;
+ gammatable[i] = inf;
+ }
+ }
+
+ for (i=0 ; i<256 ; i++)
+ {
+ r = gammatable[pal[0]];
+ g = gammatable[pal[1]];
+ b = gammatable[pal[2]];
+ pal += 3;
+
+ v = (r<<24) + (g<<16) + (b<<8) + 255;
+ v = BigLong (v);
+
+ tex_palette[i] = v;
+ }
+}
+
+void SetTexParameters (void)
+{
+ qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
+
+ switch ( texture_mode )
+ {
+ case GL_NEAREST:
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+ break;
+ case GL_LINEAR:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ break;
+ }
+}
+
+/*
+============
+Texture_SetMode
+============
+*/
+void Texture_SetMode(int iMenu)
+{
+ int i, iMode;
+ HMENU hMenu;
+ qboolean texturing = true;
+
+ hMenu = GetMenu(g_qeglobals.d_hwndMain);
+
+ switch(iMenu) {
+ case ID_VIEW_NEAREST:
+ iMode = GL_NEAREST;
+ break;
+ case ID_VIEW_NEARESTMIPMAP:
+ iMode = GL_NEAREST_MIPMAP_NEAREST;
+ break;
+ case ID_VIEW_LINEAR:
+ iMode = GL_NEAREST_MIPMAP_LINEAR;
+ break;
+ case ID_VIEW_BILINEAR:
+ iMode = GL_LINEAR;
+ break;
+ case ID_VIEW_BILINEARMIPMAP:
+ iMode = GL_LINEAR_MIPMAP_NEAREST;
+ break;
+ case ID_VIEW_TRILINEAR:
+ iMode = GL_LINEAR_MIPMAP_LINEAR;
+ break;
+
+ case ID_TEXTURES_WIREFRAME:
+ iMode = 0;
+ texturing = false;
+ break;
+
+ case ID_TEXTURES_FLATSHADE:
+ iMode = 0;
+ texturing = false;
+ break;
+
+ }
+
+ CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED);
+ CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED);
+
+ CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED);
+
+ g_qeglobals.d_savedinfo.iTexMenu = iMenu;
+ texture_mode = iMode;
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if (s_hdcTexture && s_hglrcTexture)
+ {
+ //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
+ Error ("wglMakeCurrent in LoadTexture failed");
+ }
+ else
+ return;
+ }
+
+ if ( texturing )
+ SetTexParameters ();
+
+ if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
+ {
+ g_pParentWnd->GetCamera()->Camera().draw_mode = cd_wire;
+ Map_BuildBrushData();
+ Sys_UpdateWindows (W_ALL);
+ return;
+
+ } else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) {
+
+ g_pParentWnd->GetCamera()->Camera().draw_mode = cd_solid;
+ Map_BuildBrushData();
+ Sys_UpdateWindows (W_ALL);
+ return;
+ }
+
+ for (i=1 ; i<texture_extension_number ; i++)
+ {
+ qglBindTexture( GL_TEXTURE_2D, i );
+ SetTexParameters ();
+ }
+
+ // select the default texture
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+
+ qglFinish();
+
+ if (g_pParentWnd->GetCamera()->Camera().draw_mode != cd_texture)
+ {
+ g_pParentWnd->GetCamera()->Camera().draw_mode = cd_texture;
+ Map_BuildBrushData();
+ }
+
+ Sys_UpdateWindows (W_ALL);
+}
+
+/*
+================
+R_MipMap
+
+Operates in place, quartering the size of the texture
+================
+*/
+void R_MipMap (byte *in, int &width, int &height)
+{
+ int i, j;
+ byte *out;
+ int row;
+
+ row = width * 4;
+ width >>= 1;
+ height >>= 1;
+ out = in;
+ for (i=0 ; i<height ; i++, in+=row)
+ {
+ for (j=0 ; j<width ; j++, out+=4, in+=8)
+ {
+ out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
+ out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
+ out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
+ out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
+ }
+ }
+}
+
+/*
+=================
+Texture_LoadTexture
+=================
+*/
+//++timo NOTE: miptex_t is used only for .WAL format .. a bit outdated
+qtexture_t *Texture_LoadTexture (miptex_t *qtex)
+{
+ byte *source;
+ unsigned char *dest;
+ int width, height, i, count;
+ int total[3];
+ qtexture_t *q;
+
+ width = LittleLong(qtex->width);
+ height = LittleLong(qtex->height);
+
+ q = (qtexture_t*)qmalloc(sizeof(*q));
+
+ q->width = width;
+ q->height = height;
+
+ q->flags = qtex->flags;
+ q->value = qtex->value;
+ q->contents = qtex->contents;
+
+ dest = (unsigned char*)qmalloc (width*height*4);
+
+ count = width*height;
+ source = (byte *)qtex + LittleLong(qtex->offsets[0]);
+
+ // The dib is upside down so we want to copy it into
+ // the buffer bottom up.
+
+ total[0] = total[1] = total[2] = 0;
+ for (i=0 ; i<count ; i++)
+ {
+ dest[i] = tex_palette[source[i]];
+
+ total[0] += ((byte *)(dest+i))[0];
+ total[1] += ((byte *)(dest+i))[1];
+ total[2] += ((byte *)(dest+i))[2];
+ }
+
+ q->color[0] = (float)total[0]/(count*255);
+ q->color[1] = (float)total[1]/(count*255);
+ q->color[2] = (float)total[2]/(count*255);
+
+ q->texture_number = texture_extension_number++;
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ // Timo
+ // Surface properties plugins can store their own data in an IPluginQTexture
+ q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
+ GETPLUGINTEXDEF(q)->InitForMiptex( qtex );
+ }
+
+ //++timo is the m_bSGIOpenGL parameter still taken into account?
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
+ Error ("wglMakeCurrent in LoadTexture failed");
+ }
+
+ qglBindTexture( GL_TEXTURE_2D, q->texture_number );
+
+ //Handle3DfxTexturing(q, width, height, dest);
+
+ SetTexParameters ();
+
+ int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
+ while (nCount-- > 0)
+ {
+ if (width > 16 && height > 16)
+ {
+ R_MipMap(dest, width, height);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if (nomips)
+ {
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
+ }
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
+ }
+ else
+ {
+ if (nomips)
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
+ }
+
+ free (dest);
+
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+
+ return q;
+}
+
+
+
+
+/*
+=================
+Texture_LoadTexture
+=================
+*/
+qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char* pPath, int nFlags, int nContents, int nValue )
+{
+ int i, j, inf;
+ byte gammatable[256];
+ float fGamma = g_qeglobals.d_savedinfo.fGamma;
+
+
+ qtexture_t* q = (qtexture_t*)qmalloc(sizeof(*q));
+ q->width = nWidth;
+ q->height = nHeight;
+ q->flags = nFlags;
+ q->value = nValue;
+ q->contents = nContents;
+
+ int nCount = nWidth * nHeight;
+ float total[3];
+ total[0] = total[1] = total[2] = 0.0f;
+
+ //++timo FIXME: move gamma table initialization somewhere else!
+ if (fGamma == 1.0)
+ {
+ for (i=0 ; i<256 ; i++)
+ gammatable[i] = i;
+ }
+ else
+ {
+ for (i=0 ; i<256 ; i++)
+ {
+ inf = 255 * pow ( (float)( (i+0.5)/255.5 ), fGamma ) + 0.5;
+ if (inf < 0)
+ inf = 0;
+ if (inf > 255)
+ inf = 255;
+ gammatable[i] = inf;
+ }
+ }
+
+
+ // all targas are stored internally as 32bit so rgba = 4 bytes
+ for (i = 0 ; i < (nCount * 4) ; i += 4)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ total[j] += (pPixels+i)[j];
+ byte b = (pPixels+i)[j];
+ (pPixels+i)[j] = gammatable[b];
+
+ }
+ }
+
+ q->color[0] = total[0] / (nCount * 255);
+ q->color[1] = total[1] / (nCount * 255);
+ q->color[2] = total[2] / (nCount * 255);
+
+
+ q->texture_number = texture_extension_number++;
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ // Timo
+ // Surface properties plugins can store their own data in an IPluginQTexture
+ q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
+ GETPLUGINTEXDEF(q)->SetDefaultTexdef();
+ }
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
+ Error ("wglMakeCurrent in LoadTexture failed");
+ }
+
+ qglBindTexture( GL_TEXTURE_2D, q->texture_number );
+
+ //Handle3DfxTexturing(q, width, height, dest);
+
+ SetTexParameters();
+
+ nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
+ while (nCount-- > 0)
+ {
+ if (nWidth > 16 && nHeight > 16)
+ {
+ R_MipMap(pPixels, nWidth, nHeight);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if (nomips)
+ {
+ qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
+ }
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
+ }
+ else
+ {
+ if (nomips)
+ qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
+ }
+
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+
+ return q;
+}
+
+
+qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char *pPath)
+{
+ CString strName;
+ CString strPath;
+ ExtractPath_and_Filename(pPath, strPath, strName);
+ AddSlash(strPath);
+ strPath += "textureinfo.ini";
+ strName.MakeLower();
+ StripExtension (strName.GetBuffer(0));
+ strName.ReleaseBuffer();
+
+ int nFlags = GetPrivateProfileInt(strName, "Flags", 0, strPath);
+ int nValue = GetPrivateProfileInt(strName, "Value", 0, strPath);
+ int nContents = GetPrivateProfileInt(strName, "Contents", 0, strPath);
+ return Texture_LoadTGATexture(pPixels, nWidth, nHeight, pPath, nFlags, nValue, nContents);
+}
+
+
+void Texture_LoadFromPlugIn(LPVOID vp)
+{
+ g_pluginTexture = notexture;
+ _QERTextureLoad *pLoad = reinterpret_cast<_QERTextureLoad*>(vp);
+ if (pLoad != NULL)
+ {
+ qtexture_t *q;
+ q = Texture_LoadTGATexture(pLoad->m_pRGBA, pLoad->m_nWidth, pLoad->m_nHeight, NULL, pLoad->m_nFlags, pLoad->m_nContents, pLoad->m_nValue);
+ if (q != NULL)
+ {
+ // to save duplicate code (since one always ends up getting forgotten and out of sync) this is now done later by caller
+// strcpy (q->name, pLoad->m_pName);
+// StripExtension (q->name);
+// if (!g_dontuse)
+// q->inuse = true;
+// q->next = g_qeglobals.d_qtextures;
+// g_qeglobals.d_qtextures = q;
+ g_pluginTexture = q;
+ }
+ }
+}
+
+
+/*
+===============
+Texture_CreateSolid
+
+Create a single pixel texture of the apropriate color
+===============
+*/
+qtexture_t *Texture_CreateSolid (const char *name)
+{
+ byte data[4];
+ qtexture_t *q;
+
+ q = (qtexture_t*)qmalloc(sizeof(*q));
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ // Timo
+ // Surface properties plugins can store their own data in an IPluginQTexture
+ q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
+ GETPLUGINTEXDEF(q)->SetDefaultTexdef();
+ }
+
+ sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]);
+
+ data[0] = q->color[0]*255;
+ data[1] = q->color[1]*255;
+ data[2] = q->color[2]*255;
+ data[3] = 255;
+
+ q->width = q->height = 1;
+ //q->width = q->height = 2;
+ q->texture_number = texture_extension_number++;
+ qglBindTexture( GL_TEXTURE_2D, q->texture_number );
+ SetTexParameters ();
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ }
+ else
+ {
+ if (nomips)
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data);
+ }
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+
+ return q;
+}
+
+
+/*
+=================
+Texture_MakeDefault
+=================
+*/
+qtexture_t* Texture_MakeDefault (void)
+{
+ qtexture_t *q;
+ byte data[4][4];
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if (s_hdcTexture && s_hglrcTexture)
+ {
+ //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
+ Error ("wglMakeCurrent in LoadTexture failed");
+ }
+ else
+ return NULL;
+ }
+
+ q = (qtexture_t*)qmalloc(sizeof(*q));
+
+ strcpy (q->name, "notexture");
+ q->width = q->height = 64;
+
+ memset (data, 0, sizeof(data));
+ data[0][2] = data[3][2] = 255;
+
+ q->color[0] = 0;
+ q->color[1] = 0;
+ q->color[2] = 0.5;
+
+ q->texture_number = texture_extension_number++;
+ qglBindTexture( GL_TEXTURE_2D, q->texture_number );
+ SetTexParameters ();
+
+ if (nomips)
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ else
+ VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
+
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+ return q;
+}
+
+
+/*
+=================
+Texture_MakeNotexture
+=================
+*/
+void Texture_MakeNotexture (void)
+{
+ notexture = Texture_MakeDefault();
+ // Timo
+ // Surface properties plugins can store their own data in an IPluginQTexture
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ notexture->pData = g_SurfaceTable.m_pfnQTextureAlloc( notexture );
+ GETPLUGINTEXDEF(notexture)->SetDefaultTexdef();
+ }
+}
+
+
+void DemandLoadShaderTexture(qtexture_t *q, CShaderInfo *pShader)
+{
+ char cWork[1024];
+ char cWork2[1024];
+ strcpy(cWork, (pShader->m_strTextureName.GetLength() > 0) ? pShader->m_strTextureName : pShader->m_strName);
+ StripExtension(cWork);
+ // TTimo: if the shader has a m_fTransValue != 1.0f, ignore the alpha channel when loading the texture
+ // in some cases (common/weapclip) the 32bit .tga has an empty alpha channel,
+ // causing a display bug in the camera view (brush does not seemed drawn since alpha==0 for the texture)
+ // NOTE: the workaround is not perfect, the same texture may have been loaded earlier with it's alpha channel
+ q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, false);
+
+ if (q == NULL || q == notexture) {
+ sprintf(cWork2, "%s/%s",ValueForKey(g_qeglobals.d_project_entity, "basepath"), cWork);
+ q = Texture_ForNamePath( cWork, cWork2);
+
+ if (q == NULL || q == notexture) {
+ q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, true);
+ }
+ }
+
+ if (q != NULL && q != notexture)
+ {
+ pShader->m_pQTexture = q;
+ strcpy(q->shadername, pShader->m_strShaderName);
+ q->bFromShader = true;
+ q->fTrans = pShader->m_fTransValue;
+ q->nShaderFlags = pShader->m_nFlags;
+ strcpy(q->name, pShader->m_strName );
+ }
+ else
+ {
+ Sys_Printf("Could not load shader editor image %s\n", cWork);
+ }
+}
+
+
+void LoadShader(char* pFilename, qtexture_t *q)
+{
+ char* pBuff = NULL;
+ CString strTexture;
+ int nSize = LoadFile(pFilename, reinterpret_cast<void**>(&pBuff));
+ if (nSize == -1)
+ {
+ nSize = PakLoadAnyFile(pFilename, reinterpret_cast<void**>(&pBuff));
+ }
+ if (nSize > 0)
+ {
+ StartTokenParsing(pBuff);
+ while (GetToken(true))
+ {
+ // first token should be the path + name.. (from base)
+ CShaderInfo *pShader = new CShaderInfo();
+ pShader->setName(token);
+ pShader->m_strShaderName = pFilename;
+ strTexture = token;
+ bool bGood = true;
+ float fTrans = 1.0;
+ GetToken(true);
+ if (strcmp(token, "{"))
+ {
+ bGood = false;
+ break;
+ }
+ else
+ {
+ // we need to read until we hit a balanced }
+ int nMatch = 1;
+ while (nMatch > 0 && GetToken(true))
+ {
+ if (strcmp(token, "{") == 0)
+ {
+ nMatch++;
+ }
+ else if (strcmp(token, "}") == 0)
+ {
+ nMatch--;
+ }
+ else if (strcmpi(token, "qer_nocarve") == 0)
+ {
+ pShader->m_nFlags |= QER_NOCARVE;
+ }
+ else if (strcmpi(token, "qer_trans") == 0)
+ {
+ if (GetToken(true))
+ {
+ fTrans = atof(token);
+ }
+ pShader->m_nFlags |= QER_TRANS;
+ }
+ else if (strcmpi(token, "qer_editorimage") == 0)
+ {
+ if (GetToken(true))
+ {
+ char* pTex = copystring(token);
+ QE_ConvertDOSToUnixName( pTex, pTex );
+ CString str = pTex;
+ free (pTex);
+ FindReplace(str, "textures/", "");
+ FindReplace(str, ".tga", "");
+ int nPos = str.Find('/');
+ if (nPos == -1)
+ {
+ nPos = str.Find('\\');
+ }
+ if (nPos >= 0)
+ {
+ pShader->m_strTextureName = str;
+ pShader->m_strTextureName.MakeLower(); //avoid problems with case
+/*
+ else
+ {
+ CString strPath = str.Left(nPos+1);
+ DeferredShaderLoad *deferred = new DeferredShaderLoad(str, pShader->m_strName, strPath);
+ g_lstDeferred.Add(deferred);
+ }
+*/
+ }
+ }
+ }
+ else if (strcmpi(token, "surfaceparm") == 0)
+ {
+ //--while (GetToken(false))
+ //--{
+ //--
+ //--}
+ if (GetToken(true))
+ {
+ // next token should be a surface parm
+ //--if (strcmpi(token, "trans") == 0)
+ //--{
+ //-- fTrans = 0.33;
+ //--}
+ if (strcmpi(token, "fog") == 0)
+ {
+ if (fTrans == 1.0) // has not been explicitly set by qer_trans
+ {
+ fTrans = 0.35;
+ }
+ }
+ }
+ }
+ }
+ if (nMatch != 0)
+ {
+ bGood = false;
+ break;
+ }
+ }
+ //--if (bGood && q)
+ if (bGood)
+ {
+ pShader->m_fTransValue = fTrans;
+ g_lstShaders.Add(pShader);
+
+ int n = g_PrefsDlg.m_nShader;
+ if (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_ALL || (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_COMMON && strstr(pShader->m_strName, "common" )))
+ {
+// new
+ if (pShader->m_strTextureName.GetLength() > 0)
+ {
+ if (!ShaderQTextureExists(pShader->m_strName))
+ {
+ DemandLoadShaderTexture(q, pShader);
+ }
+ }
+ }
+// end new
+ //--q->bFromShader = true;
+ //--q->fTrans = fTrans;
+
+ //--// good texture here
+ //--//Sys_Printf("Test load texture %s\n", strTexture);
+ //--// FIXME.. this is a load of crap
+ //--strcpy(dirstring, strTexture);
+ //--QE_ConvertDOSToUnixName(dirstring, dirstring);
+ //--strTexture = dirstring;
+ //--FindReplace(strTexture, "textures/", "");
+ //--qtexture_t *q = Texture_ForName (strTexture.GetBuffer(0));
+ //--if (q != NULL)
+ //--{
+ //-- q->bFromShader = true;
+ //-- q->fTrans = fTrans;
+ //--}
+ }
+ else
+ {
+ Sys_Printf("Error parsing shader at texture %s\n", strTexture);
+ }
+
+ }
+ free (pBuff);
+ }
+ else
+ {
+ Sys_Printf("Unabled to read shader %s\n", pFilename);
+ }
+}
+
+
+extern bool DoesFileExist(const char* pBuff, long& lSize);
+CShaderInfo* SetNameShaderInfo(qtexture_t* q, const char* pPath, const char* pName)
+{
+ CShaderInfo *pInfo = hasShader(pName);
+ if (pInfo)
+ {
+ strcpy(q->shadername, pInfo->m_strShaderName);
+ q->bFromShader = true;
+ q->fTrans = pInfo->m_fTransValue;
+ q->nShaderFlags = pInfo->m_nFlags;
+ }
+ else
+ {
+ q->shadername[0] = 0;
+ }
+ strncpy (q->name, pName, sizeof(q->name) - 1);
+ StripExtension (q->name);
+ return pInfo;
+}
+
+void ReplaceQTexture(qtexture_t *pOld, qtexture_t *pNew, brush_t *pList)
+{
+ for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next)
+ {
+ if (pBrush->patchBrush)
+ {
+ Patch_ReplaceQTexture(pBrush, pOld, pNew);
+ }
+ if (pBrush->terrainBrush)
+ {
+ Terrain_ReplaceQTexture(pBrush->pTerrain, pOld, pNew);
+ }
+
+ for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next)
+ {
+ if (pFace->d_texture == pOld)
+ {
+ pFace->d_texture = pNew;
+ }
+ }
+
+ //Brush_Build(pBrush);
+ }
+}
+
+
+void Texture_Remove(qtexture_t *q)
+{
+ qtexture_t* pTex = g_qeglobals.d_qtextures->next;
+ if (q == g_qeglobals.d_qtextures) // it is the head
+ {
+ g_qeglobals.d_qtextures->next = q->next->next;
+ g_qeglobals.d_qtextures = q->next;
+ }
+ else
+ {
+ qtexture_t* pLast = g_qeglobals.d_qtextures;
+ while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
+ {
+ if (pTex == q)
+ {
+ pLast->next = q->next;
+ break;
+ }
+ pLast = pTex;
+ pTex = pTex->next;
+ }
+ }
+ qglDeleteTextures(1, reinterpret_cast<const unsigned int*>(&q->texture_number));
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ // Timo
+ // Surface properties plugin
+#ifdef _DEBUG
+ if ( !q->pData )
+ Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
+#endif
+ if ( q->pData )
+ GETPLUGINTEXDEF(q)->DecRef();
+ }
+
+ free(q);
+
+}
+
+/*
+=================
+Texture_MakeNoShadertexture
+
+Make a default black/red check pattern texture
+=================
+*/
+qtexture_t * Texture_MakeNoshadertexture( const char *name )
+{
+ qtexture_t *q;
+ byte data[4][4];
+
+ notexture = q = (qtexture_t*)qmalloc(sizeof(*q));
+ q->width = q->height = 64;
+ q->fTrans = 1;
+
+ q = (qtexture_t*)qmalloc(sizeof(*q));
+ strcpy (q->name, name);
+
+ q->width = q->height = 64;
+ q->fTrans = 1;
+
+ memset (data, 0, sizeof(data));
+ data[0][0] = data[3][0] = 255;
+
+ q->color[0] = 0;
+ q->color[1] = 0;
+ q->color[2] = 0.5;
+
+ q->texture_number = texture_extension_number++;
+ qglBindTexture( GL_TEXTURE_2D, q->texture_number );
+ SetTexParameters ();
+
+ if (nomips)
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+ else
+ VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
+
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+
+ return q;
+}
+
+
+
+/*
+===============
+Texture_ForName
+===============
+*/
+//bReload is set to true when called from DemandLoadShaderTexture because it should never re-use
+//an already loaded texture
+qtexture_t *Texture_ForName (const char *name, bool bReplace, bool bShader, bool bNoAlpha, bool bReload, bool makeShader)
+{
+ byte *lump;
+ qtexture_t *q = NULL;
+ char filename[1024];
+
+ if (name == NULL || strlen(name) == 0)
+ return notexture;
+
+ qtexture_t *pRemove = NULL;
+
+ if (!bReload)
+ {
+ for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+ {
+ if (!strcmp(name, q->name))
+ {
+ if (bReplace)
+ {
+ pRemove = q;
+ //Texture_Remove(q);
+ break;
+ }
+ else
+ {
+#ifdef _DEBUG
+ // if the texture is already in memory, then the bNoAlpha flag doesn't have any influence
+ if (bNoAlpha)
+ Sys_Printf("WARNING: bNoAlpha flag on an already loaded texture\n");
+#endif
+ if (!g_dontuse)
+ {
+ q->inuse = true;
+ }
+ return q;
+ }
+ }
+ }
+ }
+
+ // did not find it in the standard list
+ // skip entity names (
+ if (!bShader && name[0] != '(')
+ {
+ CShaderInfo* pShader = hasShader(name);
+ if (pShader)
+ {
+ if (pShader->m_pQTexture == NULL)
+ {
+ DemandLoadShaderTexture(q, pShader);
+ }
+ q = pShader->m_pQTexture;
+ //Sys_Printf ("used Shader %s.\n", pShader->m_strName);
+ }
+ if ( q != NULL)
+ {
+ return q;
+ }
+ }
+
+
+ if (name[0] == '(')
+ {
+ q = Texture_CreateSolid (name);
+ strncpy (q->name, name, sizeof(q->name)-1);
+ }
+ else
+ {
+ // FIXME: this is a mess.. need to move consolidate stuff
+ // down to a single routine..
+ //
+ // if plugins have a texture loader
+ // {
+ //
+ // }
+ // else
+ //
+ if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
+ {
+ // rad: 12/19/98
+ // if the plugin is not a wad style then we need to treat it normally
+ // otherwise return without trying to explicitly load the texture
+ // as it should have been loaded by the wad style plugin at init time
+ CString strTex = GetTextureExtension(0);
+ sprintf (filename, "%s\\%s.%s", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name, strTex);
+ if (!g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
+ {
+ g_pParentWnd->GetPlugInMgr().LoadTexture(filename);
+ if (g_pluginTexture)
+ q = g_pluginTexture;
+ }
+ else
+ {
+ return notexture;
+ // wadstyle.. if we get here then we do not have it
+ }
+ }
+ else
+ // we need to try several formats here, or would it be better if we are given a complete name
+ if (g_PrefsDlg.m_bHiColorTextures == TRUE)
+ {
+ char cWork[1024];
+ sprintf (filename, "%s/%s.tga", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name);
+ QE_ConvertDOSToUnixName( cWork, filename );
+ strcpy(filename, cWork);
+ Sys_Printf ("Loading %s...", name);
+ unsigned char* pPixels = NULL;
+ int nWidth;
+ int nHeight;
+ LoadImage(filename, &pPixels, &nWidth, &nHeight);
+ if (pPixels == NULL)
+ {
+ // try jpg
+ // blatant assumption of .tga should be fine since we sprintf'd it above
+ int nLen = strlen(filename);
+ filename[nLen-3] = 'j';
+ filename[nLen-2] = 'p';
+ filename[nLen-1] = 'g';
+ LoadImage(filename, &pPixels, &nWidth, &nHeight);
+ }
+ if (pPixels)
+ {
+ // if we were asked to ignore alpha channel, do it now (.TGA is the only supported file type with alpha channel)
+ //if (bNoAlpha)
+ if (TRUE)
+ {
+ unsigned char* iPix = pPixels;
+ int nCount = nWidth * nHeight;
+ for(iPix=pPixels+3; iPix-pPixels < nCount*4; iPix+=4)
+ *iPix = 255;
+ }
+ // we'll be binding the GL texture now
+ // need to check we are using a right GL context
+ // with GL plugins that have their own window, the GL context may be the plugin's, in which case loading textures will bug
+ HDC currentHDC = qwglGetCurrentDC();
+ HGLRC currentHGLRC = qwglGetCurrentContext();
+ //++timo FIXME: this may duplicate with qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
+ //++timo FIXME: we need a list of lawfull GL contexts or something?
+ // I'd rather always use the same GL context for binding...
+ if (currentHDC != g_qeglobals.d_hdcBase || currentHGLRC != g_qeglobals.d_hglrcBase)
+ qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase );
+ q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
+ //++timo I don't set back the GL context .. I don't know how safe it is
+ //qwglMakeCurrent( currentHDC, currentHGLRC );
+ //++timo storing the filename .. will be removed by shader code cleanup
+ // this is dirty, and we sure miss some places were we should fill the filename info
+ strcpy( q->filename, name );
+ SetNameShaderInfo(q, filename, name);
+ Sys_Printf ("done.\n", name);
+ free(pPixels);
+ }
+ }
+ else
+ {
+ // load the file
+ sprintf (filename, "%s/%s.wal", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name);
+ Sys_Printf ("Loading %s...", name);
+ if (LoadFile (filename, (void**)&lump) == -1)
+ {
+ sprintf (filename, "%s.wal", name);
+ Sys_Printf("failed.. trying pak0.pak..");
+ if(!PakLoadFile(filename, (void**)&lump))
+ {
+ Sys_Printf (" load failed!\n");
+ return notexture;
+ }
+ }
+ Sys_Printf("successful.\n");
+ q = Texture_LoadTexture ((miptex_t *)lump);
+ free (lump);
+ strncpy (q->name, name, sizeof(q->name)-1);
+ StripExtension (q->name);
+ }
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if(!q)
+ return notexture;
+ }
+
+ }// name[0] != '('
+
+ if(!q) // safety
+ {
+ if (bShader && !makeShader) {
+ return q;
+ }
+
+ if (bShader)
+ {
+ q = Texture_MakeNoshadertexture( name );
+ Sys_Printf("failed, using default shader\n");
+ }
+ else
+ {
+ q = Texture_MakeDefault();
+ Sys_Printf("failed, using default\n");
+ }
+ }
+
+ strncpy (q->name, name, sizeof(q->name)-1);
+ if (name[0] != '(')
+ {
+ StripExtension (q->name);
+ }
+
+ if (!g_dontuse)
+ q->inuse = true;
+ q->next = g_qeglobals.d_qtextures;
+ g_qeglobals.d_qtextures = q;
+
+ if (pRemove != NULL)
+ {
+ ReplaceQTexture(pRemove, q, &active_brushes);
+ ReplaceQTexture(pRemove, q, &filtered_brushes);
+ Texture_Remove(pRemove);
+ }
+
+ return q;
+}
+
+/*
+===============
+Texture_ForNamePath
+===============
+*/
+qtexture_t *Texture_ForNamePath(char* name, char* pFullPath)
+{
+ byte *lump;
+ qtexture_t *q;
+ char filename[1024];
+
+ if (strlen(name) == 0)
+ return notexture;
+
+ for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+ {
+ if (!strcmp(name, q->name))
+ {
+ if (!g_dontuse)
+ q->inuse = true;
+ return q;
+ }
+ }
+
+ if (name[0] == '(')
+ {
+ q = Texture_CreateSolid (name);
+ strncpy (q->name, name, sizeof(q->name)-1);
+ }
+ else
+ {
+ // load the file
+ if (g_PrefsDlg.m_bHiColorTextures == TRUE)
+ {
+ char cWork[1024];
+ if (strstr(pFullPath, ".tga") == NULL) {
+ sprintf(filename, "%s%s", pFullPath, ".tga");
+ } else {
+ strcpy(filename, pFullPath);
+ }
+ QE_ConvertDOSToUnixName( cWork, filename );
+ strcpy(filename, cWork);
+ Sys_Printf ("Loading %s...", name);
+ unsigned char* pPixels = NULL;
+ int nWidth;
+ int nHeight;
+ LoadImage(filename, &pPixels, &nWidth, &nHeight);
+ if (!pPixels)
+ {
+ // try jpg
+ // blatant assumption of .tga should be fine since we sprintf'd it above
+ int nLen = strlen(filename);
+ filename[nLen-3] = 'j';
+ filename[nLen-2] = 'p';
+ filename[nLen-1] = 'g';
+ LoadImage(filename, &pPixels, &nWidth, &nHeight);
+ }
+ if (pPixels)
+ {
+ q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
+ //++timo storing the filename .. will be removed by shader code cleanup
+ // this is dirty, and we sure miss some places were we should fill the filename info
+ // NOTE: we store relative path, need to extract it
+ strcpy( q->filename, name );
+
+ }
+ else
+ {
+ return notexture;
+ }
+ free(pPixels);
+ }
+ else
+ {
+ sprintf(filename, "%s%s", pFullPath, ".wal");
+ Sys_Printf ("Loading %s...", name);
+ if (LoadFile (filename, (void**)&lump) == -1)
+ {
+ Sys_Printf (" load failed!\n");
+ return notexture;
+ }
+ Sys_Printf("successful.\n");
+ q = Texture_LoadTexture ((miptex_t *)lump);
+ free (lump);
+ }
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if(!q)
+ return notexture;
+ }
+ strncpy (q->name, name, sizeof(q->name)-1);
+ StripExtension (q->name);
+ }
+
+ if (!g_dontuse)
+ q->inuse = true;
+ q->next = g_qeglobals.d_qtextures;
+ g_qeglobals.d_qtextures = q;
+
+ return q;
+}
+
+
+
+/*
+==================
+FillTextureMenu
+
+==================
+*/
+void FillTextureMenu (CStringArray* pArray)
+{
+ HMENU hmenu;
+ int i;
+ struct _finddata_t fileinfo;
+ int handle;
+ char dirstring[1024];
+ char *path;
+ DIRLIST *list = NULL, *temp;
+
+ if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
+ {
+ if (g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
+ return;
+ }
+
+ hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_TEXTURE);
+
+ // delete everything
+ for (i=0 ; i<texture_nummenus ; i++)
+ DeleteMenu (hmenu, CMD_TEXTUREWAD+i, MF_BYCOMMAND);
+
+ texture_nummenus = 0;
+
+ // add everything
+ if (g_qeglobals.d_project_entity)
+ {
+ //--if (g_PrefsDlg.m_bUseShaders)
+ //--{
+ //-- path = ValueForKey (g_qeglobals.d_project_entity, "basepath");
+ //-- sprintf (dirstring, "%s/scripts/*.shader", path);
+ //--
+ //--}
+ //--else
+ //--{
+ path = ValueForKey (g_qeglobals.d_project_entity, "texturepath");
+ sprintf (dirstring, "%s/*.*", path);
+ //--}
+
+ handle = _findfirst (dirstring, &fileinfo);
+ if (handle != -1)
+ {
+ do
+ {
+ //--if (g_PrefsDlg.m_bUseShaders)
+ //--{
+ //-- if ((fileinfo.attrib & _A_SUBDIR))
+ //-- continue;
+ //--}
+ //--else
+ //--{
+ if (!(fileinfo.attrib & _A_SUBDIR))
+ continue;
+ if (fileinfo.name[0] == '.')
+ continue;
+ //--}
+ // add this directory to the menu
+ AddToDirListAlphabetized(&list, fileinfo.name, FROMDISK);
+ } while (_findnext( handle, &fileinfo ) != -1);
+
+ _findclose (handle);
+ }
+
+ //--if (!g_PrefsDlg.m_bUseShaders)
+ //--{
+ GetPackTextureDirs(&list);
+ //--}
+
+ for(temp = list; temp; temp = temp->next)
+ {
+ AppendMenu (hmenu, MF_ENABLED|MF_STRING, CMD_TEXTUREWAD+texture_nummenus, (LPCTSTR)temp->dirname);
+ strcpy (texture_menunames[texture_nummenus], temp->dirname);
+ //--if (!g_PrefsDlg.m_bUseShaders)
+ //--{
+ strcat (texture_menunames[texture_nummenus], "/");
+ //--}
+ if (pArray)
+ pArray->Add(temp->dirname);
+ if (++texture_nummenus == MAX_TEXTUREDIRS)
+ break;
+ }
+
+ ClearDirList(&list);
+ }
+
+
+}
+
+
+/*
+==================
+Texture_ClearInuse
+
+A new map is being loaded, so clear inuse markers
+==================
+*/
+void Texture_ClearInuse (void)
+{
+ qtexture_t *q;
+
+ for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+ {
+ q->inuse = false;
+ }
+}
+
+
+
+
+void LoadShadersFromDir(const char *pPath)
+{
+ int nSize = g_lstShaders.GetSize();
+ for (int i = 0; i < nSize; i++)
+ {
+ CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
+ if (pInfo != NULL)
+ {
+ if (strstr(pInfo->m_strName, pPath) && pInfo->m_pQTexture == NULL && strstr(pInfo->m_strName, "models/player") == NULL)
+ {
+ qtexture_t *q = NULL;
+ DemandLoadShaderTexture(q, pInfo);
+ }
+ }
+ }
+}
+
+
+/*
+==============
+Texture_ShowDirectory
+==============
+*/
+void Texture_ShowDirectory (int menunum, bool bLinked)
+{
+ struct _finddata_t fileinfo;
+ int handle;
+ char name[1024];
+ char dirstring[1024];
+ char linkstring[1024];
+ FILELIST *list = NULL, *temp;
+ CString strTemp;
+
+ //Texture_Flush(false);
+ //Select_Deselect();
+ Texture_ClearInuse();
+ texture_showinuse = false;
+ strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]);
+
+ if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
+ {
+ if (g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
+ return;
+ }
+
+ // new
+/*
+ if (!g_PrefsDlg.m_bShaderTest)
+ {
+ g_dontuse = true; // needed because this next piece of code calls Texture_ForName() internally! -slc
+ LoadDeferred(texture_directory);
+ g_dontuse = false;
+ }
+*/
+ if (g_PrefsDlg.m_bHiColorTextures == FALSE)
+ {
+ }
+
+ g_qeglobals.d_texturewin.originy = 0;
+
+ //--if (g_PrefsDlg.m_bUseShaders)
+ //--{
+ //-- sprintf (dirstring, "%s/scripts/%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_directory);
+ //-- Sys_Printf("loading textures from shader %s\n", dirstring);
+ //-- LoadShader(dirstring);
+ //--}
+ //--else
+ //--{
+ Sys_Status("Loading textures\n", 0);
+
+ // load all image files
+
+ sprintf (linkstring, "%s/textures/%stextureinfo.ini", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_menunames[menunum-CMD_TEXTUREWAD]);
+
+ for (int nExt = 0; nExt < GetTextureExtensionCount(); nExt++)
+ {
+ sprintf (dirstring, "%s/textures/%s*.%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
+ Sys_Printf ("Scanning %s\n", dirstring);
+ handle = _findfirst (dirstring, &fileinfo);
+
+ if (handle == -1)
+ {
+ sprintf(dirstring, "%s/%s*.%s", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
+ handle = _findfirst (dirstring, &fileinfo);
+ }
+ if (handle != -1)
+ {
+ do
+ {
+ sprintf (name, "%s%s", texture_directory, fileinfo.name);
+ AddToFileListAlphabetized(&list, name, FROMDISK, 0, false);
+ } while (_findnext( handle, &fileinfo ) != -1);
+ _findclose (handle);
+ }
+ else
+ {
+ sprintf (dirstring, "%s*.%s", texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
+ GetPackFileList(&list, dirstring);
+ }
+ }
+
+ g_dontuse = true;
+ for(temp = list; temp; temp = temp->next)
+ {
+ if(temp->offset == -1)
+ sprintf(name, "%s", temp->filename);
+ else
+ sprintf(name, "%s%s", texture_menunames[menunum-CMD_TEXTUREWAD], temp->filename);
+ StripExtension (name);
+ strTemp = name;
+ strTemp.MakeLower();
+ if ( strTemp.Find(".specular") >= 0 ||
+ strTemp.Find(".glow") >= 0 ||
+ strTemp.Find(".bump") >= 0 ||
+ strTemp.Find(".diffuse") >= 0 ||
+ strTemp.Find(".blend") >= 0 ||
+ strTemp.Find(".alpha") >= 0
+ )
+ continue;
+ else
+ {
+ Texture_ForName (name, true);
+ }
+ }
+
+ ClearFileList(&list);
+ //--}
+
+
+ g_dontuse = false;
+
+ if (!bLinked)
+ {
+
+ for (int k = 0; k < 10; k++)
+ {
+ sprintf(name, "Path%d", k);
+ if (GetPrivateProfileString("Include", name, "", dirstring, 1024, linkstring) > 0)
+ {
+ Texture_ShowDirectory(dirstring, true);
+ }
+ }
+
+ LoadShadersFromDir(texture_directory);
+
+ SortTextures();
+
+ sprintf (name, "Textures: %s", texture_directory);
+ SetWindowText(g_qeglobals.d_hwndEntity, name);
+
+ // select the first texture in the list
+ if (!g_qeglobals.d_texturewin.texdef.name[0])
+ SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
+ }
+}
+
+
+// this can be combined with the above, but per usual i am in a hurry
+//
+void Texture_ShowDirectory (char* pPath, bool bLinked)
+{
+ struct _finddata_t fileinfo;
+ int handle;
+ char name[1024];
+ char dirstring[1024];
+ char linkstring[1024];
+ FILELIST *list = NULL, *temp;
+
+ //Texture_Flush(false);
+
+ texture_showinuse = false;
+ Texture_ClearInuse();
+ strcpy (texture_directory, pPath);
+
+ if (g_PrefsDlg.m_bHiColorTextures == FALSE)
+ {
+ }
+
+ g_qeglobals.d_texturewin.originy = 0;
+ Sys_Status("loading all textures\n", 0);
+
+ // load all .wal files
+ for (int nExt = 0; nExt < GetTextureExtensionCount(); nExt++)
+ {
+ sprintf(dirstring, "%s*.%s", pPath,GetTextureExtension(nExt));
+
+ Sys_Printf ("Scanning %s\n", dirstring);
+
+ handle = _findfirst (dirstring, &fileinfo);
+
+ if (handle != -1)
+ {
+ do
+ {
+ sprintf (name, "%s%s", texture_directory, fileinfo.name);
+ AddToFileListAlphabetized(&list, name, FROMDISK, 0, false);
+ } while (_findnext( handle, &fileinfo ) != -1);
+ _findclose (handle);
+ }
+ else
+ {
+ //sprintf (dirstring, "%s*.wal", texture_menunames[menunum-CMD_TEXTUREWAD]);
+ //if(!GetPackFileList(&list, dirstring))
+ return;
+ }
+ }
+
+ g_dontuse = true;
+ for(temp = list; temp; temp = temp->next)
+ {
+ if(temp->offset == -1)
+ sprintf(name, "%s", temp->filename);
+ else
+ sprintf(name, "%s%s", pPath, temp->filename);
+ StripExtension (name);
+
+ int nLen = strlen(name)-1;
+ ASSERT(nLen > 0);
+ while (name[nLen] != '\\')
+ nLen--;
+ // found first one
+ nLen--;
+ ASSERT(nLen > 0);
+ while (name[nLen] != '\\')
+ nLen--;
+ ASSERT(nLen >= 0);
+ QE_ConvertDOSToUnixName(name, name);
+ Texture_ForName(&name[nLen+1]);
+
+ }
+
+ ClearFileList(&list);
+
+ g_dontuse = false;
+
+ SortTextures();
+
+ if (!bLinked)
+ {
+
+ for (int k = 0; k < 10; k++)
+ {
+ sprintf(name, "Path%d", k);
+ if (GetPrivateProfileString("Include", name, "", dirstring, 1024, linkstring) > 0)
+ {
+ Texture_ShowDirectory(dirstring, true);
+ }
+ }
+
+
+ sprintf (name, "Textures: %s", texture_directory);
+ SetWindowText(g_qeglobals.d_hwndEntity, name);
+
+ // select the first texture in the list
+ if (!g_qeglobals.d_texturewin.texdef.name[0])
+ SelectTexture (16, g_qeglobals.d_texturewin.height -16 ,false);
+ }
+}
+
+
+
+void Texture_ResetPosition()
+{
+ SelectTexture (16, g_qeglobals.d_texturewin.height -16 ,false);
+ g_qeglobals.d_texturewin.originy = 0;
+}
+
+
+
+/*
+==================
+Texture_SetInuse
+
+==================
+*/
+void Texture_SetInuse (void)
+{
+ qtexture_t *q;
+
+ for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+ {
+ q->inuse = true;
+ }
+}
+
+
+/*
+==============
+Texture_ShowAll
+==============
+*/
+void Texture_ShowAll()
+{
+ Texture_SetInuse();
+ Sys_Printf("Showing all textures...\n");
+ Sys_UpdateWindows (W_TEXTURE);
+}
+
+/*
+==============
+Texture_ShowInuse
+==============
+*/
+void Texture_ShowInuse (void)
+{
+ face_t *f;
+ brush_t *b;
+ char name[1024];
+
+ texture_showinuse = true;
+ g_dontuse = false;
+
+ g_qeglobals.d_texturewin.originy = 0;
+
+ Texture_ClearInuse();
+ Sys_Status("Selecting active textures\n", 0);
+
+ for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next)
+ {
+ if (b->patchBrush)
+ {
+ Texture_ForName(b->pPatch->d_texture->name);
+ }
+ else
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ Texture_ForName (f->texdef.name);
+ }
+ }
+ }
+
+ for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next)
+ {
+ if (b->patchBrush)
+ {
+ Texture_ForName(b->pPatch->d_texture->name);
+ }
+ else
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ Texture_ForName (f->texdef.name);
+ }
+ }
+ }
+
+ SortTextures();
+ //SetInspectorMode(W_TEXTURE);
+ Sys_UpdateWindows (W_TEXTURE);
+
+ sprintf (name, "Textures: in use");
+ SetWindowText(g_qeglobals.d_hwndEntity, name);
+
+ // select the first texture in the list
+ if (!g_qeglobals.d_texturewin.texdef.name[0])
+ {
+ SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
+ }
+}
+
+/*
+============================================================================
+
+TEXTURE LAYOUT
+
+============================================================================
+*/
+
+void Texture_StartPos (void)
+{
+ current_texture = g_qeglobals.d_qtextures;
+ current_x = 8;
+ current_y = -8;
+ current_row = 0;
+}
+
+qtexture_t *Texture_NextPos (int *x, int *y)
+{
+ qtexture_t *q;
+
+ while (1)
+ {
+ q = current_texture;
+ if (!q)
+ return q;
+ current_texture = current_texture->next;
+ if (q->name[0] == '(') // fake color texture
+ continue;
+
+ if (g_bFilterEnabled)
+ {
+ CString strName = q->name;
+ int nPos = strName.Find('\\');
+ if (nPos == -1)
+ nPos = strName.Find('/');
+ if (nPos >= 0)
+ strName = strName.Right(strName.GetLength() - nPos - 1);
+ if (strnicmp(g_strFilter.GetBuffer(0), strName, g_strFilter.GetLength()) == 0)
+ break;
+ else
+ continue;
+ }
+
+ if (q->bFromShader && g_PrefsDlg.m_bShowShaders == FALSE)
+ {
+ continue;
+ }
+
+ if (q->inuse)
+ break; // always show in use
+
+ if (!texture_showinuse && !strnicmp (q->name, texture_directory, strlen(texture_directory)))
+ break;
+ continue;
+ }
+
+ int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
+ int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
+ if (current_x + nWidth > g_qeglobals.d_texturewin.width-8 && current_row)
+ { // go to the next row unless the texture is the first on the row
+ current_x = 8;
+ current_y -= current_row + FONT_HEIGHT + 4;
+ current_row = 0;
+ }
+
+ *x = current_x;
+ *y = current_y;
+
+ // Is our texture larger than the row? If so, grow the
+ // row height to match it
+
+ if (current_row < nHeight)
+ current_row = nHeight;
+
+ // never go less than 64, or the names get all crunched up
+ current_x += nWidth < 64 ? 64 : nWidth;
+ current_x += 8;
+
+ return q;
+}
+
+/*
+============================================================================
+
+ MOUSE ACTIONS
+
+============================================================================
+*/
+
+static int textures_cursorx, textures_cursory;
+
+
+/*
+============
+Texture_SetTexture
+
+brushprimit_texdef must be understood as a qtexture_t with width=2 height=2 ( the default one )
+============
+*/
+void Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef *pTexdef, bool bSetSelection )
+{
+ qtexture_t *q;
+ int x,y;
+
+ if (texdef->name[0] == '(')
+ {
+ Sys_Status("Can't select an entity texture\n", 0);
+ return;
+ }
+ g_qeglobals.d_texturewin.texdef = *texdef;
+ g_qeglobals.d_texturewin.texdef.flags &= ~SURF_KEEP;
+ g_qeglobals.d_texturewin.texdef.contents &= ~CONTENTS_KEEP;
+ // store the texture coordinates for new brush primitive mode
+ // be sure that all the callers are using the default 2x2 texture
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ g_qeglobals.d_texturewin.brushprimit_texdef = *brushprimit_texdef;
+ }
+ // surface properties plugin
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ if (g_qeglobals.d_texturewin.pTexdef)
+ {
+ // decrement reference count
+ static_cast<IPluginTexdef *>(g_qeglobals.d_texturewin.pTexdef)->DecRef();
+ g_qeglobals.d_texturewin.pTexdef = NULL;
+ }
+ if (pTexdef)
+ {
+ g_qeglobals.d_texturewin.pTexdef = pTexdef->Copy();
+ }
+ }
+
+ Sys_UpdateWindows (W_TEXTURE);
+
+ g_dlgFind.updateTextures(texdef->name);
+
+ if (!g_dlgFind.isOpen() && bSetSelection)
+ {
+ Select_SetTexture(texdef,brushprimit_texdef,bFitScale);
+ }
+
+
+ //plugins: send a message telling that the selected texture may have changed
+ DispatchRadiantMsg( RADIANT_TEXTURE );
+
+ // scroll origin so the texture is completely on screen
+ Texture_StartPos ();
+ while (1)
+ {
+ q = Texture_NextPos (&x, &y);
+ if (!q)
+ break;
+
+ int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
+ int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
+ if (!strcmpi(texdef->name, q->name))
+ {
+ if (y > g_qeglobals.d_texturewin.originy)
+ {
+ g_qeglobals.d_texturewin.originy = y;
+ Sys_UpdateWindows (W_TEXTURE);
+ return;
+ }
+
+ if (y-nHeight-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height)
+ {
+ g_qeglobals.d_texturewin.originy = y-nHeight-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height;
+ Sys_UpdateWindows (W_TEXTURE);
+ return;
+ }
+
+ return;
+ }
+ }
+}
+
+
+HWND FindEditWindow()
+{
+ HWND hwnd = FindWindow("TEditPadForm", NULL);
+ HWND hwndEdit = NULL;
+ if (hwnd != NULL)
+ {
+ HWND hwndTab = FindWindowEx(hwnd, NULL, "TTabControl", NULL);
+ if (hwndTab != NULL)
+ {
+ hwndEdit = FindWindowEx(hwndTab, NULL, "TRicherEdit", NULL);
+ }
+ }
+ return hwndEdit;
+}
+
+void Delay(float fSeconds)
+{
+ DWORD dw = ::GetTickCount();
+ DWORD dwTil = dw + (fSeconds * 1000);
+ while (::GetTickCount() < dwTil)
+ {
+ MSG msg;
+ if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+}
+
+
+void ViewShader(const char *pFile, const char *pName)
+{
+ CString str;
+ char* pBuff = NULL;
+ int nSize = LoadFile(pFile, reinterpret_cast<void**>(&pBuff));
+ if (nSize == -1)
+ {
+ nSize = PakLoadAnyFile(pFile, reinterpret_cast<void**>(&pBuff));
+ }
+ if (nSize > 0)
+ {
+ str = pBuff;
+ }
+ int nStart = 0;
+ if (str.GetLength() > 0)
+ {
+ CString strFind = pName;
+ CString strLook = str;
+ strLook.MakeLower();
+ strFind.MakeLower();
+ int n = strLook.Find(strFind);
+ if (n >= 0)
+ {
+ nStart = n;
+ }
+ }
+
+ CString s= "editpad ";
+ s += pFile;
+ WinExec(s, SW_SHOWNORMAL);
+
+ Delay(1.5);
+
+ HWND hwndEdit = FindEditWindow();
+
+ if (hwndEdit != NULL)
+ {
+ PostMessage(hwndEdit, EM_SETSEL, nStart, nStart);
+ }
+ else
+ {
+ Sys_Printf("Unable to load shader editor.\n");
+ }
+
+
+}
+
+/*
+==============
+SelectTexture
+
+ By mouse click
+==============
+*/
+void SelectTexture (int mx, int my, bool bShift, bool bFitScale)
+{
+ int x, y;
+ qtexture_t *q;
+ texdef_t tex;
+ brushprimit_texdef_t brushprimit_tex;
+
+ my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height;
+
+ Texture_StartPos ();
+ while (1)
+ {
+ q = Texture_NextPos (&x, &y);
+ if (!q)
+ break;
+ int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
+ int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
+ if (mx > x && mx - x < nWidth
+ && my < y && y - my < nHeight + FONT_HEIGHT)
+ {
+ if (bShift)
+ {
+ if (g_PrefsDlg.m_bHiColorTextures && q->shadername[0] != 0)
+ {
+ //CString s = "notepad ";
+ //s += q->shadername;
+ //WinExec(s, SW_SHOWNORMAL);
+
+ ViewShader(q->shadername, q->name);
+
+ }
+ }
+ memset (&tex, 0, sizeof(tex));
+ memset (&brushprimit_tex, 0, sizeof(brushprimit_tex));
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ // brushprimit fitted to a 2x2 texture
+ brushprimit_tex.coords[0][0] = 1.0f;
+ brushprimit_tex.coords[1][1] = 1.0f;
+ }
+ else
+ {
+ tex.scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
+ tex.scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
+ }
+ tex.flags = q->flags;
+ tex.value = q->value;
+ tex.contents = q->contents;
+ //strcpy (tex.name, q->name);
+ tex.SetName(q->name);
+ Texture_SetTexture ( &tex, &brushprimit_tex, bFitScale, GETPLUGINTEXDEF(q));
+ CString strTex;
+ CString strName = q->name;
+ //int nPos = strName.Find('\\');
+ //if (nPos == -1)
+ // nPos = strName.Find('/');
+ //if (nPos >= 0)
+ // strName = strName.Right(strName.GetLength() - nPos - 1);
+ strTex.Format("%s W: %i H: %i", strName.GetBuffer(0), q->width, q->height);
+ g_pParentWnd->SetStatusText(3, strTex);
+ return;
+ }
+ }
+
+ Sys_Status("Did not select a texture\n", 0);
+}
+
+/*
+==============
+Texture_MouseDown
+==============
+*/
+void Texture_MouseDown (int x, int y, int buttons)
+{
+ Sys_GetCursorPos (&textures_cursorx, &textures_cursory);
+
+ // lbutton = select texture
+ if (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_SHIFT) || buttons == (MK_LBUTTON | MK_CONTROL))
+ {
+ SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y, buttons & MK_SHIFT, buttons & MK_CONTROL);
+ UpdateSurfaceDialog();
+ UpdatePatchInspector();
+ }
+}
+
+/*
+==============
+Texture_MouseUp
+==============
+*/
+void Texture_MouseUp (int x, int y, int buttons)
+{
+}
+
+/*
+==============
+Texture_MouseMoved
+==============
+*/
+void Texture_MouseMoved (int x, int y, int buttons)
+{
+ int scale = 1;
+
+ if ( buttons & MK_SHIFT )
+ scale = 4;
+
+ // rbutton = drag texture origin
+ if (buttons & MK_RBUTTON)
+ {
+ Sys_GetCursorPos (&x, &y);
+ if ( y != textures_cursory)
+ {
+ g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale;
+ if (g_qeglobals.d_texturewin.originy > 0)
+ g_qeglobals.d_texturewin.originy = 0;
+ Sys_SetCursorPos (textures_cursorx, textures_cursory);
+ CWnd *pWnd = CWnd::FromHandle(g_qeglobals.d_hwndTexture);
+ if (g_PrefsDlg.m_bTextureScrollbar && pWnd != NULL)
+ {
+ pWnd->SetScrollPos(SB_VERT, abs(g_qeglobals.d_texturewin.originy));
+ }
+ InvalidateRect(g_qeglobals.d_hwndTexture, NULL, false);
+ UpdateWindow (g_qeglobals.d_hwndTexture);
+ }
+ return;
+ }
+}
+
+
+/*
+============================================================================
+
+DRAWING
+
+============================================================================
+*/
+
+int imax(int iFloor, int i) { if (i>iFloor) return iFloor; return i; }
+HFONT ghFont = NULL;
+
+/*
+============
+Texture_Draw2
+============
+*/
+void Texture_Draw2 (int width, int height)
+{
+ qtexture_t *q;
+ int x, y;
+ char *name;
+
+ qglClearColor (
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0],
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1],
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2],
+ 0);
+ qglViewport (0,0,width,height);
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadIdentity ();
+
+ qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ qglDisable (GL_DEPTH_TEST);
+ qglDisable(GL_BLEND);
+ qglOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100);
+ qglEnable (GL_TEXTURE_2D);
+
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ g_qeglobals.d_texturewin.width = width;
+ g_qeglobals.d_texturewin.height = height;
+ Texture_StartPos ();
+
+ while (1)
+ {
+ q = Texture_NextPos (&x, &y);
+ if (!q)
+ break;
+
+ int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
+ int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
+ // Is this texture visible?
+ if ( (y-nHeight-FONT_HEIGHT < g_qeglobals.d_texturewin.originy)
+ && (y > g_qeglobals.d_texturewin.originy - height) )
+ {
+
+ // if in use, draw a background
+ if ((q->inuse && !texture_showinuse) || q->bFromShader)
+ {
+ qglLineWidth (1);
+
+ if (q->bFromShader)
+ {
+ qglColor3f (1,1,1);
+ }
+ else
+ {
+ qglColor3f (0.5,1,0.5);
+ }
+ qglDisable (GL_TEXTURE_2D);
+
+ qglBegin (GL_LINE_LOOP);
+ qglVertex2f (x-1,y+1-FONT_HEIGHT);
+ qglVertex2f (x-1,y-nHeight-1-FONT_HEIGHT);
+ qglVertex2f (x+1+nWidth,y-nHeight-1-FONT_HEIGHT);
+ qglVertex2f (x+1+nWidth,y+1-FONT_HEIGHT);
+ qglEnd ();
+
+ qglEnable (GL_TEXTURE_2D);
+ }
+
+ // Draw the texture
+ float fScale = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? ((float)g_PrefsDlg.m_nTextureScale / 100) : 1.0;
+
+ qglBindTexture( GL_TEXTURE_2D, q->texture_number );
+ QE_CheckOpenGLForErrors();
+ qglColor3f (1,1,1);
+ qglBegin (GL_QUADS);
+ qglTexCoord2f (0,0);
+ qglVertex2f (x,y-FONT_HEIGHT);
+ qglTexCoord2f (1,0);
+ qglVertex2f (x+nWidth,y-FONT_HEIGHT);
+ qglTexCoord2f (1,1);
+ qglVertex2f (x+nWidth,y-FONT_HEIGHT-nHeight);
+ qglTexCoord2f (0,1);
+ qglVertex2f (x,y-FONT_HEIGHT-nHeight);
+ qglEnd ();
+
+ // draw the selection border
+ if (!strcmpi(g_qeglobals.d_texturewin.texdef.name, q->name))
+ {
+ qglLineWidth (3);
+ qglColor3f (1,0,0);
+ qglDisable (GL_TEXTURE_2D);
+
+ qglBegin (GL_LINE_LOOP);
+ qglVertex2f (x-4,y-FONT_HEIGHT+4);
+ qglVertex2f (x-4,y-FONT_HEIGHT-nHeight-4);
+ qglVertex2f (x+4+nWidth,y-FONT_HEIGHT-nHeight-4);
+ qglVertex2f (x+4+nWidth,y-FONT_HEIGHT+4);
+ qglEnd ();
+
+ qglEnable (GL_TEXTURE_2D);
+ qglLineWidth (1);
+ }
+
+ // draw the texture name
+ qglColor3f (0,0,0);
+
+ qglRasterPos2f (x, y-FONT_HEIGHT+2);
+
+ // don't draw the directory name
+ for (name = q->name ; *name && *name != '/' && *name != '\\' ; name++)
+ ;
+ if (!*name)
+ name = q->name;
+ else
+ name++;
+
+ if (g_PrefsDlg.m_bHiColorTextures && q->shadername[0] != 0)
+ {
+ // slow as shit
+ CString s = "[";
+ s += name;
+ s += "]";
+ qglCallLists (s.GetLength(), GL_UNSIGNED_BYTE, s.GetBuffer(0));
+ }
+ else
+ {
+ qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
+ }
+ }
+ }
+
+ g_qeglobals.d_texturewin.m_nTotalHeight = abs(y) + 100;
+ // reset the current texture
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+ qglFinish();
+}
+
+
+void Texture_Init (bool bHardInit)
+{
+ char name[1024];
+ byte *pal = NULL;
+
+ if (g_PrefsDlg.m_bHiColorTextures == FALSE)
+ {
+ // load the palette
+ sprintf (name, "%s/pics/colormap.pcx", ValueForKey (g_qeglobals.d_project_entity, "basepath"));
+
+ Load256Image (name, NULL, &pal, NULL, NULL);
+ if (!pal)
+ {
+ // before dropping out, try to load it from the QERadiant directory
+ CString strFile = g_strAppPath;
+ AddSlash(strFile);
+ strFile += "colormap.pcx";
+ Load256Image (strFile.GetBuffer(0), NULL, &pal, NULL, NULL);
+ if (!pal)
+ Sys_Printf ("Couldn't load %s or %s", name, strFile);
+ }
+ else
+ {
+ Texture_InitPalette (pal);
+ free (pal);
+ }
+ }
+
+ // create the fallback texture
+
+ if (bHardInit)
+ {
+ Texture_MakeNotexture();
+ g_qeglobals.d_qtextures = NULL;
+ }
+ LoadShaders();
+
+}
+
+void Texture_FlushUnused()
+{
+ CWaitCursor cursor;
+ Texture_ShowInuse();
+ if (g_qeglobals.d_qtextures)
+ {
+ qtexture_t* pTex = g_qeglobals.d_qtextures->next;
+ qtexture_t *pPrev = g_qeglobals.d_qtextures;
+ while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
+ {
+ qtexture_t* pNextTex = pTex->next;
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ // Timo
+ // Surface properties plugin
+#ifdef _DEBUG
+ if ( !pTex->pData )
+ Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
+#endif
+ if ( pTex->pData && pTex->inuse )
+ GETPLUGINTEXDEF(pTex)->DecRef();
+ }
+
+ if (!pTex->inuse)
+ {
+ unsigned int nTexture = pTex->texture_number;
+ qglDeleteTextures(1, &nTexture);
+ pPrev->next = pNextTex;
+ free(pTex);
+ }
+ else
+ {
+ pPrev = pTex;
+ }
+ pTex = pNextTex;
+ }
+ }
+}
+
+void Texture_Cleanup(CStringList *pList)
+{
+ if (g_qeglobals.d_qtextures)
+ {
+ qtexture_t* pTex = g_qeglobals.d_qtextures->next;
+ while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
+ {
+ qtexture_t* pNextTex = pTex->next;
+ if (pList)
+ {
+ if (pTex->name[0] != '(')
+ {
+ pList->AddTail(pTex->name);
+ }
+ }
+
+ if (g_qeglobals.bSurfacePropertiesPlugin)
+ {
+ // Timo
+ // Surface properties plugin
+#ifdef _DEBUG
+ if ( !pTex->pData )
+ Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
+#endif
+ if ( pTex->pData )
+ GETPLUGINTEXDEF(pTex)->DecRef();
+ }
+ free(pTex);
+ pTex = pNextTex;
+ }
+ }
+
+ int nSize = g_lstSkinCache.GetSize();
+ for (int i = 0; i < nSize; i++)
+ {
+ SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
+ delete pInfo;
+ }
+
+}
+
+/*
+==================
+Texture_Flush
+==================
+*/
+void Texture_Flush (bool bReload)
+{
+ if (!ConfirmModified())
+ return;
+
+ Map_New ();
+
+ CWaitCursor cursor;
+ CStringList strList;
+ Texture_Init(false);
+ Texture_Cleanup(&strList);
+
+ GLuint* pGln = new GLuint[texture_extension_number-1];
+ qglGenTextures(texture_extension_number-1, pGln);
+ QE_CheckOpenGLForErrors();
+ qglDeleteTextures(texture_extension_number-1, pGln);
+ QE_CheckOpenGLForErrors();
+ delete []pGln;
+ texture_extension_number = 1;
+ g_qeglobals.d_qtextures = NULL;
+
+ if (bReload)
+ {
+ POSITION pos = strList.GetHeadPosition();
+ while (pos)
+ {
+ CString strTex = strList.GetNext(pos);
+ Texture_ForName (strTex.GetBuffer(0));
+ }
+ }
+
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CTexWnd
+IMPLEMENT_DYNCREATE(CTexWnd, CWnd);
+
+CTexWnd::CTexWnd()
+{
+ m_bNeedRange = true;
+}
+
+CTexWnd::~CTexWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CTexWnd, CWnd)
+ //{{AFX_MSG_MAP(CTexWnd)
+ ON_WM_CREATE()
+ ON_WM_SIZE()
+ ON_WM_PARENTNOTIFY()
+ ON_WM_TIMER()
+ ON_WM_KEYDOWN()
+ ON_WM_KEYUP()
+ ON_WM_PAINT()
+ ON_WM_VSCROLL()
+ ON_COMMAND(ID_TEXTURES_FLUSH, OnTexturesFlush)
+ ON_BN_CLICKED(1200, OnShaderClick)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CTexWnd message handlers
+
+/*
+============
+WTexWndProc
+============
+*/
+LONG WINAPI TexWndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int xPos, yPos;
+ RECT rect;
+
+ GetClientRect(hWnd, &rect);
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ s_hdcTexture = GetDC(hWnd);
+ QEW_SetupPixelFormat(s_hdcTexture, false);
+
+ if ( ( s_hglrcTexture = qwglCreateContext( s_hdcTexture ) ) == 0 )
+ Error( "wglCreateContext in WTex_WndProc failed" );
+
+ if (!qwglShareLists( g_qeglobals.d_hglrcBase, s_hglrcTexture ) )
+ Error( "wglShareLists in WTex_WndProc failed" );
+
+ if (!qwglMakeCurrent( s_hdcTexture, s_hglrcTexture ))
+ Error ("wglMakeCurrent in WTex_WndProc failed");
+
+ g_qeglobals.d_hwndTexture = hWnd;
+ return 0;
+
+ case WM_DESTROY:
+ //wglMakeCurrent( NULL, NULL );
+ //wglDeleteContext( s_hglrcTexture );
+ ReleaseDC( hWnd, s_hdcTexture );
+ return 0;
+#if 0
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint(hWnd, &ps);
+
+ if ( !qwglMakeCurrent( s_hdcTexture, s_hglrcTexture ) )
+ //if ( !wglMakeCurrent( ps.hdc, s_hglrcTexture ) )
+ {
+ Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
+ Sys_Printf("Please restart Q3Radiant if the Texture view is not working\n");
+ }
+ else
+ {
+ Texture_Draw2 (rect.right-rect.left, rect.bottom-rect.top - g_nTextureOffset);
+ qwglSwapBuffers(s_hdcTexture);
+ TRACE("Texture Paint\n");
+ }
+ EndPaint(hWnd, &ps);
+ }
+ return 0;
+#endif
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ SetCapture( g_qeglobals.d_hwndTexture );
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+
+ Texture_MouseDown (xPos, yPos - g_nTextureOffset, wParam);
+ return 0;
+
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_LBUTTONUP:
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+
+ Texture_MouseUp (xPos, yPos - g_nTextureOffset, wParam);
+ if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+ return 0;
+
+ case WM_MOUSEMOVE:
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+
+ Texture_MouseMoved (xPos, yPos - g_nTextureOffset, wParam);
+ return 0;
+ }
+
+ return DefWindowProc (hWnd, uMsg, wParam, lParam);
+}
+
+
+
+BOOL CTexWnd::PreCreateWindow(CREATESTRUCT& cs)
+{
+ WNDCLASS wc;
+ HINSTANCE hInstance = AfxGetInstanceHandle();
+ if (::GetClassInfo(hInstance, TEXTURE_WINDOW_CLASS, &wc) == FALSE)
+ {
+ // Register a new class
+ memset (&wc, 0, sizeof(wc));
+ wc.style = CS_NOCLOSE | CS_OWNDC;
+ wc.lpszClassName = TEXTURE_WINDOW_CLASS;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.lpfnWndProc = TexWndProc;
+ if (AfxRegisterClass(&wc) == FALSE)
+ Error ("CZWnd RegisterClass: failed");
+ }
+
+ cs.lpszClass = TEXTURE_WINDOW_CLASS;
+ cs.lpszName = "TEX";
+ if (cs.style != QE3_CHILDSTYLE && cs.style != QE3_STYLE)
+ cs.style = QE3_SPLITTER_STYLE;
+
+ return CWnd::PreCreateWindow(cs);
+}
+
+int CTexWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ CRect rctEdit(8, 5, 20, 20);
+ g_nTextureOffset = 0;
+
+/*
+ if (g_PrefsDlg.m_bShaderTest)
+ {
+ m_wndShaders.Create("Show Shaders", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, rctEdit, this, 1200);
+ m_wndShaders.ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
+ m_wndShaders.SetCheck(g_PrefsDlg.m_bShowShaders);
+ g_nTextureOffset = 25;
+ }
+*/
+ rctEdit.SetRect(8, g_nTextureOffset, 20, 20);
+ m_wndFilter.Create(WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_LEFT, rctEdit, this, 1201);
+ m_wndFilter.ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
+ m_wndFilter.SetTexWnd(this);
+
+ g_nTextureOffset += 25;
+ if (!g_PrefsDlg.m_bTextureWindow)
+ {
+ m_wndFilter.ShowWindow(SW_HIDE);
+ g_nTextureOffset -= 25;
+ }
+
+ ShowScrollBar(SB_VERT, g_PrefsDlg.m_bTextureScrollbar);
+ m_bNeedRange = true;
+
+ return 0;
+}
+
+void CTexWnd::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+ CRect rctClient;
+ GetClientRect(rctClient);
+/*
+ if (g_PrefsDlg.m_bShaderTest && m_wndShaders.GetSafeHwnd())
+ {
+ m_wndShaders.SetWindowPos(NULL, rctClient.left + 8, rctClient.top + 5, rctClient.right - 16, 20, 0);
+ }
+*/
+ m_wndFilter.SetWindowPos(NULL, rctClient.left + 8, rctClient.top + 25, rctClient.right - 16, 20, 0);
+ m_bNeedRange = true;
+}
+
+void CTexWnd::OnShaderClick()
+{
+ g_PrefsDlg.m_bShowShaders = (m_wndShaders.GetCheck() != 0);
+ g_PrefsDlg.SavePrefs();
+ RedrawWindow();
+}
+
+void CTexWnd::OnParentNotify(UINT message, LPARAM lParam)
+{
+ CWnd::OnParentNotify(message, lParam);
+}
+
+int g_nLastLen = 0;
+int g_nTimerHandle = -1;
+char g_cLastChar;
+
+void CTexWnd::UpdateFilter(const char* pFilter)
+{
+ if (g_nTimerHandle > 0)
+ KillTimer(1);
+ g_bFilterEnabled = false;
+ if (pFilter)
+ {
+ g_strFilter = pFilter;
+ if (g_strFilter.GetLength() > 0)
+ {
+ g_bFilterEnabled = true;
+ if (g_pParentWnd->CurrentStyle() == QR_QE4 || g_pParentWnd->CurrentStyle() == QR_4WAY)
+ {
+ if (g_strFilter.GetLength() > g_nLastLen)
+ {
+ g_cLastChar = toupper(g_strFilter.GetAt(g_strFilter.GetLength()-1));
+ if (g_cLastChar == 'N' || g_cLastChar == 'O') // one of the other popups
+ {
+ g_nTimerHandle = SetTimer(1, 800, NULL); // half second timer
+ }
+ }
+ }
+ }
+ g_nLastLen = g_strFilter.GetLength();
+ SortTextures();
+ }
+ Sys_UpdateWindows (W_TEXTURE);
+}
+
+void CTexWnd::UpdatePrefs()
+{
+ if (!g_PrefsDlg.m_bTextureWindow)
+ {
+ m_wndFilter.ShowWindow(SW_HIDE);
+ g_nTextureOffset = 0;
+ }
+ else
+ {
+ m_wndFilter.ShowWindow(SW_SHOW);
+ g_nTextureOffset = 25;
+ }
+ ShowScrollBar(SB_VERT, g_PrefsDlg.m_bTextureScrollbar);
+ m_bNeedRange = true;
+ Invalidate();
+ UpdateWindow();
+}
+
+void CTexWnd::FocusEdit()
+{
+ if (m_wndFilter.IsWindowVisible())
+ m_wndFilter.SetFocus();
+}
+
+void CTexWnd::OnTimer(UINT nIDEvent)
+{
+ KillTimer(1);
+ g_nLastLen = 0;
+ g_nTimerHandle = -1;
+ ::SetFocus(g_qeglobals.d_hwndEntity);
+ ::PostMessage(g_qeglobals.d_hwndEntity, WM_CHAR, g_cLastChar, 0);
+}
+
+void CTexWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
+ //CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CTexWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
+}
+
+void CTexWnd::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+ CRect rctClient;
+ GetClientRect(rctClient);
+ int nOld = g_qeglobals.d_texturewin.m_nTotalHeight;
+ if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
+ //if ( !qwglMakeCurrent(dc.m_hDC, s_hglrcTexture ) )
+ {
+ Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
+ Sys_Printf("Please restart Q3Radiant if the Texture view is not working\n");
+ }
+ else
+ {
+ Texture_Draw2 (rctClient.right-rctClient.left, rctClient.bottom-rctClient.top - g_nTextureOffset);
+ qwglSwapBuffers(s_hdcTexture);
+ TRACE("Texture Paint\n");
+ }
+ if (g_PrefsDlg.m_bTextureScrollbar && (m_bNeedRange || g_qeglobals.d_texturewin.m_nTotalHeight != nOld))
+ {
+ m_bNeedRange = false;
+ SetScrollRange(SB_VERT, 0, g_qeglobals.d_texturewin.m_nTotalHeight, TRUE);
+ }
+}
+
+void CTexWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
+{
+ CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
+
+ int n = GetScrollPos(SB_VERT);;
+ switch (nSBCode)
+ {
+ case SB_LINEUP :
+ {
+ n = (n - 15 > 0) ? n - 15 : 0;
+ break;
+ }
+ case SB_LINEDOWN :
+ {
+ n = (n + 15 < g_qeglobals.d_texturewin.m_nTotalHeight) ? n + 15 : n;
+ break;
+ }
+ case SB_PAGEUP :
+ {
+ n = (n - g_qeglobals.d_texturewin.height > 0) ? n - g_qeglobals.d_texturewin.height : 0;
+ break;
+ }
+ case SB_PAGEDOWN :
+ {
+ n = (n + g_qeglobals.d_texturewin.height < g_qeglobals.d_texturewin.m_nTotalHeight) ? n + g_qeglobals.d_texturewin.height : n;
+ break;
+ }
+ case SB_THUMBPOSITION :
+ {
+ n = nPos;
+ break;
+ }
+ case SB_THUMBTRACK :
+ {
+ n = nPos;
+ break;
+ }
+ }
+ SetScrollPos(SB_VERT, n);
+ g_qeglobals.d_texturewin.originy = -((int)n);
+ Invalidate();
+ UpdateWindow();
+ //Sys_UpdateWindows(W_TEXTURE);
+}
+
+/*
+and are the caps new caps? anything done with older stuff will be fubar'd.. which brings up the point if you ever naturalize a cap, you cannot force it back to cap texturing.. i will add that too
+*/
+
+void CTexWnd::OnTexturesFlush()
+{
+ // TODO: Add your command handler code here
+
+}
+
+void LoadShaders()
+{
+ char dirstring[1024];
+ char *path;
+ //struct _finddata_t fileinfo;
+ //int handle;
+ path = ValueForKey (g_qeglobals.d_project_entity, "basepath");
+ sprintf (dirstring, "%s/scripts/shaderlist.txt", path);
+ char *pBuff = NULL;
+
+ int nLen = LoadFile(dirstring, reinterpret_cast<void**>(&pBuff));
+ if (nLen == -1)
+ {
+ nLen = PakLoadAnyFile(dirstring, reinterpret_cast<void**>(&pBuff));
+ }
+ if (nLen > 0)
+ {
+ CStringList lst;
+ StartTokenParsing(pBuff);
+ nLen = 0;
+ while (GetToken(true))
+ {
+ // each token should be a shader filename
+ sprintf(dirstring, "%s/scripts/%s.shader", path, token);
+ lst.AddTail(dirstring);
+ nLen++;
+ }
+ POSITION pos = lst.GetHeadPosition();
+ while (pos != NULL)
+ {
+ LoadShader(lst.GetAt(pos).GetBuffer(0), NULL);
+ lst.GetNext(pos);
+ }
+ free(pBuff);
+ }
+ else
+ {
+ Sys_Printf("Unable to load shaderlist.txt, shaders not loaded!");
+ }
+
+/*
+ handle = _findfirst (dirstring, &fileinfo);
+ if (handle != -1)
+ {
+ do
+ {
+ if ((fileinfo.attrib & _A_SUBDIR))
+ continue;
+ sprintf(dirstring, "%s/scripts/%s", path, fileinfo.name);
+ LoadShader(dirstring, NULL);
+ } while (_findnext( handle, &fileinfo ) != -1);
+
+ _findclose (handle);
+ }
+*/
+}
+
+void FreeShaders()
+{
+ int nSize = g_lstShaders.GetSize();
+ for (int i = 0; i < nSize; i++)
+ {
+ CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
+ delete pInfo;
+ }
+
+ g_lstShaders.RemoveAll();
+}
+
+void ReloadShaders()
+{
+ FreeShaders();
+ LoadShaders();
+ qtexture_t* pTex = g_qeglobals.d_qtextures;
+ while (pTex != NULL)
+ {
+ SetNameShaderInfo(pTex, NULL, pTex->name);
+ pTex = pTex->next;
+ }
+
+}
+
+int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight)
+{
+ byte *pic = NULL;
+ byte *pic32 = NULL;
+ int nTex = -1;
+
+ strlwr(pName);
+ QE_ConvertDOSToUnixName(pName, pName);
+
+ int nSize = g_lstSkinCache.GetSize();
+ for (int i = 0; i < nSize; i++)
+ {
+ SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
+ if (pInfo)
+ {
+ if (stricmp(pName, pInfo->m_strName) == 0)
+ {
+ return pInfo->m_nTextureBind;
+ }
+ }
+ }
+
+ LoadImage( pName, &pic32, pnWidth, pnHeight);
+ if (pic32 != NULL)
+ {
+
+ nTex = texture_extension_number++;
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
+ Error ("wglMakeCurrent in LoadTexture failed");
+ }
+
+ qglBindTexture( GL_TEXTURE_2D, nTex);
+ SetTexParameters ();
+
+ int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
+ while (nCount-- > 0)
+ {
+ if (*pnWidth > 16 && *pnHeight > 16)
+ {
+ R_MipMap(pic32, *pnWidth, *pnHeight);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if (nomips)
+ {
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, *pnWidth, *pnHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic32);
+ }
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, *pnWidth, *pnHeight,GL_RGBA, GL_UNSIGNED_BYTE, pic32);
+ }
+ else
+ {
+ if (nomips)
+ qglTexImage2D(GL_TEXTURE_2D, 0, 3, *pnWidth, *pnHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic32);
+ else
+ qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, *pnWidth, *pnHeight,GL_RGBA, GL_UNSIGNED_BYTE, pic32);
+ }
+ free (pic32);
+ qglBindTexture( GL_TEXTURE_2D, 0 );
+ }
+
+ SkinInfo *pInfo = new SkinInfo(pName, nTex);
+ g_lstSkinCache.Add(pInfo);
+
+ return nTex;
+}
+
+
diff --git a/q3radiant/TexWnd.h b/q3radiant/TexWnd.h
new file mode 100755
index 0000000..c98fd66
--- /dev/null
+++ b/q3radiant/TexWnd.h
@@ -0,0 +1,88 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_TEXWND_H__44B4BA05_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
+#define AFX_TEXWND_H__44B4BA05_781B_11D1_B53C_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// TexWnd.h : header file
+//
+#include "texedit.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CTexWnd window
+
+class CTexWnd : public CWnd
+{
+ DECLARE_DYNCREATE(CTexWnd);
+// Construction
+public:
+ CTexWnd();
+ void UpdateFilter(const char* pFilter);
+ void UpdatePrefs();
+ void FocusEdit();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTexWnd)
+ protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CTexWnd();
+
+protected:
+ CTexEdit m_wndFilter;
+ CButton m_wndShaders;
+ bool m_bNeedRange;
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CTexWnd)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnParentNotify(UINT message, LPARAM lParam);
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnPaint();
+ afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+ afx_msg void OnTexturesFlush();
+ //}}AFX_MSG
+ afx_msg void OnShaderClick();
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TEXWND_H__44B4BA05_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/TextureBar.cpp b/q3radiant/TextureBar.cpp
new file mode 100755
index 0000000..4a48e26
--- /dev/null
+++ b/q3radiant/TextureBar.cpp
@@ -0,0 +1,208 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//++timo TODO : the whole CTextureBar has to be modified for the new texture code
+
+// TextureBar.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "TextureBar.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureBar dialog
+
+
+CTextureBar::CTextureBar()
+ : CDialogBar()
+{
+ //{{AFX_DATA_INIT(CTextureBar)
+ m_nHShift = 0;
+ m_nHScale = 0;
+ m_nRotate = 0;
+ m_nVShift = 0;
+ m_nVScale = 0;
+ m_nRotateAmt = 45;
+ //}}AFX_DATA_INIT
+}
+
+
+void CTextureBar::DoDataExchange(CDataExchange* pDX)
+{
+ CDialogBar::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CTextureBar)
+ DDX_Control(pDX, IDC_SPIN_ROTATE, m_spinRotate);
+ DDX_Control(pDX, IDC_SPIN_VSCALE, m_spinVScale);
+ DDX_Control(pDX, IDC_SPIN_VSHIFT, m_spinVShift);
+ DDX_Control(pDX, IDC_SPIN_HSCALE, m_spinHScale);
+ DDX_Control(pDX, IDC_SPIN_HSHIFT, m_spinHShift);
+ DDX_Text(pDX, IDC_HSHIFT, m_nHShift);
+ DDX_Text(pDX, IDC_HSCALE, m_nHScale);
+ DDX_Text(pDX, IDC_ROTATE, m_nRotate);
+ DDX_Text(pDX, IDC_VSHIFT, m_nVShift);
+ DDX_Text(pDX, IDC_VSCALE, m_nVScale);
+ DDX_Text(pDX, IDC_EDIT_ROTATEAMT, m_nRotateAmt);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CTextureBar, CDialogBar)
+ //{{AFX_MSG_MAP(CTextureBar)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HSHIFT, OnDeltaposSpinHshift)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VSHIFT, OnDeltaposSpinVshift)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_HSCALE, OnDeltaposSpinHScale)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_VSCALE, OnDeltaposSpinVScale)
+ ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_ROTATE, OnDeltaposSpinRotate)
+ ON_COMMAND(ID_SELECTION_PRINT, OnSelectionPrint)
+ ON_WM_CREATE()
+ ON_BN_CLICKED(IDC_BTN_APPLYTEXTURESTUFF, OnBtnApplytexturestuff)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureBar message handlers
+
+void CTextureBar::OnDeltaposSpinHshift(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ *pResult = 0;
+
+ if (pNMUpDown->iDelta < 0)
+ Select_ShiftTexture(abs(g_qeglobals.d_savedinfo.m_nTextureTweak), 0);
+ else
+ Select_ShiftTexture(-abs(g_qeglobals.d_savedinfo.m_nTextureTweak), 0);
+ GetSurfaceAttributes();
+}
+
+void CTextureBar::OnDeltaposSpinVshift(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+ if (pNMUpDown->iDelta < 0)
+ Select_ShiftTexture(0, abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+ else
+ Select_ShiftTexture(0, -abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+ GetSurfaceAttributes();
+}
+
+void CTextureBar::OnDeltaposSpinHScale(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+ if (pNMUpDown->iDelta < 0)
+ Select_ScaleTexture(abs(g_qeglobals.d_savedinfo.m_nTextureTweak),0);
+ else
+ Select_ScaleTexture(-abs(g_qeglobals.d_savedinfo.m_nTextureTweak),0);
+ GetSurfaceAttributes();
+}
+
+void CTextureBar::OnDeltaposSpinVScale(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ // TODO: Add your control notification handler code here
+
+ *pResult = 0;
+ if (pNMUpDown->iDelta < 0)
+ Select_ScaleTexture(0, abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+ else
+ Select_ScaleTexture(0, -abs(g_qeglobals.d_savedinfo.m_nTextureTweak));
+ GetSurfaceAttributes();
+}
+
+void CTextureBar::OnDeltaposSpinRotate(NMHDR* pNMHDR, LRESULT* pResult)
+{
+ NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
+ *pResult = 0;
+ UpdateData(TRUE);
+ if (pNMUpDown->iDelta < 0)
+ Select_RotateTexture(abs(m_nRotateAmt));
+ else
+ Select_RotateTexture(-abs(m_nRotateAmt));
+ GetSurfaceAttributes();
+}
+
+
+void CTextureBar::OnSelectionPrint()
+{
+ // TODO: Add your command handler code here
+
+}
+
+int CTextureBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CDialogBar::OnCreate(lpCreateStruct) == -1)
+ return -1;
+ return 0;
+}
+
+
+void CTextureBar::OnBtnApplytexturestuff()
+{
+ SetSurfaceAttributes();
+}
+
+void CTextureBar::GetSurfaceAttributes()
+{
+ texdef_t* pt = (g_ptrSelectedFaces.GetSize() > 0) ? &(reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0)))->texdef : &g_qeglobals.d_texturewin.texdef;
+
+ if (pt)
+ {
+ m_nHShift = pt->shift[0];
+ m_nVShift = pt->shift[1];
+ m_nHScale = pt->scale[0];
+ m_nVScale = pt->scale[1];
+ m_nRotate = pt->rotate;
+ UpdateData(FALSE);
+ }
+}
+
+//++timo implement brush primitive here
+void CTextureBar::SetSurfaceAttributes()
+{
+ if (g_ptrSelectedFaces.GetSize() > 0)
+ {
+ if (g_qeglobals.m_bBrushPrimitMode)
+ {
+ Sys_Printf("Warning : brush primitive mode not implemented in CTextureBar");
+ }
+ face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
+
+ texdef_t* pt = &selFace->texdef;
+ UpdateData(TRUE);
+ pt->shift[0] = m_nHShift;
+ pt->shift[1] = m_nVShift;
+ pt->scale[0] = m_nHScale;
+ pt->scale[1] = m_nVScale;
+ pt->rotate = m_nRotate;
+ Sys_UpdateWindows(W_CAMERA);
+ }
+}
diff --git a/q3radiant/TextureBar.h b/q3radiant/TextureBar.h
new file mode 100755
index 0000000..aca4229
--- /dev/null
+++ b/q3radiant/TextureBar.h
@@ -0,0 +1,85 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_TEXTUREBAR_H__86220273_B656_11D1_B59F_00AA00A410FC__INCLUDED_)
+#define AFX_TEXTUREBAR_H__86220273_B656_11D1_B59F_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// TextureBar.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureBar dialog
+
+class CTextureBar : public CDialogBar
+{
+// Construction
+public:
+ void GetSurfaceAttributes();
+ void SetSurfaceAttributes();
+ CTextureBar();
+
+// Dialog Data
+ //{{AFX_DATA(CTextureBar)
+ enum { IDD = IDD_TEXTUREBAR };
+ CSpinButtonCtrl m_spinRotate;
+ CSpinButtonCtrl m_spinVScale;
+ CSpinButtonCtrl m_spinVShift;
+ CSpinButtonCtrl m_spinHScale;
+ CSpinButtonCtrl m_spinHShift;
+ int m_nHShift;
+ int m_nHScale;
+ int m_nRotate;
+ int m_nVShift;
+ int m_nVScale;
+ int m_nRotateAmt;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTextureBar)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CTextureBar)
+ afx_msg void OnDeltaposSpinHshift(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDeltaposSpinVshift(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDeltaposSpinHScale(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDeltaposSpinVScale(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnDeltaposSpinRotate(NMHDR* pNMHDR, LRESULT* pResult);
+ afx_msg void OnSelectionPrint();
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnBtnApplytexturestuff();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TEXTUREBAR_H__86220273_B656_11D1_B59F_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/TextureLayout.cpp b/q3radiant/TextureLayout.cpp
new file mode 100755
index 0000000..80d6f92
--- /dev/null
+++ b/q3radiant/TextureLayout.cpp
@@ -0,0 +1,80 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// TextureLayout.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "TextureLayout.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureLayout dialog
+
+
+CTextureLayout::CTextureLayout(CWnd* pParent /*=NULL*/)
+ : CDialog(CTextureLayout::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CTextureLayout)
+ m_fX = 4.0f;
+ m_fY = 4.0f;
+ //}}AFX_DATA_INIT
+}
+
+
+void CTextureLayout::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CTextureLayout)
+ DDX_Text(pDX, IDC_EDIT_X, m_fX);
+ DDX_Text(pDX, IDC_EDIT_Y, m_fY);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CTextureLayout, CDialog)
+ //{{AFX_MSG_MAP(CTextureLayout)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureLayout message handlers
+
+void CTextureLayout::OnOK()
+{
+ CDialog::OnOK();
+}
+
+BOOL CTextureLayout::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ // TODO: Add extra initialization here
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/TextureLayout.h b/q3radiant/TextureLayout.h
new file mode 100755
index 0000000..aad4444
--- /dev/null
+++ b/q3radiant/TextureLayout.h
@@ -0,0 +1,69 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_TEXTURELAYOUT_H__5EA4C722_173F_11D2_B024_00AA00A410FC__INCLUDED_)
+#define AFX_TEXTURELAYOUT_H__5EA4C722_173F_11D2_B024_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// TextureLayout.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureLayout dialog
+
+class CTextureLayout : public CDialog
+{
+// Construction
+public:
+ CTextureLayout(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CTextureLayout)
+ enum { IDD = IDD_DIALOG_TEXTURELAYOUT };
+ float m_fX;
+ float m_fY;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTextureLayout)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CTextureLayout)
+ virtual void OnOK();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TEXTURELAYOUT_H__5EA4C722_173F_11D2_B024_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/TextureLoad.cpp b/q3radiant/TextureLoad.cpp
new file mode 100755
index 0000000..f9bc938
--- /dev/null
+++ b/q3radiant/TextureLoad.cpp
@@ -0,0 +1,80 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// TextureLoad.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "TextureLoad.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureLoad dialog
+
+
+CTextureLoad::CTextureLoad(CWnd* pParent /*=NULL*/)
+ : CDialog(CTextureLoad::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CTextureLoad)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CTextureLoad::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CTextureLoad)
+ DDX_Control(pDX, IDC_LIST_TEXTURES, m_wndList);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CTextureLoad, CDialog)
+ //{{AFX_MSG_MAP(CTextureLoad)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureLoad message handlers
+
+BOOL CTextureLoad::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CTextureLoad::OnOK()
+{
+ // TODO: Add extra validation here
+
+ CDialog::OnOK();
+}
diff --git a/q3radiant/TextureLoad.h b/q3radiant/TextureLoad.h
new file mode 100755
index 0000000..aff337b
--- /dev/null
+++ b/q3radiant/TextureLoad.h
@@ -0,0 +1,68 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_TEXTURELOAD_H__E53749E6_AAE3_47B8_B909_84C7982E35C9__INCLUDED_)
+#define AFX_TEXTURELOAD_H__E53749E6_AAE3_47B8_B909_84C7982E35C9__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// TextureLoad.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureLoad dialog
+
+class CTextureLoad : public CDialog
+{
+// Construction
+public:
+ CTextureLoad(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CTextureLoad)
+ enum { IDD = IDD_TEXLIST };
+ CListBox m_wndList;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CTextureLoad)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CTextureLoad)
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TEXTURELOAD_H__E53749E6_AAE3_47B8_B909_84C7982E35C9__INCLUDED_)
diff --git a/q3radiant/Textures.h b/q3radiant/Textures.h
new file mode 100755
index 0000000..47a78a5
--- /dev/null
+++ b/q3radiant/Textures.h
@@ -0,0 +1,96 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+//--typedef struct texdef_s
+//--{
+//-- char name[32];
+//-- float shift[2];
+//-- float rotate;
+//-- float scale[2];
+//-- int contents;
+//-- int flags;
+//-- int value;
+//--} texdef_t;
+//--
+//--typedef struct
+//--{
+//-- int width, height;
+//-- int originy;
+//-- texdef_t texdef;
+//-- int m_nTotalHeight;
+//--} texturewin_t;
+//--
+//--#define QER_TRANS 0x00000001
+//--#define QER_NOCARVE 0x00000002
+//--
+//--typedef struct qtexture_s
+//--{
+//-- struct qtexture_s *next;
+//-- char name[64]; // includes partial directory and extension
+//-- int width, height;
+//-- int contents;
+//-- int flags;
+//-- int value;
+//-- int texture_number; // gl bind number
+//--
+//-- char shadername[1024]; // old shader stuff
+//-- qboolean bFromShader; // created from a shader
+//-- float fTrans; // amount of transparency
+//-- int nShaderFlags; // qer_ shader flags
+//-- vec3_t color; // for flat shade mode
+//-- qboolean inuse; // true = is present on the level
+//--} qtexture_t;
+//--
+
+// a texturename of the form (0 0 0) will
+// create a solid color texture
+
+void Texture_Init (bool bHardInit = true);
+void Texture_FlushUnused ();
+void Texture_Flush (bool bReload = false);
+void Texture_ClearInuse (void);
+void Texture_ShowInuse (void);
+void Texture_ShowDirectory (int menunum, bool bLinked = false);
+void Texture_ShowAll();
+void Texture_Cleanup(CStringList *pList = NULL);
+
+// TTimo: added bNoAlpha flag to ignore alpha channel when parsing a .TGA file, transparency is usually achieved through qer_trans keyword in shaders
+// in some cases loading an empty alpha channel causes display bugs (brushes not seen)
+qtexture_t *Texture_ForName (const char *name, bool bReplace = false, bool bShader = false, bool bNoAlpha = false, bool bReload = false, bool makeShader = true);
+
+void Texture_Init (void);
+// Timo
+// added an optional IPluginTexdef when one is available
+// we need a forward declaration, this is crap
+class IPluginTexdef;
+void Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef *pTexdef = NULL, bool bSetSelection = true);
+
+void Texture_SetMode(int iMenu); // GL_TEXTURE_NEAREST, etc..
+void Texture_ResetPosition();
+
+void FreeShaders();
+void LoadShaders();
+void ReloadShaders();
+int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight);
+void Texture_LoadFromPlugIn(LPVOID vp);
+void Texture_StartPos (void);
+qtexture_t *Texture_NextPos (int *x, int *y);
diff --git a/q3radiant/ToolWnd.cpp b/q3radiant/ToolWnd.cpp
new file mode 100755
index 0000000..bc6f294
--- /dev/null
+++ b/q3radiant/ToolWnd.cpp
@@ -0,0 +1,55 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ToolWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ToolWnd.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CToolWnd
+
+CToolWnd::CToolWnd()
+{
+}
+
+CToolWnd::~CToolWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CToolWnd, CWnd)
+ //{{AFX_MSG_MAP(CToolWnd)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CToolWnd message handlers
diff --git a/q3radiant/ToolWnd.h b/q3radiant/ToolWnd.h
new file mode 100755
index 0000000..8cda0f6
--- /dev/null
+++ b/q3radiant/ToolWnd.h
@@ -0,0 +1,68 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_TOOLWND_H__5E29A4F9_A20C_4056_950F_9AA8842F53B7__INCLUDED_)
+#define AFX_TOOLWND_H__5E29A4F9_A20C_4056_950F_9AA8842F53B7__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// ToolWnd.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CToolWnd window
+
+class CToolWnd : public CWnd
+{
+// Construction
+public:
+ CToolWnd();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CToolWnd)
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CToolWnd();
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CToolWnd)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TOOLWND_H__5E29A4F9_A20C_4056_950F_9AA8842F53B7__INCLUDED_)
diff --git a/q3radiant/Undo.cpp b/q3radiant/Undo.cpp
new file mode 100755
index 0000000..ca0a74e
--- /dev/null
+++ b/q3radiant/Undo.cpp
@@ -0,0 +1,884 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+/*
+
+ QERadiant Undo/Redo
+
+
+basic setup:
+
+<-g_undolist---------g_lastundo> <---map data---> <-g_lastredo---------g_redolist->
+
+
+ undo/redo on the world_entity is special, only the epair changes are remembered
+ and the world entity never gets deleted.
+
+ FIXME: maybe reset the Undo system at map load
+ maybe also reset the entityId at map load
+*/
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "qe3.h"
+
+typedef struct undo_s
+{
+ double time; //time operation was performed
+ int id; //every undo has an unique id
+ int done; //true when undo is build
+ char *operation; //name of the operation
+ brush_t brushlist; //deleted brushes
+ entity_t entitylist; //deleted entities
+ struct undo_s *prev, *next; //next and prev undo in list
+} undo_t;
+
+undo_t *g_undolist; //first undo in the list
+undo_t *g_lastundo; //last undo in the list
+undo_t *g_redolist; //first redo in the list
+undo_t *g_lastredo; //last undo in list
+int g_undoMaxSize = 64; //maximum number of undos
+int g_undoSize = 0; //number of undos in the list
+int g_undoMaxMemorySize = 2*1024*1024; //maximum undo memory (default 2 MB)
+int g_undoMemorySize = 0; //memory size of undo buffer
+int g_undoId = 1; //current undo ID (zero is invalid id)
+int g_redoId = 1; //current redo ID (zero is invalid id)
+
+
+/*
+=============
+Undo_MemorySize
+=============
+*/
+int Undo_MemorySize(void)
+{
+ /*
+ int size;
+ undo_t *undo;
+ brush_t *pBrush;
+ entity_t *pEntity;
+
+ size = 0;
+ for (undo = g_undolist; undo; undo = undo->next)
+ {
+ for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pBrush->next)
+ {
+ size += Brush_MemorySize(pBrush);
+ }
+ for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pEntity->next)
+ {
+ size += Entity_MemorySize(pEntity);
+ }
+ size += sizeof(undo_t);
+ }
+ return size;
+ */
+ return g_undoMemorySize;
+}
+
+/*
+=============
+Undo_ClearRedo
+=============
+*/
+void Undo_ClearRedo(void)
+{
+ undo_t *redo, *nextredo;
+ brush_t *pBrush, *pNextBrush;
+ entity_t *pEntity, *pNextEntity;
+
+ for (redo = g_redolist; redo; redo = nextredo)
+ {
+ nextredo = redo->next;
+ for (pBrush = redo->brushlist.next ; pBrush != NULL && pBrush != &redo->brushlist ; pBrush = pNextBrush)
+ {
+ pNextBrush = pBrush->next;
+ Brush_Free(pBrush);
+ }
+ for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = pNextEntity)
+ {
+ pNextEntity = pEntity->next;
+ Entity_Free(pEntity);
+ }
+ free(redo);
+ }
+ g_redolist = NULL;
+ g_lastredo = NULL;
+ g_redoId = 1;
+}
+
+/*
+=============
+Undo_Clear
+
+ Clears the undo buffer.
+=============
+*/
+void Undo_Clear(void)
+{
+ undo_t *undo, *nextundo;
+ brush_t *pBrush, *pNextBrush;
+ entity_t *pEntity, *pNextEntity;
+
+ Undo_ClearRedo();
+ for (undo = g_undolist; undo; undo = nextundo)
+ {
+ nextundo = undo->next;
+ for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pNextBrush)
+ {
+ pNextBrush = pBrush->next;
+ g_undoMemorySize -= Brush_MemorySize(pBrush);
+ Brush_Free(pBrush);
+ }
+ for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pNextEntity)
+ {
+ pNextEntity = pEntity->next;
+ g_undoMemorySize -= Entity_MemorySize(pEntity);
+ Entity_Free(pEntity);
+ }
+ g_undoMemorySize -= sizeof(undo_t);
+ free(undo);
+ }
+ g_undolist = NULL;
+ g_lastundo = NULL;
+ g_undoSize = 0;
+ g_undoMemorySize = 0;
+ g_undoId = 1;
+}
+
+/*
+=============
+Undo_SetMaxSize
+=============
+*/
+void Undo_SetMaxSize(int size)
+{
+ Undo_Clear();
+ if (size < 1) g_undoMaxSize = 1;
+ else g_undoMaxSize = size;
+}
+
+/*
+=============
+Undo_GetMaxSize
+=============
+*/
+int Undo_GetMaxSize(void)
+{
+ return g_undoMaxSize;
+}
+
+/*
+=============
+Undo_SetMaxMemorySize
+=============
+*/
+void Undo_SetMaxMemorySize(int size)
+{
+ Undo_Clear();
+ if (size < 1024) g_undoMaxMemorySize = 1024;
+ else g_undoMaxMemorySize = size;
+}
+
+/*
+=============
+Undo_GetMaxMemorySize
+=============
+*/
+int Undo_GetMaxMemorySize(void)
+{
+ return g_undoMaxMemorySize;
+}
+
+/*
+=============
+Undo_FreeFirstUndo
+=============
+*/
+void Undo_FreeFirstUndo(void)
+{
+ undo_t *undo;
+ brush_t *pBrush, *pNextBrush;
+ entity_t *pEntity, *pNextEntity;
+
+ //remove the oldest undo from the undo buffer
+ undo = g_undolist;
+ g_undolist = g_undolist->next;
+ g_undolist->prev = NULL;
+ //
+ for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pNextBrush)
+ {
+ pNextBrush = pBrush->next;
+ g_undoMemorySize -= Brush_MemorySize(pBrush);
+ Brush_Free(pBrush);
+ }
+ for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pNextEntity)
+ {
+ pNextEntity = pEntity->next;
+ g_undoMemorySize -= Entity_MemorySize(pEntity);
+ Entity_Free(pEntity);
+ }
+ g_undoMemorySize -= sizeof(undo_t);
+ free(undo);
+ g_undoSize--;
+}
+
+/*
+=============
+Undo_GeneralStart
+=============
+*/
+void Undo_GeneralStart(char *operation)
+{
+ undo_t *undo;
+ brush_t *pBrush;
+ entity_t *pEntity;
+
+
+ if (g_lastundo)
+ {
+ if (!g_lastundo->done)
+ {
+ Sys_Printf("Undo_Start: WARNING last undo not finished.\n");
+ }
+ }
+
+ undo = (undo_t *) malloc(sizeof(undo_t));
+ if (!undo) return;
+ memset(undo, 0, sizeof(undo_t));
+ undo->brushlist.next = &undo->brushlist;
+ undo->brushlist.prev = &undo->brushlist;
+ undo->entitylist.next = &undo->entitylist;
+ undo->entitylist.prev = &undo->entitylist;
+ if (g_lastundo) g_lastundo->next = undo;
+ else g_undolist = undo;
+ undo->prev = g_lastundo;
+ undo->next = NULL;
+ g_lastundo = undo;
+
+ undo->time = Sys_DoubleTime();
+ //
+ if (g_undoId > g_undoMaxSize * 2) g_undoId = 1;
+ if (g_undoId <= 0) g_undoId = 1;
+ undo->id = g_undoId++;
+ undo->done = false;
+ undo->operation = operation;
+ //reset the undo IDs of all brushes using the new ID
+ for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
+ {
+ if (pBrush->undoId == undo->id)
+ {
+ pBrush->undoId = 0;
+ }
+ }
+ for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
+ {
+ if (pBrush->undoId == undo->id)
+ {
+ pBrush->undoId = 0;
+ }
+ }
+ //reset the undo IDs of all entities using thew new ID
+ for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
+ {
+ if (pEntity->undoId == undo->id)
+ {
+ pEntity->undoId = 0;
+ }
+ }
+ g_undoMemorySize += sizeof(undo_t);
+ g_undoSize++;
+ //undo buffer is bound to a max
+ if (g_undoSize > g_undoMaxSize)
+ {
+ Undo_FreeFirstUndo();
+ }
+}
+
+/*
+=============
+Undo_BrushInUndo
+=============
+*/
+int Undo_BrushInUndo(undo_t *undo, brush_t *brush)
+{
+ brush_t *b;
+
+ for (b = undo->brushlist.next; b != &undo->brushlist; b = b->next)
+ {
+ if (b == brush) return true;
+ }
+ return false;
+}
+
+/*
+=============
+Undo_EntityInUndo
+=============
+*/
+int Undo_EntityInUndo(undo_t *undo, entity_t *ent)
+{
+ entity_t *e;
+
+ for (e = undo->entitylist.next; e != &undo->entitylist; e = e->next)
+ {
+ if (e == ent) return true;
+ }
+ return false;
+}
+
+/*
+=============
+Undo_Start
+=============
+*/
+void Undo_Start(char *operation)
+{
+ Undo_ClearRedo();
+ Undo_GeneralStart(operation);
+}
+
+/*
+=============
+Undo_AddBrush
+=============
+*/
+void Undo_AddBrush(brush_t *pBrush)
+{
+ if (!g_lastundo)
+ {
+ Sys_Printf("Undo_AddBrushList: no last undo.\n");
+ return;
+ }
+ if (g_lastundo->entitylist.next != &g_lastundo->entitylist)
+ {
+ Sys_Printf("Undo_AddBrushList: WARNING adding brushes after entity.\n");
+ }
+ //if the brush is already in the undo
+ if (Undo_BrushInUndo(g_lastundo, pBrush))
+ return;
+ //clone the brush
+ brush_t* pClone = Brush_FullClone(pBrush);
+ //save the ID of the owner entity
+ pClone->ownerId = pBrush->owner->entityId;
+ //save the old undo ID for previous undos
+ pClone->undoId = pBrush->undoId;
+ Brush_AddToList (pClone, &g_lastundo->brushlist);
+ //
+ g_undoMemorySize += Brush_MemorySize(pClone);
+}
+
+/*
+=============
+Undo_AddBrushList
+=============
+*/
+void Undo_AddBrushList(brush_t *brushlist)
+{
+ brush_t *pBrush;
+
+ if (!g_lastundo)
+ {
+ Sys_Printf("Undo_AddBrushList: no last undo.\n");
+ return;
+ }
+ if (g_lastundo->entitylist.next != &g_lastundo->entitylist)
+ {
+ Sys_Printf("Undo_AddBrushList: WARNING adding brushes after entity.\n");
+ }
+ //copy the brushes to the undo
+ for (pBrush = brushlist->next ; pBrush != NULL && pBrush != brushlist; pBrush=pBrush->next)
+ {
+ //if the brush is already in the undo
+ if (Undo_BrushInUndo(g_lastundo, pBrush))
+ continue;
+ // do we need to store this brush's entity in the undo?
+ // if it's a fixed size entity, the brush that reprents it is not really relevant, it's used for selecting and moving around
+ // what we want to store for undo is the owner entity, epairs and origin/angle stuff
+ //++timo FIXME: if the entity is not fixed size I don't know, so I don't do it yet
+ if (pBrush->owner->eclass->fixedsize == 1)
+ Undo_AddEntity( pBrush->owner );
+ //clone the brush
+ brush_t* pClone = Brush_FullClone(pBrush);
+ //save the ID of the owner entity
+ pClone->ownerId = pBrush->owner->entityId;
+ //save the old undo ID from previous undos
+ pClone->undoId = pBrush->undoId;
+ Brush_AddToList (pClone, &g_lastundo->brushlist);
+ //
+ g_undoMemorySize += Brush_MemorySize(pClone);
+ }
+}
+
+/*
+=============
+Undo_EndBrush
+=============
+*/
+void Undo_EndBrush(brush_t *pBrush)
+{
+ if (!g_lastundo)
+ {
+ //Sys_Printf("Undo_End: no last undo.\n");
+ return;
+ }
+ if (g_lastundo->done)
+ {
+ //Sys_Printf("Undo_End: last undo already finished.\n");
+ return;
+ }
+ pBrush->undoId = g_lastundo->id;
+}
+
+/*
+=============
+Undo_EndBrushList
+=============
+*/
+void Undo_EndBrushList(brush_t *brushlist)
+{
+ if (!g_lastundo)
+ {
+ //Sys_Printf("Undo_End: no last undo.\n");
+ return;
+ }
+ if (g_lastundo->done)
+ {
+ //Sys_Printf("Undo_End: last undo already finished.\n");
+ return;
+ }
+ for (brush_t* pBrush = brushlist->next; pBrush != NULL && pBrush != brushlist; pBrush=pBrush->next)
+ {
+ pBrush->undoId = g_lastundo->id;
+ }
+}
+
+/*
+=============
+Undo_AddEntity
+=============
+*/
+void Undo_AddEntity(entity_t *entity)
+{
+ entity_t* pClone;
+
+ if (!g_lastundo)
+ {
+ Sys_Printf("Undo_AddEntity: no last undo.\n");
+ return;
+ }
+ //if the entity is already in the undo
+ if (Undo_EntityInUndo(g_lastundo, entity))
+ return;
+ //clone the entity
+ pClone = Entity_Clone(entity);
+ //NOTE: Entity_Clone adds the entity to the entity list
+ // so we remove it from that list here
+ Entity_RemoveFromList(pClone);
+ //save the old undo ID for previous undos
+ pClone->undoId = entity->undoId;
+ //save the entity ID (we need a full clone)
+ pClone->entityId = entity->entityId;
+ //
+ Entity_AddToList(pClone, &g_lastundo->entitylist);
+ //
+ g_undoMemorySize += Entity_MemorySize(pClone);
+}
+
+/*
+=============
+Undo_EndEntity
+=============
+*/
+void Undo_EndEntity(entity_t *entity)
+{
+ if (!g_lastundo)
+ {
+ //Sys_Printf("Undo_End: no last undo.\n");
+ return;
+ }
+ if (g_lastundo->done)
+ {
+ //Sys_Printf("Undo_End: last undo already finished.\n");
+ return;
+ }
+ if (entity == world_entity)
+ {
+ //Sys_Printf("Undo_AddEntity: undo on world entity.\n");
+ //NOTE: we never delete the world entity when undoing an operation
+ // we only transfer the epairs
+ return;
+ }
+ entity->undoId = g_lastundo->id;
+}
+
+/*
+=============
+Undo_End
+=============
+*/
+void Undo_End(void)
+{
+ if (!g_lastundo)
+ {
+ //Sys_Printf("Undo_End: no last undo.\n");
+ return;
+ }
+ if (g_lastundo->done)
+ {
+ //Sys_Printf("Undo_End: last undo already finished.\n");
+ return;
+ }
+ g_lastundo->done = true;
+
+ //undo memory size is bound to a max
+ while (g_undoMemorySize > g_undoMaxMemorySize)
+ {
+ //always keep one undo
+ if (g_undolist == g_lastundo) break;
+ Undo_FreeFirstUndo();
+ }
+ //
+ //Sys_Printf("undo size = %d, undo memory = %d\n", g_undoSize, g_undoMemorySize);
+}
+
+/*
+=============
+Undo_Undo
+=============
+*/
+void Undo_Undo(void)
+{
+ undo_t *undo, *redo;
+ brush_t *pBrush, *pNextBrush;
+ entity_t *pEntity, *pNextEntity, *pUndoEntity;
+
+ if (!g_lastundo)
+ {
+ Sys_Printf("Nothing left to undo.\n");
+ return;
+ }
+ if (!g_lastundo->done)
+ {
+ Sys_Printf("Undo_Undo: WARNING: last undo not yet finished!\n");
+ }
+ // get the last undo
+ undo = g_lastundo;
+ if (g_lastundo->prev) g_lastundo->prev->next = NULL;
+ else g_undolist = NULL;
+ g_lastundo = g_lastundo->prev;
+
+ //allocate a new redo
+ redo = (undo_t *) malloc(sizeof(undo_t));
+ if (!redo) return;
+ memset(redo, 0, sizeof(undo_t));
+ redo->brushlist.next = &redo->brushlist;
+ redo->brushlist.prev = &redo->brushlist;
+ redo->entitylist.next = &redo->entitylist;
+ redo->entitylist.prev = &redo->entitylist;
+ if (g_lastredo) g_lastredo->next = redo;
+ else g_redolist = redo;
+ redo->prev = g_lastredo;
+ redo->next = NULL;
+ g_lastredo = redo;
+ redo->time = Sys_DoubleTime();
+ redo->id = g_redoId++;
+ redo->done = true;
+ redo->operation = undo->operation;
+
+ //reset the redo IDs of all brushes using the new ID
+ for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
+ {
+ if (pBrush->redoId == redo->id)
+ {
+ pBrush->redoId = 0;
+ }
+ }
+ for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
+ {
+ if (pBrush->redoId == redo->id)
+ {
+ pBrush->redoId = 0;
+ }
+ }
+ //reset the redo IDs of all entities using thew new ID
+ for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
+ {
+ if (pEntity->redoId == redo->id)
+ {
+ pEntity->redoId = 0;
+ }
+ }
+
+ // remove current selection
+ Select_Deselect();
+ // move "created" brushes to the redo
+ for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush=pNextBrush)
+ {
+ pNextBrush = pBrush->next;
+ if (pBrush->undoId == undo->id)
+ {
+ //Brush_Free(pBrush);
+ //move the brush to the redo
+ Brush_RemoveFromList(pBrush);
+ Brush_AddToList(pBrush, &redo->brushlist);
+ //make sure the ID of the owner is stored
+ pBrush->ownerId = pBrush->owner->entityId;
+ //unlink the brush from the owner entity
+ Entity_UnlinkBrush(pBrush);
+ }
+ }
+ // move "created" entities to the redo
+ for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
+ {
+ pNextEntity = pEntity->next;
+ if (pEntity->undoId == undo->id)
+ {
+ // check if this entity is in the undo
+ for (pUndoEntity = undo->entitylist.next; pUndoEntity != NULL && pUndoEntity != &undo->entitylist; pUndoEntity = pUndoEntity->next)
+ {
+ // move brushes to the undo entity
+ if (pUndoEntity->entityId == pEntity->entityId)
+ {
+ pUndoEntity->brushes.next = pEntity->brushes.next;
+ pUndoEntity->brushes.prev = pEntity->brushes.prev;
+ pEntity->brushes.next = &pEntity->brushes;
+ pEntity->brushes.prev = &pEntity->brushes;
+ }
+ }
+ //
+ //Entity_Free(pEntity);
+ //move the entity to the redo
+ Entity_RemoveFromList(pEntity);
+ Entity_AddToList(pEntity, &redo->entitylist);
+ }
+ }
+ // add the undo entities back into the entity list
+ for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = undo->entitylist.next)
+ {
+ g_undoMemorySize -= Entity_MemorySize(pEntity);
+ //if this is the world entity
+ if (pEntity->entityId == world_entity->entityId)
+ {
+ //free the epairs of the world entity
+ Entity_FreeEpairs(world_entity);
+ //set back the original epairs
+ world_entity->epairs = pEntity->epairs;
+ // unhook the epairs and free the world_entity clone that stored the epairs
+ pEntity->epairs = NULL;
+ Entity_Free(pEntity);
+ }
+ else
+ {
+ Entity_RemoveFromList(pEntity);
+ Entity_AddToList(pEntity, &entities);
+ pEntity->redoId = redo->id;
+ }
+ }
+ // add the undo brushes back into the selected brushes
+ for (pBrush = undo->brushlist.next; pBrush != NULL && pBrush != &undo->brushlist; pBrush = undo->brushlist.next)
+ {
+ g_undoMemorySize -= Brush_MemorySize(pBrush);
+ Brush_RemoveFromList(pBrush);
+ Brush_AddToList(pBrush, &active_brushes);
+ for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
+ {
+ if (pEntity->entityId == pBrush->ownerId)
+ {
+ Entity_LinkBrush(pEntity, pBrush);
+ break;
+ }
+ }
+ //if the brush is not linked then it should be linked into the world entity
+ if (pEntity == NULL || pEntity == &entities)
+ {
+ Entity_LinkBrush(world_entity, pBrush);
+ }
+ //build the brush
+ //Brush_Build(pBrush);
+ Select_Brush(pBrush);
+ pBrush->redoId = redo->id;
+ }
+ //
+ Sys_Printf("%s undone.\n", undo->operation);
+ // free the undo
+ g_undoMemorySize -= sizeof(undo_t);
+ free(undo);
+ g_undoSize--;
+ g_undoId--;
+ if (g_undoId <= 0) g_undoId = 2 * g_undoMaxSize;
+ //
+ g_bScreenUpdates = true;
+ Sys_UpdateWindows(W_ALL);
+}
+
+/*
+=============
+Undo_Redo
+=============
+*/
+void Undo_Redo(void)
+{
+ undo_t *redo;
+ brush_t *pBrush, *pNextBrush;
+ entity_t *pEntity, *pNextEntity, *pRedoEntity;
+
+ if (!g_lastredo)
+ {
+ Sys_Printf("Nothing left to redo.\n");
+ return;
+ }
+ if (g_lastundo)
+ {
+ if (!g_lastundo->done)
+ {
+ Sys_Printf("WARNING: last undo not finished.\n");
+ }
+ }
+ // get the last redo
+ redo = g_lastredo;
+ if (g_lastredo->prev) g_lastredo->prev->next = NULL;
+ else g_redolist = NULL;
+ g_lastredo = g_lastredo->prev;
+ //
+ Undo_GeneralStart(redo->operation);
+ // remove current selection
+ Select_Deselect();
+ // move "created" brushes back to the last undo
+ for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pNextBrush)
+ {
+ pNextBrush = pBrush->next;
+ if (pBrush->redoId == redo->id)
+ {
+ //move the brush to the undo
+ Brush_RemoveFromList(pBrush);
+ Brush_AddToList(pBrush, &g_lastundo->brushlist);
+ g_undoMemorySize += Brush_MemorySize(pBrush);
+ pBrush->ownerId = pBrush->owner->entityId;
+ Entity_UnlinkBrush(pBrush);
+ }
+ }
+ // move "created" entities back to the last undo
+ for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
+ {
+ pNextEntity = pEntity->next;
+ if (pEntity->redoId == redo->id)
+ {
+ // check if this entity is in the redo
+ for (pRedoEntity = redo->entitylist.next; pRedoEntity != NULL && pRedoEntity != &redo->entitylist; pRedoEntity = pRedoEntity->next)
+ {
+ // move brushes to the redo entity
+ if (pRedoEntity->entityId == pEntity->entityId)
+ {
+ pRedoEntity->brushes.next = pEntity->brushes.next;
+ pRedoEntity->brushes.prev = pEntity->brushes.prev;
+ pEntity->brushes.next = &pEntity->brushes;
+ pEntity->brushes.prev = &pEntity->brushes;
+ }
+ }
+ //
+ //Entity_Free(pEntity);
+ //move the entity to the redo
+ Entity_RemoveFromList(pEntity);
+ Entity_AddToList(pEntity, &g_lastundo->entitylist);
+ g_undoMemorySize += Entity_MemorySize(pEntity);
+ }
+ }
+ // add the undo entities back into the entity list
+ for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = redo->entitylist.next)
+ {
+ //if this is the world entity
+ if (pEntity->entityId == world_entity->entityId)
+ {
+ //free the epairs of the world entity
+ Entity_FreeEpairs(world_entity);
+ //set back the original epairs
+ world_entity->epairs = pEntity->epairs;
+ //free the world_entity clone that stored the epairs
+ Entity_Free(pEntity);
+ }
+ else
+ {
+ Entity_RemoveFromList(pEntity);
+ Entity_AddToList(pEntity, &entities);
+ }
+ }
+ // add the redo brushes back into the selected brushes
+ for (pBrush = redo->brushlist.next; pBrush != NULL && pBrush != &redo->brushlist; pBrush = redo->brushlist.next)
+ {
+ Brush_RemoveFromList(pBrush);
+ Brush_AddToList(pBrush, &active_brushes);
+ for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
+ {
+ if (pEntity->entityId == pBrush->ownerId)
+ {
+ Entity_LinkBrush(pEntity, pBrush);
+ break;
+ }
+ }
+ //if the brush is not linked then it should be linked into the world entity
+ if (pEntity == NULL || pEntity == &entities)
+ {
+ Entity_LinkBrush(world_entity, pBrush);
+ }
+ //build the brush
+ //Brush_Build(pBrush);
+ Select_Brush(pBrush);
+ }
+ //
+ Undo_End();
+ //
+ Sys_Printf("%s redone.\n", redo->operation);
+ //
+ g_redoId--;
+ // free the undo
+ free(redo);
+ //
+ g_bScreenUpdates = true;
+ Sys_UpdateWindows(W_ALL);
+}
+
+/*
+=============
+Undo_RedoAvailable
+=============
+*/
+int Undo_RedoAvailable(void)
+{
+ if (g_lastredo) return true;
+ return false;
+}
+
+/*
+=============
+Undo_UndoAvailable
+=============
+*/
+int Undo_UndoAvailable(void)
+{
+ if (g_lastundo)
+ {
+ if (g_lastundo->done)
+ return true;
+ }
+ return false;
+}
diff --git a/q3radiant/Undo.h b/q3radiant/Undo.h
new file mode 100755
index 0000000..27100d7
--- /dev/null
+++ b/q3radiant/Undo.h
@@ -0,0 +1,64 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//
+//
+// QERadiant Multilevel Undo/Redo
+//
+//
+
+//start operation
+void Undo_Start(char *operation);
+//end operation
+void Undo_End(void);
+//add brush to the undo
+void Undo_AddBrush(brush_t *pBrush);
+//add a list with brushes to the undo
+void Undo_AddBrushList(brush_t *brushlist);
+//end a brush after the operation is performed
+void Undo_EndBrush(brush_t *pBrush);
+//end a list with brushes after the operation is performed
+void Undo_EndBrushList(brush_t *brushlist);
+//add entity to undo
+void Undo_AddEntity(entity_t *entity);
+//end an entity after the operation is performed
+void Undo_EndEntity(entity_t *entity);
+//undo last operation
+void Undo_Undo(void);
+//redo last undone operation
+void Undo_Redo(void);
+//returns true if there is something to be undone available
+int Undo_UndoAvailable(void);
+//returns true if there is something to redo available
+int Undo_RedoAvailable(void);
+//clear the undo buffer
+void Undo_Clear(void);
+//set maximum undo size (default 64)
+void Undo_SetMaxSize(int size);
+//get maximum undo size
+int Undo_GetMaxSize(void);
+//set maximum undo memory in bytes (default 2 MB)
+void Undo_SetMaxMemorySize(int size);
+//get maximum undo memory in bytes
+int Undo_GetMaxMemorySize(void);
+//returns the amount of memory used by undo
+int Undo_MemorySize(void);
+
diff --git a/q3radiant/VERTSEL.CPP b/q3radiant/VERTSEL.CPP
new file mode 100755
index 0000000..d41c34b
--- /dev/null
+++ b/q3radiant/VERTSEL.CPP
@@ -0,0 +1,372 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "stdafx.h"
+#include "qe3.h"
+#include "winding.h"
+
+#define NEWEDGESEL 1
+
+
+int FindPoint (vec3_t point)
+{
+ int i, j;
+
+ for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ if (fabs(point[j] - g_qeglobals.d_points[i][j]) > 0.1)
+ break;
+ if (j == 3)
+ return i;
+ }
+
+ VectorCopy (point, g_qeglobals.d_points[g_qeglobals.d_numpoints]);
+ if (g_qeglobals.d_numpoints < MAX_POINTS-1)
+ {
+ g_qeglobals.d_numpoints++;
+ }
+
+ return g_qeglobals.d_numpoints-1;
+}
+
+int FindEdge (int p1, int p2, face_t *f)
+{
+ int i;
+
+ for (i=0 ; i<g_qeglobals.d_numedges ; i++)
+ if (g_qeglobals.d_edges[i].p1 == p2 && g_qeglobals.d_edges[i].p2 == p1)
+ {
+ g_qeglobals.d_edges[i].f2 = f;
+ return i;
+ }
+
+ g_qeglobals.d_edges[g_qeglobals.d_numedges].p1 = p1;
+ g_qeglobals.d_edges[g_qeglobals.d_numedges].p2 = p2;
+ g_qeglobals.d_edges[g_qeglobals.d_numedges].f1 = f;
+
+ if (g_qeglobals.d_numedges < MAX_EDGES-1)
+ {
+ g_qeglobals.d_numedges++;
+ }
+
+ return g_qeglobals.d_numedges-1;
+}
+
+#ifdef NEWEDGESEL
+void MakeFace (brush_t* b, face_t *f)
+#else
+void MakeFace (face_t *f)
+#endif
+{
+ winding_t *w;
+ int i;
+ int pnum[128];
+
+#ifdef NEWEDGESEL
+ w = Brush_MakeFaceWinding (b, f);
+#else
+ w = Brush_MakeFaceWinding (selected_brushes.next, f);
+#endif
+ if (!w)
+ return;
+ for (i=0 ; i<w->numpoints ; i++)
+ pnum[i] = FindPoint (w->points[i]);
+ for (i=0 ; i<w->numpoints ; i++)
+ FindEdge (pnum[i], pnum[(i+1)%w->numpoints], f);
+
+ free (w);
+}
+
+void SetupVertexSelection (void)
+{
+ face_t *f;
+ brush_t *b;
+
+ g_qeglobals.d_numpoints = 0;
+ g_qeglobals.d_numedges = 0;
+
+#ifdef NEWEDGESEL
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ MakeFace (b,f);
+ }
+#else
+ if (!QE_SingleBrush())
+ return;
+
+ b = selected_brushes.next;
+ for (f=b->brush_faces ; f ; f=f->next)
+ MakeFace (b,f);
+#endif
+
+}
+
+
+#ifdef NEWEDGESEL
+void SelectFaceEdge (brush_t* b, face_t *f, int p1, int p2)
+#else
+void SelectFaceEdge (face_t *f, int p1, int p2)
+#endif
+{
+ winding_t *w;
+ int i, j, k;
+ int pnum[128];
+
+#ifdef NEWEDGESEL
+ w = Brush_MakeFaceWinding (b, f);
+#else
+ w = Brush_MakeFaceWinding (selected_brushes.next, f);
+#endif
+ if (!w)
+ return;
+ for (i=0 ; i<w->numpoints ; i++)
+ pnum[i] = FindPoint (w->points[i]);
+
+ for (i=0 ; i<w->numpoints ; i++)
+ if (pnum[i] == p1 && pnum[(i+1)%w->numpoints] == p2)
+ {
+ VectorCopy (g_qeglobals.d_points[pnum[i]], f->planepts[0]);
+ VectorCopy (g_qeglobals.d_points[pnum[(i+1)%w->numpoints]], f->planepts[1]);
+ VectorCopy (g_qeglobals.d_points[pnum[(i+2)%w->numpoints]], f->planepts[2]);
+ for (j=0 ; j<3 ; j++)
+ {
+ for (k=0 ; k<3 ; k++)
+ {
+ f->planepts[j][k] = floor(f->planepts[j][k]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
+ }
+ }
+
+ AddPlanept (f->planepts[0]);
+ AddPlanept (f->planepts[1]);
+ break;
+ }
+
+ if (i == w->numpoints)
+ Sys_Printf ("SelectFaceEdge: failed\n");
+ free (w);
+}
+
+
+void SelectVertex (int p1)
+{
+ brush_t *b;
+ winding_t *w;
+ int i, j, k;
+ face_t *f;
+
+#ifdef NEWEDGESEL
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ w = Brush_MakeFaceWinding (b, f);
+ if (!w)
+ continue;
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ if (FindPoint (w->points[i]) == p1)
+ {
+ VectorCopy (w->points[(i+w->numpoints-1)%w->numpoints], f->planepts[0]);
+ VectorCopy (w->points[i], f->planepts[1]);
+ VectorCopy (w->points[(i+1)%w->numpoints], f->planepts[2]);
+ for (j=0 ; j<3 ; j++)
+ {
+ for (k=0 ; k<3 ; k++)
+ {
+ ;//f->planepts[j][k] = floor(f->planepts[j][k]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
+ }
+ }
+
+ AddPlanept (f->planepts[1]);
+ //MessageBeep(-1);
+
+ break;
+ }
+ }
+ free (w);
+ }
+ }
+#else
+ b = selected_brushes.next;
+ for (f=b->brush_faces ; f ; f=f->next)
+ {
+ w = Brush_MakeFaceWinding (b, f);
+ if (!w)
+ continue;
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ if (FindPoint (w->points[i]) == p1)
+ {
+ VectorCopy (w->points[(i+w->numpoints-1)%w->numpoints], f->planepts[0]);
+ VectorCopy (w->points[i], f->planepts[1]);
+ VectorCopy (w->points[(i+1)%w->numpoints], f->planepts[2]);
+ for (j=0 ; j<3 ; j++)
+ {
+ for (k=0 ; k<3 ; k++)
+ {
+ ;//f->planepts[j][k] = floor(f->planepts[j][k]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
+ }
+ }
+
+ AddPlanept (f->planepts[1]);
+ //MessageBeep(-1);
+
+ break;
+ }
+ }
+ free (w);
+ }
+#endif
+}
+
+void SelectEdgeByRay (vec3_t org, vec3_t dir)
+{
+ int i, j, besti;
+ float d, bestd;
+ vec3_t mid, temp;
+ pedge_t *e;
+
+ // find the edge closest to the ray
+ besti = -1;
+ bestd = 8;
+
+ for (i=0 ; i<g_qeglobals.d_numedges ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ mid[j] = 0.5*(g_qeglobals.d_points[g_qeglobals.d_edges[i].p1][j] + g_qeglobals.d_points[g_qeglobals.d_edges[i].p2][j]);
+
+ VectorSubtract (mid, org, temp);
+ d = DotProduct (temp, dir);
+ VectorMA (org, d, dir, temp);
+ VectorSubtract (mid, temp, temp);
+ d = VectorLength (temp);
+ if (d < bestd)
+ {
+ bestd = d;
+ besti = i;
+ }
+ }
+
+ if (besti == -1)
+ {
+ Sys_Printf ("Click didn't hit an edge\n");
+ return;
+ }
+ Sys_Printf ("hit edge\n");
+
+ // make the two faces that border the edge use the two edge points
+ // as primary drag points
+ g_qeglobals.d_num_move_points = 0;
+ e = &g_qeglobals.d_edges[besti];
+#ifdef NEWEDGESEL
+ for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ {
+ SelectFaceEdge (b, e->f1, e->p1, e->p2);
+ SelectFaceEdge (b, e->f2, e->p2, e->p1);
+ }
+#else
+ SelectFaceEdge (e->f1, e->p1, e->p2);
+ SelectFaceEdge (e->f2, e->p2, e->p1);
+#endif
+
+
+}
+
+void SelectVertexByRay (vec3_t org, vec3_t dir)
+{
+ int i, besti;
+ float d, bestd;
+ vec3_t temp;
+
+ // find the point closest to the ray
+ besti = -1;
+ bestd = 8;
+
+ for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
+ {
+ VectorSubtract (g_qeglobals.d_points[i], org, temp);
+ d = DotProduct (temp, dir);
+ VectorMA (org, d, dir, temp);
+ VectorSubtract (g_qeglobals.d_points[i], temp, temp);
+ d = VectorLength (temp);
+ if (d < bestd)
+ {
+ bestd = d;
+ besti = i;
+ }
+ }
+
+ if (besti == -1)
+ {
+ Sys_Printf ("Click didn't hit a vertex\n");
+ return;
+ }
+ Sys_Printf ("hit vertex\n");
+ g_qeglobals.d_move_points[g_qeglobals.d_num_move_points++] = g_qeglobals.d_points[besti];
+ //SelectVertex (besti);
+}
+
+
+
+extern void AddPatchMovePoint(vec3_t v, bool bMulti, bool bFull);
+void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons)
+{
+ int i, besti;
+ float d, bestd;
+ vec3_t temp;
+
+ // find the point closest to the ray
+ besti = -1;
+ bestd = 8;
+
+ for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
+ {
+ VectorSubtract (g_qeglobals.d_points[i], org, temp);
+ d = DotProduct (temp, dir);
+ VectorMA (org, d, dir, temp);
+ VectorSubtract (g_qeglobals.d_points[i], temp, temp);
+ d = VectorLength (temp);
+ if (d <= bestd)
+ {
+ bestd = d;
+ besti = i;
+ }
+ }
+
+ if (besti == -1)
+ {
+ if (g_pParentWnd->ActiveXY()->AreaSelectOK())
+ {
+ g_qeglobals.d_select_mode = sel_area;
+ VectorCopy(org, g_qeglobals.d_vAreaTL);
+ VectorCopy(org, g_qeglobals.d_vAreaBR);
+ }
+ return;
+ }
+ //Sys_Printf ("hit vertex\n");
+ AddPatchMovePoint(g_qeglobals.d_points[besti], buttons & MK_CONTROL, buttons & MK_SHIFT);
+}
+
+
+
diff --git a/q3radiant/VIEW.H b/q3radiant/VIEW.H
new file mode 100755
index 0000000..3f90520
--- /dev/null
+++ b/q3radiant/VIEW.H
@@ -0,0 +1,53 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+
+typedef struct
+{
+ int x, y;
+ int w, h;
+
+ int redraws; // clear to 0 when need update
+
+ vec3_t color;
+
+ vec3_t origin;
+ vec3_t angles;
+ vec3_t forward, right, up;
+
+ int draw_filtered;
+ int draw_wire;
+ int draw_solid;
+ int draw_textured;
+ int draw_blend;
+} vieworg_t;
+
+extern vieworg_t *view_org;
+extern int keysdown;
+
+void View_Init (void);
+void View_Draw (void);
+void View_MouseDown (int x, int y, int buttons);
+void View_KeyUp (int key);
+void View_KeyDown (int key);
+void View_Reshape(int w, int h);
+
diff --git a/q3radiant/WIN_CAM.CPP b/q3radiant/WIN_CAM.CPP
new file mode 100755
index 0000000..3fb952a
--- /dev/null
+++ b/q3radiant/WIN_CAM.CPP
@@ -0,0 +1,274 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// win_cam.c -- windows specific camera view code
+
+#include "stdafx.h"
+#include "qe3.h"
+
+/*
+============
+CameraWndProc
+============
+*/
+LONG WINAPI WCam_WndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int fwKeys, xPos, yPos;
+ RECT rect;
+
+ GetClientRect(hWnd, &rect);
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+ {
+ HFONT hfont;
+
+ g_qeglobals.d_hdcBase = GetDC(hWnd);
+ QEW_SetupPixelFormat(g_qeglobals.d_hdcBase, true);
+
+ if ( ( g_qeglobals.d_hglrcBase = wglCreateContext( g_qeglobals.d_hdcBase ) ) == 0 )
+ Error ("wglCreateContext failed");
+ if (!wglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase ))
+ Error ("wglMakeCurrent failed");
+
+ Texture_SetMode(g_qeglobals.d_savedinfo.iTexMenu);
+
+ //
+ // create GL font
+ //
+ hfont = CreateFont(
+ 10, // logical height of font
+ 7, // logical average character width
+ 0, // angle of escapement
+ 0, // base-line orientation angle
+ 0, // font weight
+ 0, // italic attribute flag
+ 0, // underline attribute flag
+ 0, // strikeout attribute flag
+ 0, // character set identifier
+ 0, // output precision
+ 0, // clipping precision
+ 0, // output quality
+ 0, // pitch and family
+ 0 // pointer to typeface name string
+ );
+
+ if ( !hfont )
+ Error( "couldn't create font" );
+
+ SelectObject (g_qeglobals.d_hdcBase, hfont);
+
+ if ( ( g_qeglobals.d_font_list = glGenLists (256) ) == 0 )
+ Error( "couldn't create font dlists" );
+
+ // create the bitmap display lists
+ // we're making images of glyphs 0 thru 255
+ if ( !wglUseFontBitmaps (g_qeglobals.d_hdcBase, 1, 255, g_qeglobals.d_font_list) )
+ Error( "wglUseFontBitmaps faileD" );
+
+ // indicate start of glyph display lists
+ glListBase (g_qeglobals.d_font_list);
+
+ // report OpenGL information
+ Sys_Printf ("GL_VENDOR: %s\n", glGetString (GL_VENDOR));
+ Sys_Printf ("GL_RENDERER: %s\n", glGetString (GL_RENDERER));
+ Sys_Printf ("GL_VERSION: %s\n", glGetString (GL_VERSION));
+ Sys_Printf ("GL_EXTENSIONS: %s\n", glGetString (GL_EXTENSIONS));
+ }
+ return 0;
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ if (!wglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase ))
+ Error ("wglMakeCurrent failed");
+
+ if ( BeginPaint(hWnd, &ps) )
+ {
+ QE_CheckOpenGLForErrors();
+ Cam_Draw ();
+ QE_CheckOpenGLForErrors();
+
+ EndPaint(hWnd, &ps);
+ SwapBuffers(g_qeglobals.d_hdcBase);
+ }
+ }
+ return 0;
+
+ case WM_USER+267: // benchmark
+ {
+ PAINTSTRUCT ps;
+ WINDOWPLACEMENT wp;
+ double start, end;
+ int i;
+
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( wp );
+ GetWindowPlacement( g_qeglobals.d_hwndCamera, &wp );
+
+ MoveWindow( g_qeglobals.d_hwndCamera, 30, 30, 400, 400, TRUE );
+
+ BeginPaint(hWnd, &ps);
+ if (!wglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
+ Error ("wglMakeCurrent failed");
+ glDrawBuffer (GL_FRONT);
+
+ start = Sys_DoubleTime ();
+ for (i=0 ; i<100 ; i++)
+ {
+ camera.angles[YAW] = i*4;
+ Cam_Draw ();
+ }
+ wglSwapBuffers(g_qeglobals.d_hdcBase);
+ glDrawBuffer (GL_BACK);
+ end = Sys_DoubleTime ();
+ EndPaint(hWnd, &ps);
+ Sys_Printf ("%5.2f seconds\n", end-start);
+
+ SetWindowPlacement( g_qeglobals.d_hwndCamera, &wp );
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if ( QE_KeyDown (wParam) )
+ return 0;
+ else
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ if (GetTopWindow(g_qeglobals.d_hwndMain) != hWnd)
+ BringWindowToTop(hWnd);
+
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetCapture (g_qeglobals.d_hwndCamera);
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ Cam_MouseDown (xPos, yPos, fwKeys);
+ return 0;
+
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_LBUTTONUP:
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ Cam_MouseUp (xPos, yPos, fwKeys);
+ if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+ return 0;
+
+ case WM_MOUSEMOVE:
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ Cam_MouseMoved (xPos, yPos, fwKeys);
+ return 0;
+
+ case WM_SIZE:
+ camera.width = rect.right;
+ camera.height = rect.bottom;
+ InvalidateRect(g_qeglobals.d_hwndCamera, NULL, false);
+ return 0;
+
+ case WM_KILLFOCUS:
+ case WM_SETFOCUS:
+ SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
+ return 0;
+
+ case WM_NCCALCSIZE:// don't let windows copy pixels
+ DefWindowProc (hWnd, uMsg, wParam, lParam);
+ return WVR_REDRAW;
+
+ case WM_CLOSE:
+ DestroyWindow (hWnd);
+ return 0;
+
+ case WM_DESTROY:
+ QEW_StopGL( hWnd, g_qeglobals.d_hglrcBase, g_qeglobals.d_hdcBase );
+ return 0;
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+/*
+==============
+WCam_Create
+==============
+*/
+void WCam_Create (HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+ char *title;
+
+ /* Register the camera class */
+ memset (&wc, 0, sizeof(wc));
+
+ wc.style = CS_NOCLOSE;
+ wc.lpfnWndProc = (WNDPROC)WCam_WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = 0;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = CAMERA_WINDOW_CLASS;
+
+ if (!RegisterClass (&wc) )
+ Error ("WCam_Register: failed");
+
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL )
+ title = "Camera View (DETAIL EXCLUDED)";
+ else
+ title = "Camera View";
+
+ g_qeglobals.d_hwndCamera = CreateWindow (CAMERA_WINDOW_CLASS ,
+ title,
+ QE3_STYLE,
+ ZWIN_WIDTH,
+ 20,
+ (int)(screen_width*CWIN_SIZE),
+ (int)(screen_height*CWIN_SIZE), // size
+
+ g_qeglobals.d_hwndMain, // parent window
+ 0, // no menu
+ hInstance,
+ 0);
+
+ if (!g_qeglobals.d_hwndCamera)
+ Error ("Couldn't create g_qeglobals.d_hwndCamera");
+
+ LoadWindowState(g_qeglobals.d_hwndCamera, "camerawindow");
+ ShowWindow (g_qeglobals.d_hwndCamera, SW_SHOWDEFAULT);
+}
diff --git a/q3radiant/WIN_DLG.CPP b/q3radiant/WIN_DLG.CPP
new file mode 100755
index 0000000..5095de2
--- /dev/null
+++ b/q3radiant/WIN_DLG.CPP
@@ -0,0 +1,616 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+#include "PrefsDlg.h"
+
+BOOL CALLBACK EditCommandDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char key[1024];
+ char value[1024];
+ char *temp;
+ int index;
+ HWND hOwner;
+
+ hOwner = GetParent (hwndDlg);
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ index = SendDlgItemMessage (hOwner, IDC_CMD_LIST, LB_GETCURSEL, 0, 0);
+ if (index >= 0)
+ {
+ SendDlgItemMessage(hOwner, IDC_CMD_LIST, LB_GETTEXT, index, (LPARAM) (LPCTSTR) key);
+ temp = ValueForKey (g_qeglobals.d_project_entity, key);
+ strcpy (value, temp);
+ SetDlgItemText(hwndDlg, IDC_CMDMENUTEXT, key);
+ SetDlgItemText(hwndDlg, IDC_CMDCOMMAND, value);
+ }
+ return FALSE;
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ if (!GetDlgItemText(hwndDlg, IDC_CMDMENUTEXT, key, 64))
+ {
+ Sys_Printf ("Command not added\n");
+ return FALSE;
+ }
+
+ if (!GetDlgItemText(hwndDlg, IDC_CMDCOMMAND, value, 64))
+ {
+ Sys_Printf ("Command not added\n");
+ return FALSE;
+ }
+
+ //if (key[0] == 'b' && key[1] == 's' && key[2] == 'p')
+ //{
+ SetKeyValue (g_qeglobals.d_project_entity, key, value);
+ FillBSPMenu ();
+ //}
+ //else
+ // Sys_Printf ("BSP commands must be preceded by \"bsp\"");
+
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOL CALLBACK AddCommandDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char key[64];
+ char value[128];
+
+ switch (uMsg)
+ {
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ if (!GetDlgItemText(hwndDlg, IDC_CMDMENUTEXT, key, 64))
+ {
+ Sys_Printf ("Command not added\n");
+ return FALSE;
+ }
+
+ if (!GetDlgItemText(hwndDlg, IDC_CMDCOMMAND, value, 64))
+ {
+ Sys_Printf ("Command not added\n");
+ return FALSE;
+ }
+
+ if (key[0] == 'b' && key[1] == 's' && key[2] == 'p')
+ {
+ SetKeyValue (g_qeglobals.d_project_entity, key, value);
+ FillBSPMenu ();
+ }
+ else
+ Sys_Printf ("BSP commands must be preceded by \"bsp\"");
+
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void UpdateBSPCommandList (HWND hwndDlg)
+{
+ int i;
+ epair_t *ep;
+
+ SendDlgItemMessage(hwndDlg, IDC_CMD_LIST, LB_RESETCONTENT, 0 , 0);
+
+ i = 0;
+ for (ep = g_qeglobals.d_project_entity->epairs ; ep ; ep=ep->next)
+ {
+ if (ep->key[0] == 'b' && ep->key[1] == 's' && ep->key[2] == 'p')
+ {
+ SendDlgItemMessage(hwndDlg, IDC_CMD_LIST, LB_ADDSTRING, i , (LPARAM) ep->key);
+ i++;
+ }
+ }
+}
+
+
+// FIXME: turn this into an MFC dialog
+BOOL CALLBACK ProjectDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char key[1024];
+ char value[1024];
+ int index;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ SetDlgItemText(hwndDlg, IDC_PRJBASEPATH, ValueForKey (g_qeglobals.d_project_entity, "basepath"));
+ SetDlgItemText(hwndDlg, IDC_PRJMAPSPATH, ValueForKey (g_qeglobals.d_project_entity, "mapspath"));
+ SetDlgItemText(hwndDlg, IDC_PRJRSHCMD, ValueForKey (g_qeglobals.d_project_entity, "rshcmd"));
+ SetDlgItemText(hwndDlg, IDC_PRJREMOTEBASE, ValueForKey (g_qeglobals.d_project_entity, "remotebasepath"));
+ SetDlgItemText(hwndDlg, IDC_PRJENTITYPATH, ValueForKey (g_qeglobals.d_project_entity, "entitypath"));
+ SetDlgItemText(hwndDlg, IDC_PRJTEXPATH, ValueForKey (g_qeglobals.d_project_entity, "texturepath"));
+ UpdateBSPCommandList (hwndDlg);
+ // Timo
+ // additional fields
+ CheckDlgButton( hwndDlg, IDC_CHECK_BPRIMIT, (g_qeglobals.m_bBrushPrimitMode) ? BST_CHECKED : BST_UNCHECKED );
+// SendMessage( ::GetDlgItem( hwndDlg, IDC_CHECK_BPRIMIT ), BM_SETCHECK, (WPARAM) g_qeglobals.m_bBrushPrimitMode, 0 );
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDC_ADDCMD:
+// DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, g_qeglobals.d_hwndMain, AddCommandDlgProc);
+ DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, hwndDlg, AddCommandDlgProc);
+ UpdateBSPCommandList (hwndDlg);
+ break;
+
+ case IDC_EDITCMD:
+// DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, g_qeglobals.d_hwndMain, EditCommandDlgProc);
+ DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ADDCMD, hwndDlg, EditCommandDlgProc);
+ UpdateBSPCommandList (hwndDlg);
+ break;
+
+ case IDC_REMCMD:
+ index = SendDlgItemMessage (hwndDlg, IDC_CMD_LIST, LB_GETCURSEL, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_CMD_LIST, LB_GETTEXT, index, (LPARAM) (LPCTSTR) key);
+ DeleteKey (g_qeglobals.d_project_entity, key);
+ Sys_Printf ("Selected %d\n", index);
+ UpdateBSPCommandList (hwndDlg);
+ break;
+
+ case IDOK:
+ GetDlgItemText(hwndDlg, IDC_PRJBASEPATH, value, 1024);
+ SetKeyValue (g_qeglobals.d_project_entity, "basepath", value);
+ GetDlgItemText(hwndDlg, IDC_PRJMAPSPATH, value, 1024);
+ SetKeyValue (g_qeglobals.d_project_entity, "mapspath", value);
+ GetDlgItemText(hwndDlg, IDC_PRJRSHCMD, value, 1024);
+ SetKeyValue (g_qeglobals.d_project_entity, "rshcmd", value);
+ GetDlgItemText(hwndDlg, IDC_PRJREMOTEBASE, value, 1024);
+ SetKeyValue (g_qeglobals.d_project_entity, "remotebasepath", value);
+ GetDlgItemText(hwndDlg, IDC_PRJENTITYPATH, value, 1024);
+ SetKeyValue (g_qeglobals.d_project_entity, "entitypath", value);
+ GetDlgItemText(hwndDlg, IDC_PRJTEXPATH, value, 1024);
+ SetKeyValue (g_qeglobals.d_project_entity, "texturepath", value);
+ // Timo
+ // read additional fields
+ if ( IsDlgButtonChecked( hwndDlg, IDC_CHECK_BPRIMIT ) )
+ {
+ g_qeglobals.m_bBrushPrimitMode = TRUE;
+ }
+ else
+ {
+ g_qeglobals.m_bBrushPrimitMode = FALSE;
+ }
+ SetKeyValue ( g_qeglobals.d_project_entity, "brush_primit", ( g_qeglobals.m_bBrushPrimitMode ? "1" : "0" ) );
+
+ EndDialog(hwndDlg, 1);
+ QE_SaveProject(g_strProject);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+void DoProjectSettings()
+{
+ DialogBox(g_qeglobals.d_hInstance, (char *)IDD_PROJECT, g_qeglobals.d_hwndMain, ProjectDlgProc);
+}
+
+
+
+BOOL CALLBACK GammaDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char sz[256];
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ sprintf(sz, "%1.1f", g_qeglobals.d_savedinfo.fGamma);
+ SetWindowText(GetDlgItem(hwndDlg, IDC_G_EDIT), sz);
+ return TRUE;
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+
+ case IDOK:
+ GetWindowText(GetDlgItem(hwndDlg, IDC_G_EDIT), sz, 255);
+ g_qeglobals.d_savedinfo.fGamma = atof(sz);
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+void DoGamma(void)
+{
+ if ( DialogBox(g_qeglobals.d_hInstance, (char *)IDD_GAMMA, g_qeglobals.d_hwndMain, GammaDlgProc))
+ {
+ }
+}
+
+//================================================
+
+
+void SelectBrush (int entitynum, int brushnum)
+{
+ entity_t *e;
+ brush_t *b;
+ int i;
+
+ if (entitynum == 0)
+ e = world_entity;
+ else
+ {
+ e = entities.next;
+ while (--entitynum)
+ {
+ e=e->next;
+ if (e == &entities)
+ {
+ Sys_Status ("No such entity.", 0);
+ return;
+ }
+ }
+ }
+
+ b = e->brushes.onext;
+ if (b == &e->brushes)
+ {
+ Sys_Status ("No such brush.", 0);
+ return;
+ }
+ while (brushnum--)
+ {
+ b=b->onext;
+ if (b == &e->brushes)
+ {
+ Sys_Status ("No such brush.", 0);
+ return;
+ }
+ }
+
+ Brush_RemoveFromList (b);
+ Brush_AddToList (b, &selected_brushes);
+
+
+ Sys_UpdateWindows (W_ALL);
+ for (i=0 ; i<3 ; i++)
+ {
+ if (g_pParentWnd->GetXYWnd())
+ g_pParentWnd->GetXYWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
+
+ if (g_pParentWnd->GetXZWnd())
+ g_pParentWnd->GetXZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
+
+ if (g_pParentWnd->GetYZWnd())
+ g_pParentWnd->GetYZWnd()->GetOrigin()[i] = (b->mins[i] + b->maxs[i])/2;
+ }
+
+ Sys_Status ("Selected.", 0);
+}
+
+/*
+=================
+GetSelectionIndex
+=================
+*/
+void GetSelectionIndex (int *ent, int *brush)
+{
+ brush_t *b, *b2;
+ entity_t *entity;
+
+ *ent = *brush = 0;
+
+ b = selected_brushes.next;
+ if (b == &selected_brushes)
+ return;
+
+ // find entity
+ if (b->owner != world_entity)
+ {
+ (*ent)++;
+ for (entity = entities.next ; entity != &entities
+ ; entity=entity->next, (*ent)++)
+ ;
+ }
+
+ // find brush
+ for (b2=b->owner->brushes.onext
+ ; b2 != b && b2 != &b->owner->brushes
+ ; b2=b2->onext, (*brush)++)
+ ;
+}
+
+BOOL CALLBACK FindBrushDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char entstr[256];
+ char brushstr[256];
+ HWND h;
+ int ent, brush;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ // set entity and brush number
+ GetSelectionIndex (&ent, &brush);
+ sprintf (entstr, "%i", ent);
+ sprintf (brushstr, "%i", brush);
+ SetWindowText(GetDlgItem(hwndDlg, IDC_FIND_ENTITY), entstr);
+ SetWindowText(GetDlgItem(hwndDlg, IDC_FIND_BRUSH), brushstr);
+
+ h = GetDlgItem(hwndDlg, IDC_FIND_ENTITY);
+ SetFocus (h);
+ return FALSE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ GetWindowText(GetDlgItem(hwndDlg, IDC_FIND_ENTITY), entstr, 255);
+ GetWindowText(GetDlgItem(hwndDlg, IDC_FIND_BRUSH), brushstr, 255);
+ SelectBrush (atoi(entstr), atoi(brushstr));
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+void DoFind(void)
+{
+ DialogBox(g_qeglobals.d_hInstance, (char *)IDD_FINDBRUSH, g_qeglobals.d_hwndMain, FindBrushDlgProc);
+}
+
+/*
+===================================================
+
+ ARBITRARY ROTATE
+
+===================================================
+*/
+
+
+BOOL CALLBACK RotateDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char str[256];
+ HWND h;
+ float v;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ h = GetDlgItem(hwndDlg, IDC_FIND_ENTITY);
+ SetFocus (h);
+ return FALSE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+
+ case IDOK:
+ GetWindowText(GetDlgItem(hwndDlg, IDC_ROTX), str, 255);
+ v = atof(str);
+ if (v)
+ Select_RotateAxis (0, v);
+
+ GetWindowText(GetDlgItem(hwndDlg, IDC_ROTY), str, 255);
+ v = atof(str);
+ if (v)
+ Select_RotateAxis (1, v);
+
+ GetWindowText(GetDlgItem(hwndDlg, IDC_ROTZ), str, 255);
+ v = atof(str);
+ if (v)
+ Select_RotateAxis (2, v);
+
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+void DoRotate(void)
+{
+ DialogBox(g_qeglobals.d_hInstance, (char *)IDD_ROTATE, g_qeglobals.d_hwndMain, RotateDlgProc);
+}
+
+/*
+===================================================
+
+ ARBITRARY SIDES
+
+===================================================
+*/
+
+bool g_bDoCone = false;
+bool g_bDoSphere = false;
+BOOL CALLBACK SidesDlgProc (
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam // second message parameter
+ )
+{
+ char str[256];
+ HWND h;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ h = GetDlgItem(hwndDlg, IDC_SIDES);
+ SetFocus (h);
+ return FALSE;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+
+ case IDOK:
+ GetWindowText(GetDlgItem(hwndDlg, IDC_SIDES), str, 255);
+ if (g_bDoCone)
+ Brush_MakeSidedCone(atoi(str));
+ else if (g_bDoSphere)
+ Brush_MakeSidedSphere(atoi(str));
+ else
+ Brush_MakeSided (atoi(str));
+
+ EndDialog(hwndDlg, 1);
+ break;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ break;
+ }
+ default:
+ return FALSE;
+ }
+}
+
+
+void DoSides(bool bCone, bool bSphere, bool bTorus)
+{
+ g_bDoCone = bCone;
+ g_bDoSphere = bSphere;
+ //g_bDoTorus = bTorus;
+ DialogBox(g_qeglobals.d_hInstance, (char *)IDD_SIDES, g_qeglobals.d_hwndMain, SidesDlgProc);
+}
+
+
+//======================================================================
+
+/*
+===================
+DoAbout
+===================
+*/
+BOOL CALLBACK AboutDlgProc( HWND hwndDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam )
+{
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ char renderer[1024];
+ char version[1024];
+ char vendor[1024];
+ char extensions[4096];
+
+ sprintf( renderer, "Renderer:\t%s", qglGetString( GL_RENDERER ) );
+ sprintf( version, "Version:\t\t%s", qglGetString( GL_VERSION ) );
+ sprintf( vendor, "Vendor:\t\t%s", qglGetString( GL_VENDOR ) );
+ sprintf( extensions, "%s", qglGetString( GL_EXTENSIONS ) );
+
+ SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLRENDERER ), renderer );
+ SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLVERSION ), version );
+ SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLVENDOR ), vendor );
+ SetWindowText( GetDlgItem( hwndDlg, IDC_ABOUT_GLEXTENSIONS ), extensions );
+
+ }
+ return TRUE;
+
+ case WM_CLOSE:
+ EndDialog( hwndDlg, 1 );
+ return TRUE;
+
+ case WM_COMMAND:
+ if ( LOWORD( wParam ) == IDOK )
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void DoAbout(void)
+{
+ DialogBox( g_qeglobals.d_hInstance, ( char * ) IDD_ABOUT, g_qeglobals.d_hwndMain, AboutDlgProc );
+}
+
+
diff --git a/q3radiant/WIN_QE3.CPP b/q3radiant/WIN_QE3.CPP
new file mode 100755
index 0000000..86cad56
--- /dev/null
+++ b/q3radiant/WIN_QE3.CPP
@@ -0,0 +1,753 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+#include "mru.h"
+#include "PrefsDlg.h"
+
+////////////////////////////////////////////////////////////////////////////
+// BSP frontend plugin
+// global flag for BSP frontend plugin is g_qeglobals.bBSPFrontendPlugin
+_QERPlugBSPFrontendTable g_BSPFrontendTable;
+CStringArray g_BSPFrontendCommands;
+
+extern CEdit* g_pEdit;
+
+int screen_width;
+int screen_height;
+qboolean have_quit;
+
+int update_bits;
+
+HANDLE bsp_process;
+
+//===========================================
+
+void Sys_MarkMapModified (void)
+{
+ char title[1024];
+
+ if (modified != 1)
+ {
+ modified = true; // mark the map as changed
+ sprintf (title, "%s *", currentmap);
+
+ QE_ConvertDOSToUnixName( title, title );
+ Sys_SetTitle (title);
+ }
+}
+
+
+void Sys_SetTitle (char *text)
+{
+ SetWindowText (g_qeglobals.d_hwndMain, text);
+}
+
+HCURSOR waitcursor;
+
+void Sys_BeginWait (void)
+{
+ waitcursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
+}
+
+void Sys_EndWait (void)
+{
+ if (waitcursor)
+ {
+ SetCursor (waitcursor);
+ waitcursor = NULL;
+ }
+}
+
+
+void Sys_GetCursorPos (int *x, int *y)
+{
+ POINT lpPoint;
+
+ GetCursorPos (&lpPoint);
+ *x = lpPoint.x;
+ *y = lpPoint.y;
+}
+
+void Sys_SetCursorPos (int x, int y)
+{
+ SetCursorPos (x, y);
+}
+
+
+void Sys_Beep (void)
+{
+ MessageBeep (MB_ICONASTERISK);
+}
+
+char *TranslateString (char *buf)
+{
+ static char buf2[32768];
+ int i, l;
+ char *out;
+
+ l = strlen(buf);
+ out = buf2;
+ for (i=0 ; i<l ; i++)
+ {
+ if (buf[i] == '\n')
+ {
+ *out++ = '\r';
+ *out++ = '\n';
+ }
+ else
+ *out++ = buf[i];
+ }
+ *out++ = 0;
+
+ return buf2;
+}
+
+
+void Sys_ClearPrintf (void)
+{
+ char text[4];
+ text[0] = 0;
+
+ SendMessage (g_qeglobals.d_hwndEdit, WM_SETTEXT, 0, (LPARAM)text);
+}
+
+
+#define SCROLLBACK_MAX_LINES 600
+#define SCROLLBACK_DEL_CHARS 500
+
+void Sys_Printf (char *text, ...)
+{
+ va_list argptr;
+ char buf[32768];
+ char *out;
+ LRESULT result; // PGM
+ DWORD oldPosS, oldPosE; // PGM
+
+ va_start (argptr,text);
+ vsprintf (buf, text,argptr);
+ va_end (argptr);
+
+ out = TranslateString (buf);
+
+#ifdef LATER
+ Sys_Status(out);
+#else
+//PGM
+ result = SendMessage (g_qeglobals.d_hwndEdit, EM_GETLINECOUNT, 0, 0);
+ if(result > SCROLLBACK_MAX_LINES)
+ {
+ char replaceText[5];
+
+ replaceText[0] = '\0';
+
+ SendMessage (g_qeglobals.d_hwndEdit, WM_SETREDRAW, (WPARAM)0, (LPARAM)0);
+ SendMessage (g_qeglobals.d_hwndEdit, EM_GETSEL, (WPARAM)&oldPosS, (LPARAM)&oldPosE);
+ SendMessage (g_qeglobals.d_hwndEdit, EM_SETSEL, 0, SCROLLBACK_DEL_CHARS);
+ SendMessage (g_qeglobals.d_hwndEdit, EM_REPLACESEL, (WPARAM)0, (LPARAM)replaceText);
+ SendMessage (g_qeglobals.d_hwndEdit, EM_SETSEL, oldPosS, oldPosE);
+ SendMessage (g_qeglobals.d_hwndEdit, WM_SETREDRAW, (WPARAM)1, (LPARAM)0);
+ }
+//PGM
+
+ SendMessage (g_qeglobals.d_hwndEdit, EM_REPLACESEL, 0, (LPARAM)out);
+#endif
+
+}
+
+
+double Sys_DoubleTime (void)
+{
+ return clock()/ 1000.0;
+}
+
+void PrintPixels (HDC hDC)
+{
+ int i;
+ PIXELFORMATDESCRIPTOR p[64];
+
+ printf ("### flags color layer\n");
+ for (i=1 ; i<64 ; i++)
+ {
+ if (!DescribePixelFormat ( hDC, i, sizeof(p[0]), &p[i]))
+ break;
+ printf ("%3i %5i %5i %5i\n", i,
+ p[i].dwFlags,
+ p[i].cColorBits,
+ p[i].bReserved);
+ }
+ printf ("%i modes\n", i-1);
+}
+
+
+
+//==========================================================================
+
+void QEW_StopGL( HWND hWnd, HGLRC hGLRC, HDC hDC )
+{
+ qwglMakeCurrent( NULL, NULL );
+ qwglDeleteContext( hGLRC );
+ ReleaseDC( hWnd, hDC );
+}
+
+int WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer )
+{
+ static PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
+ 1, // version number
+ PFD_DRAW_TO_WINDOW | // support window
+ PFD_SUPPORT_OPENGL | // support OpenGL
+ PFD_DOUBLEBUFFER, // double buffered
+ PFD_TYPE_RGBA, // RGBA type
+ 24, // 24-bit color depth
+ 0, 0, 0, 0, 0, 0, // color bits ignored
+ 0, // no alpha buffer
+ 0, // shift bit ignored
+ 0, // no accumulation buffer
+ 0, 0, 0, 0, // accum bits ignored
+ 32, // depth bits
+ 0, // no stencil buffer
+ 0, // no auxiliary buffer
+ PFD_MAIN_PLANE, // main layer
+ 0, // reserved
+ 0, 0, 0 // layer masks ignored
+ }; //
+ int pixelformat = 0;
+
+ zbuffer = true;
+ if ( !zbuffer )
+ pfd.cDepthBits = 0;
+
+ if (g_PrefsDlg.m_bSGIOpenGL)
+ {
+ if ( (pixelformat = qwglChoosePixelFormat(hDC, &pfd)) == 0 )
+ {
+ printf("%d",GetLastError());
+ Error ("ChoosePixelFormat failed");
+ }
+
+ if (!qwglSetPixelFormat(hDC, pixelformat, &pfd))
+ Error ("SetPixelFormat failed");
+ }
+ else
+ {
+ if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 )
+ {
+ printf("%d",GetLastError());
+ Error ("ChoosePixelFormat failed");
+ }
+
+ if (!SetPixelFormat(hDC, pixelformat, &pfd))
+ Error ("SetPixelFormat failed");
+ }
+
+ return pixelformat;
+}
+
+/*
+=================
+Error
+
+For abnormal program terminations
+=================
+*/
+void Error (char *error, ...)
+{
+ va_list argptr;
+ char text[1024];
+ char text2[1024];
+ int err;
+
+ err = GetLastError ();
+ int i = qglGetError();
+
+ va_start (argptr,error);
+ vsprintf (text, error,argptr);
+ va_end (argptr);
+
+ sprintf (text2, "%s\nGetLastError() = %i - %i\nAn unrecoverable error has occured. Would you like to edit Preferences before exiting Q3Radiant?", text, err, i);
+
+ if (MessageBox(g_qeglobals.d_hwndMain, text2, "Error", MB_YESNO) == IDYES)
+ {
+ g_PrefsDlg.LoadPrefs();
+ g_PrefsDlg.DoModal();
+ }
+
+ exit (1);
+}
+
+
+void Warning (char *error, ...)
+{
+ va_list argptr;
+ char text[1024];
+ int err;
+
+ err = GetLastError ();
+ int i = qglGetError();
+
+ va_start (argptr,error);
+ vsprintf (text, error,argptr);
+ va_end (argptr);
+
+ Sys_Printf(text);
+}
+
+
+/*
+======================================================================
+
+FILE DIALOGS
+
+======================================================================
+*/
+
+qboolean ConfirmModified (void)
+{
+ if (!modified)
+ return true;
+
+ if (MessageBox (g_qeglobals.d_hwndMain, "This will lose changes to the map"
+ , "warning", MB_OKCANCEL) == IDCANCEL)
+ return false;
+ return true;
+}
+
+static OPENFILENAME ofn; /* common dialog box structure */
+static char szDirName[MAX_PATH]; /* directory string */
+static char szFile[260]; /* filename string */
+static char szFileTitle[260]; /* file title string */
+static char szFilter[260] = /* filter string */
+ "Map file (*.map, *.reg)\0*.map\0*.reg\0\0";
+static char szProjectFilter[260] = /* filter string */
+ "Q3Radiant project (*.qe4, *.prj)\0*.qe4\0*.prj\0\0";
+static char chReplace; /* string separator for szFilter */
+static int i, cbString; /* integer count variables */
+static HANDLE hf; /* file handle */
+
+void OpenDialog (void)
+{
+ /*
+ * Obtain the system directory name and
+ * store it in szDirName.
+ */
+
+ strcpy (szDirName, ValueForKey (g_qeglobals.d_project_entity, "mapspath") );
+ if (strlen(szDirName) == 0)
+ {
+ strcpy (szDirName, ValueForKey (g_qeglobals.d_project_entity, "basepath") );
+ strcat (szDirName, "\\maps");
+ }
+
+ /* Place the terminating null character in the szFile. */
+
+ szFile[0] = '\0';
+
+ /* Set the members of the OPENFILENAME structure. */
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = g_qeglobals.d_hwndCamera;
+ ofn.lpstrFilter = szFilter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = sizeof(szFileTitle);
+ ofn.lpstrInitialDir = szDirName;
+ ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST |
+ OFN_FILEMUSTEXIST;
+
+ /* Display the Open dialog box. */
+
+ if (!GetOpenFileName(&ofn))
+ return; // canceled
+
+ // Add the file in MRU.
+ //FIXME
+ AddNewItem( g_qeglobals.d_lpMruMenu, ofn.lpstrFile);
+
+ // Refresh the File menu.
+ //FIXME
+ PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(g_qeglobals.d_hwndMain),0),
+ ID_FILE_EXIT);
+
+ /* Open the file. */
+
+ Map_LoadFile (ofn.lpstrFile);
+}
+
+void ProjectDialog (void)
+{
+ /*
+ * Obtain the system directory name and
+ * store it in szDirName.
+ */
+
+ strcpy (szDirName, ValueForKey(g_qeglobals.d_project_entity, "basepath") );
+ strcat (szDirName, "\\scripts");
+
+ /* Place the terminating null character in the szFile. */
+
+ szFile[0] = '\0';
+
+ /* Set the members of the OPENFILENAME structure. */
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = g_qeglobals.d_hwndCamera;
+ ofn.lpstrFilter = szProjectFilter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = sizeof(szFileTitle);
+ ofn.lpstrInitialDir = szDirName;
+ ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST |
+ OFN_FILEMUSTEXIST;
+
+ /* Display the Open dialog box. */
+
+ if (!GetOpenFileName(&ofn))
+ return; // canceled
+
+ // Refresh the File menu.
+ PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(g_qeglobals.d_hwndMain),0),
+ ID_FILE_EXIT);
+
+ /* Open the file. */
+ if (!QE_LoadProject(ofn.lpstrFile))
+ Error ("Couldn't load project file");
+}
+
+
+extern void AddSlash(CString& strPath);
+void SaveAsDialog (bool bRegion)
+{
+ strcpy (szDirName, ValueForKey (g_qeglobals.d_project_entity, "basepath") );
+ CString strPath = szDirName;
+ AddSlash(strPath);
+ strPath += "maps";
+
+ /* Place the terminating null character in the szFile. */
+
+ szFile[0] = '\0';
+
+ /* Set the members of the OPENFILENAME structure. */
+
+ ofn.lStructSize = sizeof(OPENFILENAME);
+ ofn.hwndOwner = g_qeglobals.d_hwndCamera;
+ ofn.lpstrFilter = szFilter;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrFileTitle = szFileTitle;
+ ofn.nMaxFileTitle = sizeof(szFileTitle);
+ ofn.lpstrInitialDir = strPath;
+ ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST |
+ OFN_FILEMUSTEXIST | OFN_OVERWRITEPROMPT;
+
+ /* Display the Open dialog box. */
+
+ if (!GetSaveFileName(&ofn))
+ return; // canceled
+
+ if (bRegion)
+ DefaultExtension (ofn.lpstrFile, ".reg");
+ else
+ DefaultExtension (ofn.lpstrFile, ".map");
+
+ if (!bRegion)
+ {
+ strcpy (currentmap, ofn.lpstrFile);
+ AddNewItem(g_qeglobals.d_lpMruMenu, ofn.lpstrFile);
+ PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(g_qeglobals.d_hwndMain),0), ID_FILE_EXIT);
+ }
+ Map_SaveFile (ofn.lpstrFile, bRegion); // ignore region
+}
+
+/*
+=======================================================
+
+Menu modifications
+
+=======================================================
+*/
+
+/*
+==================
+FillBSPMenu
+
+==================
+*/
+char *bsp_commands[256];
+
+void FillBSPMenu (void)
+{
+ HMENU hmenu;
+ epair_t *ep;
+ int i;
+ static int count;
+
+ hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_BSP);
+
+ for (i=0 ; i<count ; i++)
+ DeleteMenu (hmenu, CMD_BSPCOMMAND+i, MF_BYCOMMAND);
+ count = 0;
+
+ if ( g_qeglobals.bBSPFrontendPlugin )
+ {
+ CString str = g_BSPFrontendTable.m_pfnGetBSPMenu();
+ char cTemp[1024];
+ strcpy(cTemp, str);
+ char* token = strtok(cTemp, ",;");
+ if (token && *token == ' ')
+ {
+ while (*token == ' ')
+ token++;
+ }
+ i = 0;
+ // first token is menu name
+ ModifyMenu( GetMenu(g_qeglobals.d_hwndMain), MENU_BSP, MF_BYPOSITION, MENU_BSP, (LPCTSTR)token );
+ // redraw the menu bar
+ DrawMenuBar( g_qeglobals.d_hwndMain );
+ token = strtok(NULL, ",;");
+ while (token != NULL)
+ {
+ g_BSPFrontendCommands.Add(token);
+ AppendMenu (hmenu, MF_ENABLED|MF_STRING, CMD_BSPCOMMAND+i, (LPCTSTR)token );
+ token = strtok(NULL, ",;");
+ i++;
+ }
+ count = i;
+ }
+ else
+ {
+ i = 0;
+ for (ep = g_qeglobals.d_project_entity->epairs ; ep ; ep=ep->next)
+ {
+ if (ep->key[0] == 'b' && ep->key[1] == 's' && ep->key[2] == 'p')
+ {
+ bsp_commands[i] = ep->key;
+ AppendMenu (hmenu, MF_ENABLED|MF_STRING,
+ CMD_BSPCOMMAND+i, (LPCTSTR)ep->key);
+ i++;
+ }
+ }
+ count = i;
+ }
+}
+
+//==============================================
+void AddSlash(CString& strPath)
+{
+ if (strPath.GetLength() > 0)
+ {
+ if (strPath.GetAt(strPath.GetLength()-1) != '\\')
+ strPath += '\\';
+ }
+}
+
+
+bool ExtractPath_and_Filename(const char* pPath, CString& strPath, CString& strFilename)
+{
+ CString strPathName = pPath;
+ int nSlash = strPathName.ReverseFind('\\');
+ if (nSlash >= 0)
+ {
+ strPath = strPathName.Left(nSlash+1);
+ strFilename = strPathName.Right(strPathName.GetLength() - nSlash - 1);
+ }
+ else strFilename = pPath;
+ return true;
+}
+
+
+/*
+===============
+CheckBspProcess
+
+See if the BSP is done yet
+===============
+*/
+extern void FindReplace(CString& strContents, const char* pTag, const char* pValue);
+extern CTime g_tBegin;
+
+void CheckBspProcess (void)
+{
+ char outputpath[1024];
+ char temppath[512];
+ DWORD exitcode;
+ char *out;
+ BOOL ret;
+
+ if (!bsp_process)
+ return;
+
+ ret = GetExitCodeProcess (bsp_process, &exitcode);
+ if (!ret)
+ Error ("GetExitCodeProcess failed");
+ if (exitcode == STILL_ACTIVE)
+ return;
+
+ bsp_process = 0;
+
+ GetTempPath(512, temppath);
+ sprintf (outputpath, "%sjunk.txt", temppath);
+
+ LoadFile (outputpath, (void **)&out);
+ Sys_Printf ("%s", out);
+ Sys_Printf ("\ncompleted.\n");
+ free (out);
+
+ CTime tEnd = CTime::GetCurrentTime();
+ CTimeSpan tElapsed = tEnd - g_tBegin;
+ CString strElapsed;
+ strElapsed.Format("Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds());
+ Sys_Printf(strElapsed.GetBuffer(0));
+
+
+ Sys_Beep ();
+ Pointfile_Check();
+ // run game if no PointFile and pref is set
+ //++timo needs to stop after BSP if leaked .. does run through vis and light instead ..
+ if (g_PrefsDlg.m_bRunQuake == TRUE && !g_qeglobals.d_pointfile_display_list)
+ {
+ char cCurDir[1024];
+ GetCurrentDirectory(1024, cCurDir);
+ CString strExePath = g_PrefsDlg.m_strQuake2;
+ CString strOrgPath;
+ CString strOrgFile;
+ ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
+ if (g_PrefsDlg.m_bSetGame == TRUE) // run in place with set game.. don't copy map
+ {
+ CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ strExePath += " +set game ";
+ strExePath += strBasePath;
+ WinExec(strExePath, SW_SHOW);
+ }
+ else
+ {
+ CString strCopyPath = strExePath;
+ char* pBuffer = strCopyPath.GetBufferSetLength(_MAX_PATH + 1);
+ pBuffer[strCopyPath.ReverseFind('\\') + 1] = '\0';
+ strCopyPath.ReleaseBuffer();
+ SetCurrentDirectory(strCopyPath);
+ CString strOrgPath;
+ CString strOrgFile;
+ ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
+ AddSlash(strCopyPath);
+ FindReplace(strOrgFile, ".map", ".bsp");
+ //++timo modified for Quake3 !!
+ strCopyPath += "baseq3\\maps\\";
+ strCopyPath += strOrgFile;
+ AddSlash(strOrgPath);
+ strOrgPath += strOrgFile;
+ bool bRun = (strOrgPath.CompareNoCase(strCopyPath) == 0);
+ if (!bRun)
+ bRun = (CopyFile(strOrgPath, strCopyPath, FALSE) == TRUE);
+ if (bRun)
+ {
+ FindReplace(strOrgFile, ".bsp", "");
+ strExePath += " +map ";
+ strExePath += strOrgFile;
+ WinExec(strExePath, SW_SHOW);
+ }
+ }
+ SetCurrentDirectory(cCurDir);
+ }
+}
+
+extern int cambuttonstate;
+
+extern "C" {
+void *Com_Allocate( int bytes ) {
+ return malloc(bytes);
+}
+
+void Com_Dealloc( void *ptr ) {
+ free(ptr);
+}
+
+
+void Com_Printf( const char *msg, ... ) {
+ va_list argptr;
+ char buf[32768];
+ char *out;
+
+ va_start (argptr,msg);
+ vsprintf (buf, msg,argptr);
+ va_end (argptr);
+
+ out = TranslateString (buf);
+
+ Sys_Printf(buf);
+}
+
+void Com_Error( int level, const char *error, ... ) {
+ va_list argptr;
+ char buf[32768];
+ char *out;
+
+ va_start (argptr,error);
+ vsprintf (buf, error,argptr);
+ va_end (argptr);
+
+ out = TranslateString (buf);
+
+ Sys_Printf(buf);
+}
+
+void Com_DPrintf( const char *msg, ... ) {
+ return;
+}
+
+int FS_Write( const void *buffer, int len, fileHandle_t h ) {
+ SafeWrite(reinterpret_cast<FILE*>(h), buffer, len);
+ return len;
+}
+
+int FS_ReadFile( const char *qpath, void **buffer ) {
+ CString strPath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ AddSlash(strPath);
+ strPath += qpath;
+ return LoadFile(strPath, buffer);
+}
+
+void FS_FreeFile( void *buffer ) {
+ Com_Dealloc(buffer);
+}
+
+fileHandle_t FS_FOpenFileWrite( const char *filename ) {
+ CString strPath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ AddSlash(strPath);
+ strPath += filename;
+ // bad casting ptr to int
+ return reinterpret_cast<fileHandle_t>(SafeOpenWrite(strPath));
+}
+
+void FS_FCloseFile( fileHandle_t f ) {
+ fclose(reinterpret_cast<FILE*>(f));
+}
+
+
+
+}
+
diff --git a/q3radiant/WIN_QE3.RC2 b/q3radiant/WIN_QE3.RC2
new file mode 100755
index 0000000..2adb8fd
--- /dev/null
+++ b/q3radiant/WIN_QE3.RC2
@@ -0,0 +1,693 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU DISCARDABLE
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New", ID_FILE_NEW
+ MENUITEM "&Open", ID_FILE_OPEN
+ MENUITEM "&Save", ID_FILE_SAVE
+ MENUITEM "Save &as...", ID_FILE_SAVEAS
+ MENUITEM "&Pointfile", ID_FILE_POINTFILE
+ MENUITEM "Load &project", ID_FILE_LOADPROJECT
+ MENUITEM "E&xit", ID_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "&Copy brush", ID_EDIT_COPYBRUSH, GRAYED
+ MENUITEM "&Paste brush", ID_EDIT_PASTEBRUSH, GRAYED
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "Texture View\tT", ID_VIEW_TEXTURE
+ MENUITEM "Console View\tO", ID_VIEW_CONSOLE
+ MENUITEM "Entity View\tN", ID_VIEW_ENTITY
+ MENUITEM SEPARATOR
+ MENUITEM "&Center\tEnd", ID_VIEW_CENTER
+ MENUITEM "&Up Floor\tPage Up", ID_VIEW_UPFLOOR
+ MENUITEM "&Down Floor\tPage Down", ID_VIEW_DOWNFLOOR
+ MENUITEM SEPARATOR
+ MENUITEM "&XY 100%", ID_VIEW_100
+ MENUITEM "XY Zoom &In\tDelete", ID_VIEW_ZOOMIN
+ MENUITEM "XY Zoom &Out\tInsert", ID_VIEW_ZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "Show &Names", ID_VIEW_SHOWNAMES, CHECKED
+ MENUITEM "Show Blocks", ID_VIEW_SHOWBLOCKS
+ MENUITEM "Show C&oordinates", ID_VIEW_SHOWCOORDINATES
+ , CHECKED
+ MENUITEM "Show &Entities", ID_VIEW_SHOWENT, CHECKED
+ MENUITEM "Show &Path", ID_VIEW_SHOWPATH, CHECKED
+ MENUITEM "Show &Lights", ID_VIEW_SHOWLIGHTS, CHECKED
+ MENUITEM "Show &Water", ID_VIEW_SHOWWATER, CHECKED
+ MENUITEM "Show Clip &Brush", ID_VIEW_SHOWCLIP, CHECKED
+ MENUITEM "Show Wor&ld", ID_VIEW_SHOWWORLD, CHECKED
+ MENUITEM "Show Detail\tctrl-D", ID_VIEW_SHOWDETAIL, CHECKED
+ MENUITEM SEPARATOR
+ MENUITEM "&Z 100%", ID_VIEW_Z100
+ MENUITEM "Z Zoo&m In\tctrl-Delete", ID_VIEW_ZZOOMIN
+ MENUITEM "Z Zoom O&ut\tctrl-Insert", ID_VIEW_ZZOOMOUT
+ END
+ POPUP "&Selection"
+ BEGIN
+ MENUITEM "Drag &Edges\tE", ID_SELECTION_DRAGEDGES
+ MENUITEM "Drag &Vertecies\tV", ID_SELECTION_DRAGVERTECIES
+ MENUITEM "&Clone\tspace", ID_SELECTION_CLONE
+ MENUITEM "Deselect\tEsc", ID_SELECTION_DESELECT
+ MENUITEM "&Delete\tBackspace", ID_SELECTION_DELETE
+ MENUITEM "Flip &X", ID_BRUSH_FLIPX
+ MENUITEM "Flip &Y", ID_BRUSH_FLIPY
+ MENUITEM "Flip &Z", ID_BRUSH_FLIPZ
+ MENUITEM "Rotate X", ID_BRUSH_ROTATEX
+ MENUITEM "Rotate Y", ID_BRUSH_ROTATEY
+ MENUITEM "Rotate Z", ID_BRUSH_ROTATEZ
+ MENUITEM "Arbitrary rotation", ID_SELECTION_ARBITRARYROTATION
+
+ MENUITEM "Make &Hollow", ID_SELECTION_MAKEHOLLOW
+ MENUITEM "CSG &Subtract", ID_SELECTION_CSGSUBTRACT
+ MENUITEM "Select Complete &Tall", ID_SELECTION_SELECTCOMPLETETALL
+
+ MENUITEM "Select T&ouching", ID_SELECTION_SELECTTOUCHING
+ MENUITEM "Select &Partial Tall", ID_SELECTION_SELECTPARTIALTALL
+
+ MENUITEM "Select &Inside", ID_SELECTION_SELECTINSIDE
+ MENUITEM "Connect entities\tCtrl-k", ID_SELECTION_CONNECT
+ MENUITEM "Ungroup entity", ID_SELECTION_UNGROUPENTITY
+ MENUITEM "Make detail\tCtrl-m", ID_SELECTION_MAKE_DETAIL
+ MENUITEM "Make structural", ID_SELECTION_MAKE_STRUCTURAL
+ END
+ POPUP "&Bsp"
+ BEGIN
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Grid"
+ BEGIN
+ MENUITEM "Grid1\t&1", ID_GRID_1
+ MENUITEM "Grid2\t&2", ID_GRID_2
+ MENUITEM "Grid4\t&3", ID_GRID_4
+ MENUITEM "Grid8\t&4", ID_GRID_8, CHECKED
+ MENUITEM "Grid16\t&5", ID_GRID_16
+ MENUITEM "Grid32\t&6", ID_GRID_32
+ MENUITEM "Grid64\t&7", ID_GRID_64
+ END
+ POPUP "&Textures"
+ BEGIN
+ MENUITEM "Show In &Use\tU", ID_TEXTURES_SHOWINUSE
+ MENUITEM "&Surface inspector\tS", ID_TEXTURES_INSPECTOR
+ MENUITEM SEPARATOR
+ MENUITEM "&Wireframe", ID_TEXTURES_WIREFRAME
+ MENUITEM "&Flat shade", ID_TEXTURES_FLATSHADE
+ MENUITEM "&Nearest", ID_VIEW_NEAREST
+ MENUITEM "Nearest &Mipmap", ID_VIEW_NEARESTMIPMAP
+ MENUITEM "&Linear", ID_VIEW_LINEAR
+ MENUITEM "&Bilinear", ID_VIEW_BILINEAR
+ MENUITEM "B&ilinear Mipmap", ID_VIEW_BILINEARMIPMAP
+ MENUITEM "T&rilinear", ID_VIEW_TRILINEAR
+ MENUITEM SEPARATOR
+ END
+ POPUP "&Misc"
+ BEGIN
+ MENUITEM "&Benchmark", ID_MISC_BENCHMARK
+ POPUP "&Colors"
+ BEGIN
+ MENUITEM "&Texture Background", ID_TEXTUREBK
+ MENUITEM "Grid Background", ID_COLORS_XYBK
+ MENUITEM "Grid Major", ID_COLORS_MAJOR
+ MENUITEM "Grid Minor", ID_COLORS_MINOR
+ END
+ MENUITEM "&Gamma", ID_MISC_GAMMA
+ MENUITEM "Find brush", ID_MISC_FINDBRUSH
+ MENUITEM "Next leak spot\tctrl-l", ID_MISC_NEXTLEAKSPOT
+ MENUITEM "Previous leak spot\tctrl-p", ID_MISC_PREVIOUSLEAKSPOT
+ MENUITEM "&Print XY View", ID_MISC_PRINTXY
+ MENUITEM "&Select Entity Color\tK", ID_MISC_SELECTENTITYCOLOR
+ END
+ POPUP "&Region"
+ BEGIN
+ MENUITEM "&Off", ID_REGION_OFF
+ MENUITEM "&Set XY", ID_REGION_SETXY
+ MENUITEM "Set &Tall Brush", ID_REGION_SETTALLBRUSH
+ MENUITEM "Set &Brush", ID_REGION_SETBRUSH
+ MENUITEM "Set Se&lected Brushes", ID_REGION_SETSELECTION
+ END
+ POPUP "&Brush"
+ BEGIN
+ MENUITEM "3 sided\tctrl-3", ID_BRUSH_3SIDED
+ MENUITEM "4 sided\tctrl-4", ID_BRUSH_4SIDED
+ MENUITEM "5 sided\tctrl-5", ID_BRUSH_5SIDED
+ MENUITEM "6 sided\tctrl-6", ID_BRUSH_6SIDED
+ MENUITEM "7 sided\tctrl-7", ID_BRUSH_7SIDED
+ MENUITEM "8 sided\tctrl-8", ID_BRUSH_8SIDED
+ MENUITEM "9 sided\tctrl-9", ID_BRUSH_9SIDED
+ MENUITEM "Arbitrary sided", ID_BRUSH_ARBITRARYSIDED
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About", ID_HELP_ABOUT
+ END
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_FINDTEXTURE DIALOG DISCARDABLE 0, 0, 129, 53
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Find Texture"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,10,30,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,70,30,50,14
+ EDITTEXT IDC_EDIT1,10,10,110,14,ES_AUTOHSCROLL
+END
+
+IDD_ENTITY DIALOGEX 0, 0, 234, 389
+STYLE DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPSIBLINGS |
+ WS_CAPTION | WS_THICKFRAME
+EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CLIENTEDGE
+CAPTION "Entity"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ LISTBOX IDC_E_LIST,5,5,180,99,LBS_SORT | LBS_NOINTEGRALHEIGHT |
+ LBS_WANTKEYBOARDINPUT | WS_VSCROLL | WS_TABSTOP,
+ WS_EX_CLIENTEDGE
+ EDITTEXT IDC_E_COMMENT,5,106,180,50,ES_MULTILINE | ES_READONLY |
+ WS_VSCROLL,WS_EX_CLIENTEDGE
+ PUSHBUTTON "135",IDC_E_135,5,290,15,15
+ PUSHBUTTON "180",IDC_E_180,5,305,15,15
+ PUSHBUTTON "225",IDC_E_225,5,320,15,15
+ PUSHBUTTON "270",IDC_E_270,21,320,15,15
+ PUSHBUTTON "90",IDC_E_90,21,290,15,15
+ PUSHBUTTON "45",IDC_E_45,35,290,15,15
+ PUSHBUTTON "0",IDC_E_0,35,305,15,15
+ PUSHBUTTON "315",IDC_E_315,35,320,15,15
+ PUSHBUTTON "Up",IDC_E_UP,60,295,15,15
+ PUSHBUTTON "Dn",IDC_E_DOWN,60,310,15,15
+ CONTROL "",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,160,50,8
+ CONTROL "",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,170,50,8
+ CONTROL "",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,180,50,8
+ CONTROL "",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,5,190,50,8
+ CONTROL "",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,160,50,8
+ CONTROL "",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,170,50,8
+ CONTROL "",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,180,50,8
+ CONTROL "",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,65,190,50,8
+ CONTROL "!Easy",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 125,160,50,8
+ CONTROL "!Medium",IDC_CHECK10,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,125,170,50,8
+ CONTROL "!Hard",IDC_CHECK11,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,125,180,50,10
+ CONTROL "!DeathMatch",IDC_CHECK12,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,125,190,55,10
+ LISTBOX IDC_E_PROPS,5,205,180,50,LBS_SORT | LBS_USETABSTOPS |
+ LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT |
+ WS_VSCROLL | WS_TABSTOP,WS_EX_CLIENTEDGE
+ PUSHBUTTON "Del Key/Pair",IDC_E_DELPROP,105,295,45,15
+ EDITTEXT IDC_E_STATUS,83,312,95,30,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
+ LTEXT "Key",IDC_STATIC_KEY,5,260,25,10
+ LTEXT "Value",IDC_STATIC_VALUE,5,275,25,10
+ EDITTEXT IDC_E_KEY_FIELD,40,260,135,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_E_VALUE_FIELD,40,275,135,14,ES_AUTOHSCROLL
+END
+
+IDD_GAMMA DIALOGEX 0, 0, 127, 76
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Gamma"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,10,40,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,65,40,50,14
+ EDITTEXT IDC_G_EDIT,30,15,66,13,ES_AUTOHSCROLL,WS_EX_CLIENTEDGE
+END
+
+IDD_FINDBRUSH DIALOGEX 0, 0, 127, 76
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "Find brush"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,5,55,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,65,55,50,14
+ EDITTEXT IDC_FIND_ENTITY,80,15,46,13,ES_AUTOHSCROLL,
+ WS_EX_CLIENTEDGE
+ EDITTEXT IDC_FIND_BRUSH,80,30,46,13,ES_AUTOHSCROLL,
+ WS_EX_CLIENTEDGE
+ LTEXT "Entity number",IDC_STATIC,10,15,60,8
+ LTEXT "Brush number",IDC_STATIC,10,30,65,8
+END
+
+IDD_ROTATE DIALOG DISCARDABLE 0, 0, 186, 71
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Arbitrary rotation"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+ EDITTEXT IDC_ROTX,30,5,40,14,ES_AUTOHSCROLL
+ LTEXT "x",IDC_STATIC,5,10,8,8
+ EDITTEXT IDC_ROTZ,30,45,40,14,ES_AUTOHSCROLL
+ LTEXT "y",IDC_STATIC,5,25,8,8
+ EDITTEXT IDC_ROTY,30,25,40,14,ES_AUTOHSCROLL
+ LTEXT "z",IDC_STATIC,5,45,8,8
+END
+
+IDD_SIDES DIALOG DISCARDABLE 0, 0, 186, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Arbitrrary sides"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+ EDITTEXT IDC_SIDES,50,15,40,14,ES_AUTOHSCROLL
+ LTEXT "Sides",IDC_STATIC,15,15,18,8
+END
+
+IDD_ABOUT DIALOG DISCARDABLE 0, 0, 274, 212
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About QuakeEd"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,217,7,50,14
+ CONTROL 127,IDC_STATIC,"Static",SS_BITMAP,7,7,83,58
+ CONTROL "Q3Radiant\nCopyright (C) 1997, 2005 id Software, Inc.",
+ IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,100,10,
+ 110,23
+ GROUPBOX "OpenGL Properties",IDC_STATIC,5,75,265,50
+ LTEXT "Vendor:\t\tWHOEVER",IDC_ABOUT_GLVENDOR,10,90,125,10
+ LTEXT "Version:\t\t1.1",IDC_ABOUT_GLVERSION,10,100,125,10
+ LTEXT "Renderer:\tWHATEVER",IDC_ABOUT_GLRENDERER,10,110,125,10
+ LTEXT "WHATEVER",IDC_ABOUT_GLEXTENSIONS,10,140,255,60
+ GROUPBOX "OpenGL Extensions",IDC_STATIC,5,130,265,80
+END
+
+IDD_SURFACE DIALOG DISCARDABLE 400, 100, 392, 181
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Surface inspector"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,5,155,40,14
+ PUSHBUTTON "Cancel",IDCANCEL,105,155,40,14
+ EDITTEXT IDC_HSHIFT,85,45,35,15,ES_AUTOHSCROLL
+ SCROLLBAR IDC_HSHIFTA,120,45,10,15,SBS_VERT
+ LTEXT "Horizontal shift",IDC_STATIC,10,45,65,8
+ LTEXT "Vertical shift",IDC_STATIC,10,60,65,8
+ LTEXT "Horizontal stretch",IDC_STATIC,10,75,65,8
+ LTEXT "Vertical stretch",IDC_STATIC,10,90,65,8
+ LTEXT "Rotate",IDC_STATIC,10,105,65,8
+ LTEXT "value",IDC_STATIC,10,120,65,8
+ EDITTEXT IDC_VSHIFT,85,60,35,15,ES_AUTOHSCROLL
+ SCROLLBAR IDC_VSHIFTA,120,60,10,15,SBS_VERT
+ EDITTEXT IDC_HSCALE,85,75,35,15,ES_AUTOHSCROLL
+ SCROLLBAR IDC_HSCALEA,120,75,10,15,SBS_VERT
+ EDITTEXT IDC_VSCALE,85,90,35,15,ES_AUTOHSCROLL
+ SCROLLBAR IDC_VSCALEA,120,90,10,15,SBS_VERT
+ EDITTEXT IDC_ROTATE,85,105,35,15,ES_AUTOHSCROLL
+ SCROLLBAR IDC_ROTATEA,120,105,10,15,SBS_VERT
+ EDITTEXT IDC_VALUE,85,120,35,15,ES_AUTOHSCROLL
+ EDITTEXT IDC_TEXTURE,50,15,80,14,ES_AUTOHSCROLL
+ CONTROL "light",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,10,41,8
+ CONTROL "slick",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,20,41,8
+ CONTROL "sky",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,30,41,8
+ CONTROL "warp",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,40,41,8
+ CONTROL "trans33",IDC_CHECK5,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,160,50,41,8
+ CONTROL "trans66",IDC_CHECK6,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,160,60,41,8
+ CONTROL "flowing",IDC_CHECK7,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,160,70,41,8
+ CONTROL "nodraw",IDC_CHECK8,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,160,80,41,8
+ CONTROL "100",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,90,41,8
+ CONTROL "200",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,100,41,8
+ CONTROL "400",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,110,41,8
+ CONTROL "800",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,120,41,8
+ CONTROL "1000",IDC_CHECK13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,130,41,8
+ CONTROL "2000",IDC_CHECK14,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,140,41,8
+ CONTROL "4000",IDC_CHECK15,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,150,41,8
+ CONTROL "8000",IDC_CHECK16,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 160,160,41,8
+ LTEXT "Texture",IDC_STATIC,10,18,30,8
+ PUSHBUTTON "Apply",IDAPPLY,55,155,40,14
+ CONTROL "10000",IDC_CHECK17,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,10,41,8
+ CONTROL "20000",IDC_CHECK18,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,20,41,8
+ CONTROL "40000",IDC_CHECK19,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,30,41,8
+ CONTROL "80000",IDC_CHECK20,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,40,41,8
+ CONTROL "100000",IDC_CHECK21,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,50,41,8
+ CONTROL "200000",IDC_CHECK22,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,60,41,8
+ CONTROL "400000",IDC_CHECK23,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,70,41,8
+ CONTROL "800000",IDC_CHECK24,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,80,41,8
+ CONTROL "1000000",IDC_CHECK25,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,90,41,8
+ CONTROL "2000000",IDC_CHECK26,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,100,41,8
+ CONTROL "4000000",IDC_CHECK27,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,110,41,8
+ CONTROL "8000000",IDC_CHECK28,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,120,41,8
+ CONTROL "10000000",IDC_CHECK29,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,130,40,8
+ CONTROL "20000000",IDC_CHECK30,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,140,45,8
+ CONTROL "40000000",IDC_CHECK31,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,150,45,8
+ CONTROL "80000000",IDC_CHECK32,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,210,160,45,8
+ CONTROL "solid",IDC_CHECK33,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,280,10,41,8
+ CONTROL "window",IDC_CHECK34,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,280,20,41,8
+ CONTROL "aux",IDC_CHECK35,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,31,41,8
+ CONTROL "lava",IDC_CHECK36,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,41,41,8
+ CONTROL "slime",IDC_CHECK37,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,280,50,41,8
+ CONTROL "water",IDC_CHECK38,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,280,60,41,8
+ CONTROL "mist",IDC_CHECK39,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,71,41,8
+ CONTROL "80",IDC_CHECK40,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,81,41,8
+ CONTROL "100",IDC_CHECK41,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,90,41,8
+ CONTROL "200",IDC_CHECK42,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,100,41,8
+ CONTROL "400",IDC_CHECK43,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,111,41,8
+ CONTROL "800",IDC_CHECK44,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,121,41,8
+ CONTROL "1000",IDC_CHECK45,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,130,41,8
+ CONTROL "2000",IDC_CHECK46,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,140,41,8
+ CONTROL "4000",IDC_CHECK47,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,151,41,8
+ CONTROL "8000",IDC_CHECK48,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 280,161,41,8
+ CONTROL "playerclip",IDC_CHECK49,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,10,41,8
+ CONTROL "monsterclip",IDC_CHECK50,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,20,50,8
+ CONTROL "current_0",IDC_CHECK51,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,31,50,8
+ CONTROL "current_90",IDC_CHECK52,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,41,50,8
+ CONTROL "current_180",IDC_CHECK53,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,50,50,8
+ CONTROL "current_270",IDC_CHECK54,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,60,50,8
+ CONTROL "current_up",IDC_CHECK55,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,71,50,8
+ CONTROL "current_dn",IDC_CHECK56,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,81,50,8
+ CONTROL "origin",IDC_CHECK57,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,90,41,8
+ CONTROL "monster",IDC_CHECK58,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,100,41,8
+ CONTROL "corpse",IDC_CHECK59,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,111,41,8
+ CONTROL "detail",IDC_CHECK60,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,121,41,8
+ CONTROL "translucent",IDC_CHECK61,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,130,50,8
+ CONTROL "ladder",IDC_CHECK62,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,140,45,8
+ CONTROL "40000000",IDC_CHECK63,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,151,45,8
+ CONTROL "80000000",IDC_CHECK64,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,330,161,45,8
+ GROUPBOX "Surf flags",IDC_STATIC,150,0,115,175
+ GROUPBOX "Content flags",IDC_STATIC,270,0,115,175
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Id Software\0"
+ VALUE "FileDescription", "qe3\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "qe3\0"
+ VALUE "LegalCopyright", "Copyright © 1996\0"
+ VALUE "OriginalFilename", "qe3.exe\0"
+ VALUE "ProductName", "Id Software qe3\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ "3", ID_BRUSH_3SIDED, VIRTKEY, CONTROL, NOINVERT
+ "4", ID_BRUSH_4SIDED, VIRTKEY, CONTROL, NOINVERT
+ "5", ID_BRUSH_5SIDED, VIRTKEY, CONTROL, NOINVERT
+ "6", ID_BRUSH_6SIDED, VIRTKEY, CONTROL, NOINVERT
+ "7", ID_BRUSH_7SIDED, VIRTKEY, CONTROL, NOINVERT
+ "8", ID_BRUSH_8SIDED, VIRTKEY, CONTROL, NOINVERT
+ "9", ID_BRUSH_9SIDED, VIRTKEY, CONTROL, NOINVERT
+ "D", ID_VIEW_SHOWDETAIL, VIRTKEY, CONTROL, NOINVERT
+ "K", ID_SELECTION_CONNECT, VIRTKEY, CONTROL, NOINVERT
+ "L", ID_MISC_NEXTLEAKSPOT, VIRTKEY, CONTROL, NOINVERT
+ "M", ID_SELECTION_MAKE_DETAIL, VIRTKEY, CONTROL, NOINVERT
+ "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "P", ID_MISC_PREVIOUSLEAKSPOT, VIRTKEY, CONTROL, NOINVERT
+ "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ VK_DELETE, ID_VIEW_ZZOOMIN, VIRTKEY, CONTROL, NOINVERT
+ VK_INSERT, ID_VIEW_ZZOOMOUT, VIRTKEY, CONTROL, NOINVERT
+ "X", ID_FILE_EXIT, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Toolbar
+//
+
+IDR_TOOLBAR1 TOOLBAR DISCARDABLE 16, 15
+BEGIN
+ BUTTON ID_BRUSH_FLIPX
+ BUTTON ID_BRUSH_ROTATEX
+ BUTTON ID_BRUSH_FLIPY
+ BUTTON ID_BRUSH_ROTATEY
+ BUTTON ID_BRUSH_FLIPZ
+ BUTTON ID_BRUSH_ROTATEZ
+ BUTTON ID_SELECTION_SELECTCOMPLETETALL
+ BUTTON ID_SELECTION_SELECTTOUCHING
+ BUTTON ID_SELECTION_SELECTPARTIALTALL
+ BUTTON ID_SELECTION_SELECTINSIDE
+ BUTTON ID_SELECTION_CSGSUBTRACT
+ BUTTON ID_SELECTION_MAKEHOLLOW
+ BUTTON ID_TEXTURES_WIREFRAME
+ BUTTON ID_TEXTURES_FLATSHADE
+ BUTTON ID_VIEW_TRILINEAR
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDR_TOOLBAR1 BITMAP DISCARDABLE "toolbar1.bmp"
+IDB_BITMAP1 BITMAP DISCARDABLE "q.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ENTITY, DIALOG
+ BEGIN
+ RIGHTMARGIN, 227
+ BOTTOMMARGIN, 387
+ END
+
+ IDD_GAMMA, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 120
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 68
+ END
+
+ IDD_FINDBRUSH, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 120
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 68
+ END
+
+ IDD_ROTATE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 64
+ END
+
+ IDD_SIDES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 48
+ END
+
+ IDD_ABOUT, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 267
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 205
+ END
+
+ IDD_SURFACE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 385
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 174
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON DISCARDABLE "icon1.ico"
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/q3radiant/WIN_XY.CPP b/q3radiant/WIN_XY.CPP
new file mode 100755
index 0000000..34d3564
--- /dev/null
+++ b/q3radiant/WIN_XY.CPP
@@ -0,0 +1,310 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// win_xy.c -- windows specific xy view code
+
+#include "stdafx.h"
+#include "qe3.h"
+
+static HDC s_hdcXY;
+static HGLRC s_hglrcXY;
+
+static unsigned s_stipple[32] =
+{
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+};
+
+/*
+============
+WXY_WndProc
+============
+*/
+LONG WINAPI XYWndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int fwKeys, xPos, yPos;
+ RECT rect;
+
+
+ GetClientRect(hWnd, &rect);
+
+ switch (uMsg)
+ {
+ case WM_CREATE:
+
+ s_hdcXY = GetDC(hWnd);
+ QEW_SetupPixelFormat(s_hdcXY, false);
+
+ if ( ( s_hglrcXY = wglCreateContext( s_hdcXY ) ) == 0 )
+ Error( "wglCreateContext in WXY_WndProc failed" );
+
+ if (!wglMakeCurrent( s_hdcXY, s_hglrcXY ))
+ Error ("wglMakeCurrent failed");
+
+ if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcXY ) )
+ Error( "wglShareLists in WXY_WndProc failed" );
+
+ glPolygonStipple ((unsigned char *)s_stipple);
+ glLineStipple (3, 0xaaaa);
+
+ return 0;
+
+ case WM_DESTROY:
+ QEW_StopGL( hWnd, s_hglrcXY, s_hdcXY );
+ return 0;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint(hWnd, &ps);
+
+ if (!wglMakeCurrent( s_hdcXY, s_hglrcXY ))
+ Error ("wglMakeCurrent failed");
+
+ QE_CheckOpenGLForErrors();
+ XY_Draw ();
+ QE_CheckOpenGLForErrors();
+
+ SwapBuffers(s_hdcXY);
+
+ EndPaint(hWnd, &ps);
+ }
+ return 0;
+
+ case WM_KEYDOWN:
+ return QE_KeyDown (wParam);
+
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ if ( GetTopWindow( g_qeglobals.d_hwndMain ) != hWnd)
+ BringWindowToTop(hWnd);
+ SetFocus( g_qeglobals.d_hwndXY );
+ SetCapture( g_qeglobals.d_hwndXY );
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ XY_MouseDown (xPos, yPos, fwKeys);
+ return 0;
+
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_LBUTTONUP:
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ XY_MouseUp (xPos, yPos, fwKeys);
+ if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+ return 0;
+
+ case WM_MOUSEMOVE:
+ if (::GetFocus() != hWnd)
+ ::SetFocus(hWnd);
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ XY_MouseMoved (xPos, yPos, fwKeys);
+ return 0;
+
+ case WM_SIZE:
+ g_qeglobals.d_xy.width = rect.right;
+ g_qeglobals.d_xy.height = rect.bottom - 16;
+ InvalidateRect( g_qeglobals.d_hwndXY, NULL, false);
+ return 0;
+
+ case WM_NCCALCSIZE:// don't let windows copy pixels
+ DefWindowProc (hWnd, uMsg, wParam, lParam);
+ return WVR_REDRAW;
+
+ case WM_KILLFOCUS:
+ case WM_SETFOCUS:
+ SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
+ return 0;
+
+ case WM_CLOSE:
+ DestroyWindow (hWnd);
+ return 0;
+ }
+
+ return DefWindowProc (hWnd, uMsg, wParam, lParam);
+}
+
+
+/*
+==============
+WXY_Create
+==============
+*/
+void WXY_Create (HINSTANCE hInstance)
+{
+ ASSERT(0);
+#if 0
+ WNDCLASS wc;
+
+ /* Register the camera class */
+ memset (&wc, 0, sizeof(wc));
+
+ wc.style = CS_NOCLOSE;
+ wc.lpfnWndProc = (WNDPROC)WXY_WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = 0;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.hbrBackground = NULL; //(HBRUSH)(COLOR_WINDOW+1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = XY_WINDOW_CLASS;
+
+ if (!RegisterClass (&wc) )
+ Error ("RegisterClass: failed");
+
+ g_qeglobals.d_hwndXY = CreateWindow (XY_WINDOW_CLASS ,
+ "XY View",
+ QE3_STYLE ,
+ ZWIN_WIDTH,
+ (int)(screen_height*CWIN_SIZE)-20,
+ screen_width-ZWIN_WIDTH,
+ (int)(screen_height*(1.0-CWIN_SIZE)-38), // size
+
+ g_qeglobals.d_hwndMain, // parent
+ 0, // no menu
+ hInstance,
+ NULL);
+
+ if (!g_qeglobals.d_hwndXY )
+ Error ("Couldn't create XY View");
+
+ LoadWindowState(g_qeglobals.d_hwndXY, "xywindow");
+ ShowWindow(g_qeglobals.d_hwndXY, SW_SHOWDEFAULT);
+#endif
+}
+
+static void WXY_InitPixelFormat( PIXELFORMATDESCRIPTOR *pPFD )
+{
+ memset( pPFD, 0, sizeof( *pPFD ) );
+
+ pPFD->nSize = sizeof( PIXELFORMATDESCRIPTOR );
+ pPFD->nVersion = 1;
+ pPFD->dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
+ pPFD->iPixelType = PFD_TYPE_RGBA;
+ pPFD->cColorBits = 24;
+ pPFD->cDepthBits = 32;
+ pPFD->iLayerType = PFD_MAIN_PLANE;
+
+}
+
+void WXY_Print( void )
+{
+ DOCINFO di;
+
+ PRINTDLG pd;
+
+ /*
+ ** initialize the PRINTDLG struct and execute it
+ */
+ memset( &pd, 0, sizeof( pd ) );
+ pd.lStructSize = sizeof( pd );
+ pd.hwndOwner = g_qeglobals.d_hwndXY;
+ pd.Flags = PD_RETURNDC;
+ pd.hInstance = 0;
+ if ( !PrintDlg( &pd ) || !pd.hDC )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ /*
+ ** StartDoc
+ */
+ memset( &di, 0, sizeof( di ) );
+ di.cbSize = sizeof( di );
+ di.lpszDocName = "QE4";
+ if ( StartDoc( pd.hDC, &di ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ /*
+ ** StartPage
+ */
+ if ( StartPage( pd.hDC ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ /*
+ ** read pixels from the XY window
+ */
+ {
+ int bmwidth = 320, bmheight = 320;
+ int pwidth, pheight;
+
+ RECT r;
+
+ GetWindowRect( g_qeglobals.d_hwndXY, &r );
+
+ bmwidth = r.right - r.left;
+ bmheight = r.bottom - r.top;
+
+ pwidth = GetDeviceCaps( pd.hDC, PHYSICALWIDTH ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETX );
+ pheight = GetDeviceCaps( pd.hDC, PHYSICALHEIGHT ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETY );
+
+ StretchBlt( pd.hDC,
+ 0, 0,
+ pwidth, pheight,
+ s_hdcXY,
+ 0, 0,
+ bmwidth, bmheight,
+ SRCCOPY );
+ }
+
+ /*
+ ** EndPage and EndDoc
+ */
+ if ( EndPage( pd.hDC ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ if ( EndDoc( pd.hDC ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR );
+ return;
+ }
+}
diff --git a/q3radiant/WIN_Z.CPP b/q3radiant/WIN_Z.CPP
new file mode 100755
index 0000000..caac0d0
--- /dev/null
+++ b/q3radiant/WIN_Z.CPP
@@ -0,0 +1,192 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// win_cam.c -- windows specific camera view code
+
+#include "stdafx.h"
+#include "qe3.h"
+
+static HDC s_hdcZ;
+static HGLRC s_hglrcZ;
+
+/*
+============
+WZ_WndProc
+============
+*/
+LONG WINAPI WZ_WndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ int fwKeys, xPos, yPos;
+ RECT rect;
+
+ GetClientRect(hWnd, &rect);
+
+ switch (uMsg)
+ {
+
+ case WM_DESTROY:
+ QEW_StopGL( hWnd, s_hglrcZ, s_hdcZ );
+ return 0;
+
+ case WM_CREATE:
+ s_hdcZ = GetDC(hWnd);
+ QEW_SetupPixelFormat( s_hdcZ, false);
+ if ( ( s_hglrcZ = wglCreateContext( s_hdcZ ) ) == 0 )
+ Error( "wglCreateContext in WZ_WndProc failed" );
+
+ if (!wglMakeCurrent( s_hdcZ, s_hglrcZ ))
+ Error ("wglMakeCurrent in WZ_WndProc failed");
+
+ if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcZ ) )
+ Error( "wglShareLists in WZ_WndProc failed" );
+ return 0;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+
+ BeginPaint(hWnd, &ps);
+
+ if ( !wglMakeCurrent( s_hdcZ, s_hglrcZ ) )
+ Error ("wglMakeCurrent failed");
+ QE_CheckOpenGLForErrors();
+
+ Z_Draw ();
+ SwapBuffers(s_hdcZ);
+
+ EndPaint(hWnd, &ps);
+ }
+ return 0;
+
+
+ case WM_KEYDOWN:
+ QE_KeyDown (wParam);
+ return 0;
+
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_LBUTTONDOWN:
+ if (GetTopWindow(g_qeglobals.d_hwndMain) != hWnd)
+ BringWindowToTop(hWnd);
+
+ SetFocus( g_qeglobals.d_hwndZ );
+ SetCapture( g_qeglobals.d_hwndZ );
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ Z_MouseDown (xPos, yPos, fwKeys);
+ return 0;
+
+ case WM_MBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_LBUTTONUP:
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ Z_MouseUp (xPos, yPos, fwKeys);
+ if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+ return 0;
+
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO *pmmi = (LPMINMAXINFO) lParam;
+
+ pmmi->ptMinTrackSize.x = ZWIN_WIDTH;
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ fwKeys = wParam; // key flags
+ xPos = (short)LOWORD(lParam); // horizontal position of cursor
+ yPos = (short)HIWORD(lParam); // vertical position of cursor
+ yPos = (int)rect.bottom - 1 - yPos;
+ Z_MouseMoved (xPos, yPos, fwKeys);
+ return 0;
+
+ case WM_SIZE:
+ z.width = rect.right;
+ z.height = rect.bottom;
+ InvalidateRect( g_qeglobals.d_hwndZ, NULL, false);
+ return 0;
+
+ case WM_NCCALCSIZE:// don't let windows copy pixels
+ DefWindowProc (hWnd, uMsg, wParam, lParam);
+ return WVR_REDRAW;
+
+ case WM_KILLFOCUS:
+ case WM_SETFOCUS:
+ SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
+ return 0;
+
+ case WM_CLOSE:
+ /* call destroy window to cleanup and go away */
+ DestroyWindow (hWnd);
+ return 0;
+ }
+
+ return DefWindowProc (hWnd, uMsg, wParam, lParam);
+}
+
+
+/*
+==============
+WZ_Create
+==============
+*/
+void WZ_Create (HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+ memset (&wc, 0, sizeof(wc));
+ wc.style = CS_NOCLOSE;
+ wc.lpfnWndProc = (WNDPROC)WZ_WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = 0;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = Z_WINDOW_CLASS;
+
+ if (!RegisterClass (&wc) )
+ Error ("WCam_Register: failed");
+
+ g_qeglobals.d_hwndZ = CreateWindow (Z_WINDOW_CLASS ,
+ "Z",
+ QE3_STYLE,
+ 0,20,ZWIN_WIDTH,screen_height-38, // size
+ g_qeglobals.d_hwndMain, // parent
+ 0, // no menu
+ hInstance,
+ NULL);
+ if (!g_qeglobals.d_hwndZ)
+ Error ("Couldn't create zwindow");
+
+ LoadWindowState(g_qeglobals.d_hwndZ, "zwindow");
+ ShowWindow (g_qeglobals.d_hwndZ, SW_SHOWDEFAULT);
+}
diff --git a/q3radiant/WaveOpen.cpp b/q3radiant/WaveOpen.cpp
new file mode 100755
index 0000000..34f1f6b
--- /dev/null
+++ b/q3radiant/WaveOpen.cpp
@@ -0,0 +1,98 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// WaveOpen.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "WaveOpen.h"
+#include "mmsystem.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CWaveOpen
+
+IMPLEMENT_DYNAMIC(CWaveOpen, CFileDialog)
+
+CWaveOpen::CWaveOpen(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
+ DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
+ CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
+{
+ m_ofn.Flags |= (OFN_EXPLORER | OFN_ENABLETEMPLATE);
+ m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_PLAYWAVE);
+}
+
+
+BEGIN_MESSAGE_MAP(CWaveOpen, CFileDialog)
+ //{{AFX_MSG_MAP(CWaveOpen)
+ ON_BN_CLICKED(IDC_BTN_PLAY, OnBtnPlay)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+void CWaveOpen::OnFileNameChange()
+{
+ CString str = GetPathName();
+ str.MakeLower();
+ CWnd *pWnd = GetDlgItem(IDC_BTN_PLAY);
+ if (pWnd == NULL)
+ {
+ return;
+ }
+ if (str.Find(".wav") >= 0)
+ {
+ pWnd->EnableWindow(TRUE);
+ }
+ else
+ {
+ pWnd->EnableWindow(FALSE);
+ }
+}
+
+void CWaveOpen::OnBtnPlay()
+{
+ sndPlaySound(NULL, NULL);
+ CString str = GetPathName();
+ if (str.GetLength() > 0)
+ {
+ sndPlaySound(str, SND_FILENAME | SND_ASYNC);
+ }
+}
+
+BOOL CWaveOpen::OnInitDialog()
+{
+ CFileDialog::OnInitDialog();
+
+ CWnd *pWnd = GetDlgItem(IDC_BTN_PLAY);
+ if (pWnd != NULL)
+ {
+ pWnd->EnableWindow(FALSE);
+ }
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
diff --git a/q3radiant/WaveOpen.h b/q3radiant/WaveOpen.h
new file mode 100755
index 0000000..f5208a3
--- /dev/null
+++ b/q3radiant/WaveOpen.h
@@ -0,0 +1,58 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_WAVEOPEN_H__0FB9DA11_EB02_11D2_A50A_0020AFEB881A__INCLUDED_)
+#define AFX_WAVEOPEN_H__0FB9DA11_EB02_11D2_A50A_0020AFEB881A__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// WaveOpen.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CWaveOpen dialog
+
+class CWaveOpen : public CFileDialog
+{
+ DECLARE_DYNAMIC(CWaveOpen)
+
+public:
+ CWaveOpen(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
+ LPCTSTR lpszDefExt = NULL,
+ LPCTSTR lpszFileName = NULL,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
+ LPCTSTR lpszFilter = NULL,
+ CWnd* pParentWnd = NULL);
+
+ virtual void OnFileNameChange( );
+protected:
+ //{{AFX_MSG(CWaveOpen)
+ afx_msg void OnBtnPlay();
+ virtual BOOL OnInitDialog();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_WAVEOPEN_H__0FB9DA11_EB02_11D2_A50A_0020AFEB881A__INCLUDED_)
diff --git a/q3radiant/Win_ent.cpp b/q3radiant/Win_ent.cpp
new file mode 100755
index 0000000..28bc9ab
--- /dev/null
+++ b/q3radiant/Win_ent.cpp
@@ -0,0 +1,1411 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+#include "entityw.h"
+#include "TexWnd.h"
+#include "WaveOpen.h"
+
+int rgIds[EntLast] = {
+ IDC_E_LIST,
+ IDC_E_COMMENT,
+ IDC_CHECK1,
+ IDC_CHECK2,
+ IDC_CHECK3,
+ IDC_CHECK4,
+ IDC_CHECK5,
+ IDC_CHECK6,
+ IDC_CHECK7,
+ IDC_CHECK8,
+ IDC_CHECK9,
+ IDC_CHECK10,
+ IDC_CHECK11,
+ IDC_CHECK12,
+ IDC_E_PROPS,
+ IDC_E_0,
+ IDC_E_45,
+ IDC_E_90,
+ IDC_E_135,
+ IDC_E_180,
+ IDC_E_225,
+ IDC_E_270,
+ IDC_E_315,
+ IDC_E_UP,
+ IDC_E_DOWN,
+ IDC_E_DELPROP,
+
+ IDC_STATIC_KEY,
+ IDC_E_KEY_FIELD,
+ IDC_STATIC_VALUE,
+ IDC_E_VALUE_FIELD,
+
+ IDC_E_COLOR,
+
+ IDC_BTN_ASSIGNSOUND,
+ IDC_BTN_ASSIGNMODEL
+
+};
+
+HWND hwndEnt[EntLast];
+CTabCtrl g_wndTabs;
+
+int inspector_mode; // W_TEXTURE, W_ENTITY, or W_CONSOLE
+
+qboolean multiple_entities;
+
+entity_t *edit_entity;
+
+
+BOOL CALLBACK EntityWndProc(
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam); // second message parameter
+
+void SizeEntityDlg(int iWidth, int iHeight);
+void AddProp();
+void GetTexMods(void);
+
+
+LRESULT (CALLBACK* OldFieldWindowProc) (HWND, UINT, WPARAM, LPARAM);
+LRESULT (CALLBACK* OldEntityListWindowProc) (HWND, UINT, WPARAM, LPARAM);
+
+/*
+=========================
+FieldWndProc
+
+Just to handle tab and enter...
+=========================
+*/
+BOOL CALLBACK FieldWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_CHAR:
+ if (LOWORD(wParam) == VK_TAB)
+ return FALSE;
+ if (LOWORD(wParam) == VK_RETURN)
+ return FALSE;
+ if (LOWORD(wParam) == VK_ESCAPE)
+ {
+ SetFocus (g_qeglobals.d_hwndCamera);
+ return FALSE;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if (LOWORD(wParam) == VK_TAB)
+ {
+ if (hwnd == hwndEnt[EntKeyField])
+ {
+ SendMessage (hwndEnt[EntValueField], WM_SETTEXT, 0, (long)"");
+ SetFocus (hwndEnt[EntValueField]);
+ }
+ else
+ SetFocus (hwndEnt[EntKeyField]);
+ }
+ if (LOWORD(wParam) == VK_RETURN)
+ {
+ if (hwnd == hwndEnt[EntKeyField])
+ {
+ SendMessage (hwndEnt[EntValueField], WM_SETTEXT, 0, (long)"");
+ SetFocus (hwndEnt[EntValueField]);
+ }
+ else
+ {
+ AddProp ();
+ SetFocus (g_qeglobals.d_hwndCamera);
+ }
+ }
+ break;
+// case WM_NCHITTEST:
+ case WM_LBUTTONDOWN:
+ SetFocus (hwnd);
+ break;
+ }
+ return CallWindowProc (OldFieldWindowProc, hwnd, uMsg, wParam, lParam);
+}
+
+
+/*
+=========================
+EntityListWndProc
+
+Just to handle enter...
+=========================
+*/
+BOOL CALLBACK EntityListWndProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_KEYDOWN:
+ if (LOWORD(wParam) == VK_RETURN)
+ {
+ SendMessage ( g_qeglobals.d_hwndEntity,
+ WM_COMMAND,
+ (LBN_DBLCLK<<16) + IDC_E_LIST,
+ 0 );
+ return 0;
+ }
+ break;
+ }
+ return CallWindowProc (OldEntityListWindowProc, hwnd, uMsg, wParam, lParam);
+}
+
+
+/*
+================
+GetEntityControls
+
+Finds the controls from the dialog and
+moves them to the window
+================
+*/
+void GetEntityControls(HWND ghwndEntity)
+{
+ int i;
+
+ for (i = 0; i < EntLast; i++)
+ {
+ if (i == EntList || i == EntProps || i == EntComment)
+ continue;
+ if (i == EntKeyField || i == EntValueField)
+ continue;
+ hwndEnt[i] = GetDlgItem(ghwndEntity, rgIds[i]);
+ if (hwndEnt[i])
+ {
+ SetParent (hwndEnt[i], g_qeglobals.d_hwndEntity );
+ SendMessage(hwndEnt[i], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+ }
+ }
+
+
+ // SetParent apears to not modify some internal state
+ // on listboxes, so create it from scratch...
+
+ hwndEnt[EntList] = CreateWindow ("listbox", NULL,
+ LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_WANTKEYBOARDINPUT
+ | WS_VSCROLL | WS_CHILD | WS_VISIBLE,
+ 5, 5, 180, 99,
+ g_qeglobals.d_hwndEntity,
+ (HMENU)IDC_E_LIST,
+ g_qeglobals.d_hInstance,
+ NULL);
+ if (!hwndEnt[EntList])
+ Error ("CreateWindow failed");
+
+ hwndEnt[EntProps] = CreateWindow ("listbox", NULL,
+ LBS_STANDARD | LBS_NOINTEGRALHEIGHT | LBS_USETABSTOPS
+ | WS_VSCROLL | WS_CHILD | WS_VISIBLE,
+ 5, 100, 180, 99,
+ g_qeglobals.d_hwndEntity,
+ (HMENU)IDC_E_PROPS,
+ g_qeglobals.d_hInstance,
+ NULL);
+ if (!hwndEnt[EntProps])
+ Error ("CreateWindow failed");
+
+ hwndEnt[EntComment] = CreateWindow ("edit", NULL,
+ ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER,
+ 5, 100, 180, 99,
+ g_qeglobals.d_hwndEntity,
+ (HMENU)IDC_E_COMMENT,
+ g_qeglobals.d_hInstance,
+ NULL);
+ if (!hwndEnt[EntComment])
+ Error ("CreateWindow failed");
+
+ hwndEnt[EntKeyField] = CreateWindow ("edit", NULL,
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
+ 5, 100, 180, 99,
+ g_qeglobals.d_hwndEntity,
+ (HMENU)IDC_E_KEY_FIELD,
+ g_qeglobals.d_hInstance,
+ NULL);
+ if (!hwndEnt[EntKeyField])
+ Error ("CreateWindow failed");
+
+ hwndEnt[EntValueField] = CreateWindow ("edit", NULL,
+ WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
+ 5, 100, 180, 99,
+ g_qeglobals.d_hwndEntity,
+ (HMENU)IDC_E_VALUE_FIELD,
+ g_qeglobals.d_hInstance,
+ NULL);
+ if (!hwndEnt[EntValueField])
+ Error ("CreateWindow failed");
+
+ g_wndTabs.SubclassDlgItem(IDC_TAB_MODE, CWnd::FromHandle(ghwndEntity));
+ hwndEnt[EntTab] = g_wndTabs.GetSafeHwnd();
+ g_wndTabs.InsertItem(0, "Groups");
+ ::SetParent(g_wndTabs.GetSafeHwnd(), g_qeglobals.d_hwndEntity);
+
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ {
+ g_qeglobals.d_hwndEdit = CreateWindow ("edit", NULL, ES_MULTILINE | ES_READONLY | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER,
+ 5, 100, 180, 99, g_qeglobals.d_hwndEntity, (HMENU)IDC_E_STATUS,
+ g_qeglobals.d_hInstance, NULL);
+ if (!g_qeglobals.d_hwndEdit)
+ Error ("CreateWindow failed");
+ g_wndTabs.InsertItem(0, "Console");
+ g_wndTabs.InsertItem(0, "Textures");
+ }
+ g_wndTabs.InsertItem(0, "Entities");
+ g_wndTabs.ShowWindow(SW_SHOW);
+
+#if 0
+ for (i=0 ; i<12 ; i++)
+ {
+ hwndEnt[EntCheck1 + i] = CreateWindow ("button", NULL,
+ BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE,
+ 5, 100, 180, 99,
+ entwindow,
+ (HMENU)IDC_E_STATUS,
+ main_instance,
+ NULL);
+ if (!hwndEnt[EntCheck1 + i])
+ Error ("CreateWindow failed");
+ }
+#endif
+ SendMessage(hwndEnt[EntList], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+ SendMessage(hwndEnt[EntProps], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+ SendMessage(hwndEnt[EntComment], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+ SendMessage(hwndEnt[EntKeyField], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+ SendMessage(hwndEnt[EntValueField], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+ SendMessage(hwndEnt[EntTab], WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ SendMessage(g_qeglobals.d_hwndEdit, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)TRUE);
+}
+
+
+
+/*
+===============================================================
+
+ENTITY WINDOW
+
+===============================================================
+*/
+
+
+void FillClassList (void)
+{
+ eclass_t *pec;
+ int iIndex;
+
+ SendMessage(hwndEnt[EntList], LB_RESETCONTENT, 0 , 0);
+
+ for (pec = eclass ; pec ; pec = pec->next)
+ {
+ iIndex = SendMessage(hwndEnt[EntList], LB_ADDSTRING, 0 , (LPARAM)pec->name);
+ SendMessage(hwndEnt[EntList], LB_SETITEMDATA, iIndex, (LPARAM)pec);
+ }
+
+}
+
+
+/*
+==============
+WEnt_Create
+==============
+*/
+void WEnt_Create (HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+
+ /* Register the camera class */
+ memset (&wc, 0, sizeof(wc));
+
+ wc.style = CS_NOCLOSE | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC)EntityWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = 0;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject (LTGRAY_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = ENT_WINDOW_CLASS;
+
+ RegisterClass (&wc);
+
+ int nStyle = (g_pParentWnd->CurrentStyle() == QR_QE4) ? QE3_STYLE : QE3_STYLE2;
+ g_qeglobals.d_hwndEntity = CreateWindow (ENT_WINDOW_CLASS ,
+ "Entity",
+ nStyle,
+ 20,
+ 20,
+ 100,
+ 480, // size
+
+ g_qeglobals.d_hwndMain, // parent
+ 0, // no menu
+ hInstance,
+ NULL);
+
+ if (!g_qeglobals.d_hwndEntity )
+ Error ("Couldn't create Entity window");
+}
+
+/*
+==============
+CreateEntityWindow
+==============
+*/
+BOOL CreateEntityWindow(HINSTANCE hInstance)
+{
+ HWND hwndEntityPalette;
+
+ inspector_mode = W_ENTITY;
+
+ WEnt_Create (hInstance);
+
+ hwndEntityPalette = CreateDialog(hInstance, (char *)IDD_ENTITY, g_qeglobals.d_hwndMain, (DLGPROC)NULL);
+ if (!hwndEntityPalette)
+ Error ("CreateDialog failed");
+
+ GetEntityControls (hwndEntityPalette);
+ DestroyWindow (hwndEntityPalette);
+
+ OldFieldWindowProc = (WNDPROC)GetWindowLong (hwndEnt[EntKeyField], GWL_WNDPROC);
+ SetWindowLong (hwndEnt[EntKeyField], GWL_WNDPROC, (long)FieldWndProc);
+ SetWindowLong (hwndEnt[EntValueField], GWL_WNDPROC, (long)FieldWndProc);
+
+ OldEntityListWindowProc = (WNDPROC)GetWindowLong (hwndEnt[EntList], GWL_WNDPROC);
+ SetWindowLong (hwndEnt[EntList], GWL_WNDPROC, (long)EntityListWndProc);
+
+ FillClassList ();
+
+
+ LoadWindowPlacement(g_qeglobals.d_hwndEntity, "EntityWindowPlace");
+ ShowWindow (g_qeglobals.d_hwndEntity, SW_HIDE);
+ SetInspectorMode (W_CONSOLE);
+
+ return TRUE;
+}
+
+/*
+==============
+SetInspectorMode
+==============
+*/
+void SetInspectorMode(int iType)
+{
+ RECT rc;
+ HMENU hMenu = GetMenu( g_qeglobals.d_hwndMain );
+
+ if ((g_pParentWnd->CurrentStyle() == QR_SPLIT || g_pParentWnd->CurrentStyle() == QR_SPLITZ) && (iType == W_TEXTURE || iType == W_CONSOLE))
+ return;
+
+
+ // Is the caller asking us to cycle to the next window?
+
+ if (iType == -1)
+ {
+ if (inspector_mode == W_ENTITY)
+ iType = W_TEXTURE;
+ else if (inspector_mode == W_TEXTURE)
+ iType = W_CONSOLE;
+ else if (inspector_mode == W_CONSOLE)
+ iType = W_GROUP;
+ else
+ iType = W_ENTITY;
+ }
+
+ inspector_mode = iType;
+ switch(iType)
+ {
+
+ case W_ENTITY:
+ SetWindowText(g_qeglobals.d_hwndEntity, "Entity");
+ EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_ENABLED | MF_BYCOMMAND );
+ // entity is always first in the inspector
+ g_wndTabs.SetCurSel(0);
+ break;
+
+ case W_TEXTURE:
+ SetWindowText(g_qeglobals.d_hwndEntity, "Textures");
+ g_pParentWnd->GetTexWnd()->FocusEdit();
+ EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND );
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ g_wndTabs.SetCurSel(1);
+ break;
+
+ case W_CONSOLE:
+ SetWindowText(g_qeglobals.d_hwndEntity, "Console");
+ EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND );
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ g_wndTabs.SetCurSel(2);
+ break;
+
+ case W_GROUP:
+ SetWindowText(g_qeglobals.d_hwndEntity, "Groups");
+ EnableMenuItem( hMenu, ID_MISC_SELECTENTITYCOLOR, MF_GRAYED | MF_DISABLED | MF_BYCOMMAND );
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ g_wndTabs.SetCurSel(3);
+ else
+ g_wndTabs.SetCurSel(1);
+ break;
+
+
+ default:
+ break;
+ }
+
+ GetWindowRect (g_qeglobals.d_hwndEntity, &rc);
+ SizeEntityDlg( rc.right - rc.left - 8, rc.bottom - rc.top - 20);
+
+
+// InvalidateRect(entwindow, NULL, true);
+// ShowWindow (entwindow, SW_SHOW);
+// UpdateWindow (entwindow);
+
+ HWND hFlag = (g_pParentWnd->CurrentStyle() == QR_QE4) ? HWND_TOP : HWND_TOPMOST;
+ SetWindowPos( g_qeglobals.d_hwndEntity, hFlag, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOSIZE | SWP_NOMOVE );
+ RedrawWindow (g_qeglobals.d_hwndEntity, NULL, NULL, RDW_ERASE | RDW_INVALIDATE| RDW_ERASENOW | RDW_UPDATENOW | RDW_ALLCHILDREN);
+}
+
+
+
+
+
+// SetKeyValuePairs
+//
+// Reset the key/value (aka property) listbox and fill it with the
+// k/v pairs from the entity being edited.
+//
+
+void SetKeyValuePairs (bool bClearMD3)
+{
+ epair_t *pep;
+ RECT rc;
+ char sz[4096];
+
+ if (edit_entity == NULL)
+ return;
+
+ // set key/value pair list
+
+ GetWindowRect(hwndEnt[EntProps], &rc);
+ SendMessage(hwndEnt[EntProps], LB_SETCOLUMNWIDTH, (rc.right - rc.left)/2, 0);
+ SendMessage(hwndEnt[EntProps], LB_RESETCONTENT, 0, 0);
+
+ // Walk through list and add pairs
+
+ for (pep = edit_entity->epairs ; pep ; pep = pep->next)
+ {
+ // if the key is less than 8 chars, add a tab for alignment
+ if (strlen(pep->key) > 8)
+ sprintf (sz, "%s\t%s", pep->key, pep->value);
+ else
+ sprintf (sz, "%s\t\t%s", pep->key, pep->value);
+ SendMessage(hwndEnt[EntProps], LB_ADDSTRING, 0, (LPARAM)sz);
+ }
+
+ if (edit_entity->eclass->nShowFlags & ECLASS_MISCMODEL)
+ {
+ // if this is a misc_model
+ // cache the md3 for display later
+ if (bClearMD3)
+ {
+ edit_entity->md3Class = NULL;
+ }
+ //char *pModel = ValueForKey(edit_entity, "model");
+
+ /*
+ if (pModel != NULL)
+ {
+ GetCachedModel(pModel, vMin, vMax);
+ }
+ */
+ }
+
+ Sys_UpdateWindows(W_CAMERA | W_XY);
+
+}
+
+// SetSpawnFlags
+//
+// Update the checkboxes to reflect the flag state of the entity
+//
+void SetSpawnFlags(void)
+{
+ int f;
+ int i;
+ int v;
+
+ f = atoi(ValueForKey (edit_entity, "spawnflags"));
+ for (i=0 ; i<12 ; i++)
+ {
+ v = !!(f&(1<<i));
+ SendMessage(hwndEnt[EntCheck1+i], BM_SETCHECK, v, 0);
+ }
+}
+
+
+// GetSpawnFlags
+//
+// Update the entity flags to reflect the state of the checkboxes
+//
+void GetSpawnFlags(void)
+{
+ int f;
+ int i, v;
+ char sz[32];
+
+ f = 0;
+ for (i=0 ; i<12 ; i++)
+ {
+ v = SendMessage(hwndEnt[EntCheck1+i], BM_GETCHECK, 0, 0);
+ f |= v<<i;
+ }
+
+ sprintf (sz, "%i", f);
+
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ SetKeyValue(b->owner, "spawnflags", sz);
+ }
+ else
+ SetKeyValue (edit_entity, "spawnflags", sz);
+ SetKeyValuePairs ();
+}
+
+// UpdateSel
+//
+// Update the listbox, checkboxes and k/v pairs to reflect the new selection
+//
+BOOL UpdateSel(int iIndex, eclass_t *pec)
+{
+ int i;
+ brush_t *b;
+
+ if (selected_brushes.next == &selected_brushes)
+ {
+ edit_entity = world_entity;
+ multiple_entities = false;
+ }
+ else
+ {
+ edit_entity = selected_brushes.next->owner;
+ for (b=selected_brushes.next->next ; b != &selected_brushes ; b=b->next)
+ {
+ if (b->owner != edit_entity)
+ {
+ multiple_entities = true;
+ break;
+ }
+ }
+ }
+
+ if (iIndex != LB_ERR)
+ SendMessage(hwndEnt[EntList], LB_SETCURSEL, iIndex, 0);
+
+ if (pec == NULL)
+ return TRUE;
+
+ // Set up the description
+
+ SendMessage(hwndEnt[EntComment], WM_SETTEXT, 0,
+ (LPARAM)TranslateString(pec->comments));
+
+ for (i=0 ; i<8 ; i++)
+ {
+ HWND hwnd = hwndEnt[EntCheck1+i];
+ if (pec->flagnames[i] && pec->flagnames[i][0] != 0)
+ {
+ EnableWindow(hwnd, TRUE);
+ SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)pec->flagnames[i]);
+ } else {
+
+ // disable check box
+ SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)" ");
+ EnableWindow(hwnd, FALSE);
+ }
+ }
+
+ SetSpawnFlags();
+ SetKeyValuePairs();
+ return TRUE;
+}
+
+BOOL UpdateEntitySel(eclass_t *pec)
+{
+ int iIndex;
+
+ iIndex = (int)SendMessage(hwndEnt[EntList], LB_FINDSTRINGEXACT,
+ (WPARAM)-1, (LPARAM)pec->name);
+
+ return UpdateSel(iIndex, pec);
+}
+
+// CreateEntity
+//
+// Creates a new entity based on the currently selected brush and entity type.
+//
+
+void CreateEntity(void)
+{
+ eclass_t *pecNew;
+ entity_t *petNew;
+ int i;
+ HWND hwnd;
+ char sz[1024];
+
+ // check to make sure we have a brush
+
+ if (selected_brushes.next == &selected_brushes)
+ {
+ MessageBox(g_qeglobals.d_hwndMain, "You must have a selected brush to create an entity"
+ , "info", 0);
+ return;
+ }
+
+
+ // find out what type of entity we are trying to create
+
+ hwnd = hwndEnt[EntList];
+
+ i = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0);
+
+ if (i < 0)
+ {
+ MessageBox(g_qeglobals.d_hwndMain, "You must have a selected class to create an entity"
+ , "info", 0);
+ return;
+ }
+
+ SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz);
+
+ if (!stricmp(sz, "worldspawn"))
+ {
+ MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0);
+ return;
+ }
+
+ pecNew = Eclass_ForName(sz, false);
+
+ // create it
+
+ petNew = Entity_Create(pecNew);
+
+ if (petNew == NULL)
+ {
+ MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0);
+ return;
+ }
+
+ if (selected_brushes.next == &selected_brushes)
+ edit_entity = world_entity;
+ else
+ edit_entity = selected_brushes.next->owner;
+
+ SetKeyValuePairs();
+ Select_Deselect ();
+ Select_Brush (edit_entity->brushes.onext);
+ Sys_UpdateWindows(W_ALL);
+
+}
+
+
+
+/*
+===============
+AddProp
+
+===============
+*/
+void AddProp()
+{
+ char key[4096];
+ char value[4096];
+
+ if (edit_entity == NULL)
+ return;
+
+ // Get current selection text
+
+ SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(key)-1, (LPARAM)key);
+ SendMessage(hwndEnt[EntValueField], WM_GETTEXT, sizeof(value)-1, (LPARAM)value);
+
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ SetKeyValue(b->owner, key, value);
+ }
+ else
+ SetKeyValue(edit_entity, key, value);
+
+ // refresh the prop listbox
+ SetKeyValuePairs();
+
+ // if it's a plugin entity, perhaps we need to update some drawing parameters
+ // NOTE: perhaps moving this code to a seperate func would help if we need it in other places
+ // TODO: we need to call some update func in the IPluginEntity in case model name changes etc.
+ // ( for the moment only bounding brush is updated ), see UpdateModelBrush in Ritual's Q3Radiant
+ if (edit_entity->eclass->nShowFlags & ECLASS_PLUGINENTITY)
+ {
+ vec3_t mins, maxs;
+ edit_entity->pPlugEnt->GetBounds( mins, maxs );
+ // replace old bounding brush by newly computed one
+ // NOTE: this part is similar to Entity_BuildModelBrush in Ritual's Q3Radiant, it can be
+ // usefull moved into a seperate func
+ brush_t *b,*oldbrush;
+ if (edit_entity->brushes.onext != &edit_entity->brushes)
+ oldbrush = edit_entity->brushes.onext;
+ b = Brush_Create (mins, maxs, &edit_entity->eclass->texdef);
+ Entity_LinkBrush (edit_entity, b);
+ Brush_Build( b, true );
+ Select_Deselect();
+ Brush_AddToList (edit_entity->brushes.onext, &selected_brushes);
+ if (oldbrush)
+ Brush_Free( oldbrush );
+ }
+
+}
+
+/*
+===============
+DelProp
+
+===============
+*/
+void DelProp(void)
+{
+ char sz[4096];
+
+ if (edit_entity == NULL)
+ return;
+
+ // Get current selection text
+
+ SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(sz)-1, (LPARAM)sz);
+
+ if (multiple_entities)
+ {
+ brush_t *b;
+
+ for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
+ DeleteKey(b->owner, sz);
+ }
+ else
+ DeleteKey(edit_entity, sz);
+
+ // refresh the prop listbox
+
+ SetKeyValuePairs();
+}
+
+BOOL GetSelectAllCriteria(CString &strKey, CString &strVal) {
+ char sz[4096];
+ HWND hwnd = hwndEnt[EntProps];
+ int i = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
+ if (i >= 0 && inspector_mode == W_ENTITY) {
+ SendMessage(hwndEnt[EntKeyField], WM_GETTEXT, sizeof(sz), (LPARAM)sz);
+ strKey = sz;
+ SendMessage(hwndEnt[EntValueField], WM_GETTEXT, sizeof(sz), (LPARAM)sz);
+ strVal = sz;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+===============
+EditProp
+
+===============
+*/
+void EditProp(void)
+{
+ int i;
+ HWND hwnd;
+ char sz[4096];
+ char *val;
+
+ if (edit_entity == NULL)
+ return;
+
+ hwnd = hwndEnt[EntProps];
+
+ // Get current selection text
+
+ i = SendMessage(hwnd, LB_GETCURSEL, 0, 0);
+
+ if (i < 0)
+ return;
+
+ SendMessage(hwnd, LB_GETTEXT, i, (LPARAM)sz);
+
+ // strip it down to the key name
+
+ for(i=0;sz[i] != '\t';i++)
+ ;
+
+ sz[i] = '\0';
+
+ val = sz + i + 1;
+ if (*val == '\t')
+ val++;
+
+ SendMessage(hwndEnt[EntKeyField], WM_SETTEXT, 0, (LPARAM)sz);
+ SendMessage(hwndEnt[EntValueField], WM_SETTEXT, 0, (LPARAM)val);
+}
+
+
+HDWP defer;
+int col;
+void MOVE(HWND e, int x, int y, int w, int h, HWND hwndPlacement = HWND_TOP, int swp = SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOZORDER)
+{
+// defer=DeferWindowPos(defer,e,HWND_TOP,col+(x),y,w,h,SWP_SHOWWINDOW);
+// MoveWindow (e, col+x, y, w, h, FALSE);
+ SetWindowPos (e, hwndPlacement, col+x, y, w, h, swp);
+}
+
+
+/*
+===============
+SizeEnitityDlg
+
+Positions all controls so that the active inspector
+is displayed correctly and the inactive ones are
+off the side
+===============
+*/
+void SizeEntityDlg(int iWidth, int iHeight)
+{
+ int y, x, xCheck, yCheck;
+ int i, iRow;
+ int w, h;
+
+ if (iWidth < 32 || iHeight < 32)
+ return;
+
+ SendMessage( g_qeglobals.d_hwndEntity, WM_SETREDRAW, 0, 0);
+ iHeight -= 24;
+
+
+ //==========================================
+
+
+ //
+ // console
+ //
+ if (inspector_mode == W_CONSOLE)
+ {
+ col = 0;
+ }
+ else
+ {
+ col = iWidth;
+ }
+
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ MOVE(g_qeglobals.d_hwndEdit, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) );
+
+ //==========================================
+
+ //
+ // texture controls
+ //
+ if (inspector_mode == W_TEXTURE)
+ {
+ col = 0;
+ }
+ else
+ {
+ col = iWidth;
+ }
+
+ if (g_pParentWnd->CurrentStyle() > 0 && g_pParentWnd->CurrentStyle() < 3)
+ MOVE(g_qeglobals.d_hwndTexture, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) );
+
+ if (inspector_mode == W_GROUP)
+ {
+ col = 0;
+ }
+ else
+ {
+ col = iWidth;
+ }
+
+ MOVE(g_qeglobals.d_hwndGroup, DlgXBorder, DlgYBorder, iWidth - (2 * DlgXBorder), iHeight - (2 * DlgYBorder) );
+
+ //==========================================
+
+ //
+ // entity controls
+ //
+ if (inspector_mode == W_ENTITY)
+ {
+ col = 0;
+ }
+ else
+ {
+ col = iWidth;
+ }
+
+
+
+ // top half includes the entity list (2/3) and the
+ // comments (1/3) - 2 gaps, above and below.
+
+ y = iHeight/2;
+ y -= 2 * DlgYBorder;
+ y = y / 3;
+ w = iWidth - (2 * DlgXBorder);
+ MOVE(hwndEnt[EntList], DlgXBorder, DlgYBorder, w, 2 * y);
+
+ MOVE(hwndEnt[EntComment], DlgXBorder, 2 * DlgYBorder + 2 * y, w, y - (2 * DlgYBorder));
+
+ // bottom half includes flags (fixed), k/v pairs,
+ // and buttons (fixed).
+
+ // xCheck = width of a single check box
+ // yCheck = distance from top of one check to the next
+
+ xCheck = (iWidth - (2 * DlgXBorder)) / 3;
+ yCheck = 18;
+
+ x = DlgXBorder;
+
+ for (iRow = 0; iRow <= 12; iRow += 4)
+ {
+ y = iHeight/2;
+
+ for (i = 0; i < 4; i++)
+ {
+ MOVE(hwndEnt[EntCheck1 + i + iRow],
+ x, y, xCheck, yCheck);
+ y += yCheck;
+ }
+
+ x += xCheck;
+ }
+
+ //
+ // properties scroll box
+ //
+ y = iHeight/2 + 4 * yCheck;
+
+ w = iWidth - (2 * DlgXBorder);
+ h = (iHeight - (yCheck * 5 + 2 * DlgYBorder) ) - y;
+
+ MOVE(hwndEnt[EntProps], DlgXBorder, y, w, h);
+
+ y += h + DlgYBorder;
+
+ //
+ // key / value fields
+ //
+ w = iWidth-(DlgXBorder+45);
+ MOVE(hwndEnt[EntKeyLabel], DlgXBorder, y, 40, yCheck);
+ MOVE(hwndEnt[EntKeyField], DlgXBorder+40, y, w, yCheck);
+ y += yCheck;
+
+ MOVE(hwndEnt[EntValueLabel], DlgXBorder, y, 40, yCheck);
+ MOVE(hwndEnt[EntValueField], DlgXBorder+40, y, w, yCheck);
+ y += yCheck;
+
+ //
+ // angle check boxes
+ //
+ y += 2;
+ i = y;
+ x = DlgXBorder;
+
+ xCheck = yCheck*2;
+
+ MOVE(hwndEnt[EntDir135], x, y, xCheck, yCheck);
+ y += yCheck;
+
+ MOVE(hwndEnt[EntDir180], x, y, xCheck, yCheck);
+ y += yCheck;
+
+ MOVE(hwndEnt[EntDir225], x, y, xCheck, yCheck);
+
+ y = i;
+ x += xCheck;
+
+
+ MOVE(hwndEnt[EntDir90], x, y, xCheck, yCheck);
+ y += yCheck;
+ y += yCheck;
+
+ MOVE(hwndEnt[EntDir270], x, y, xCheck, yCheck);
+
+ y = i;
+ x += xCheck;
+
+
+ MOVE(hwndEnt[EntDir45], x, y, xCheck, yCheck);
+ y += yCheck;
+
+ MOVE(hwndEnt[EntDir0], x, y, xCheck, yCheck);
+ y += yCheck;
+
+ MOVE(hwndEnt[EntDir315], x, y, xCheck, yCheck);
+
+ y = i + yCheck/2;
+ x += xCheck + xCheck/2;
+
+
+ MOVE(hwndEnt[EntDirUp], x, y, xCheck, yCheck);
+ y += yCheck;
+
+ MOVE(hwndEnt[EntDirDown], x, y, xCheck, yCheck);
+
+ y = i;
+ x += 1.5 * xCheck;
+
+ MOVE(hwndEnt[EntDelProp], x, y, xCheck*2, yCheck);
+ y += yCheck + 4;
+
+ MOVE(hwndEnt[EntAssignSounds], x, y, xCheck*2, yCheck);
+ y += yCheck;
+ MOVE(hwndEnt[EntAssignModels], x, y, xCheck*2, yCheck);
+
+ // tab selector is always visible
+ col = 0;
+ iHeight += 24;
+ MOVE(hwndEnt[EntTab], 0,0,iWidth,iHeight, HWND_BOTTOM, SWP_NOACTIVATE | SWP_NOCOPYBITS);
+
+ SendMessage( g_qeglobals.d_hwndEntity, WM_SETREDRAW, 1, 0);
+// InvalidateRect(entwindow, NULL, TRUE);
+}
+
+void AssignSound()
+{
+ CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ AddSlash(strBasePath);
+ CString strPath = strBasePath;
+ strPath += "sound\\";
+
+ CWaveOpen dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Sound files (*.wav)|*.wav||", g_pParentWnd);
+ dlgFile.m_ofn.lpstrInitialDir = strPath;
+ if (dlgFile.DoModal() == IDOK)
+ {
+ SendMessage(hwndEnt[EntKeyField], WM_SETTEXT, 0, (LPARAM)"noise");
+ CString str = dlgFile.GetPathName().GetBuffer(0);
+ str.MakeLower();
+ strBasePath.MakeLower();
+ QE_ConvertDOSToUnixName(str.GetBuffer(0), str.GetBuffer(0));
+ QE_ConvertDOSToUnixName(strBasePath.GetBuffer(0), strBasePath.GetBuffer(0));
+ int n = str.Find(strBasePath);
+ if (n == 0)
+ {
+ str = str.Right(str.GetLength() - strBasePath.GetLength());
+ }
+
+ SendMessage(hwndEnt[EntValueField], WM_SETTEXT, 0, (LPARAM)str.GetBuffer(0));
+ AddProp();
+ g_pParentWnd->GetXYWnd()->SetFocus();
+ }
+}
+
+void AssignModel()
+{
+ CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ AddSlash(strBasePath);
+ CString strPath = strBasePath;
+ strPath += "models\\mapobjects\\";
+
+ CFileDialog dlgFile(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Model files (*.md3)|*.md3||", g_pParentWnd);
+ dlgFile.m_ofn.lpstrInitialDir = strPath;
+ if (dlgFile.DoModal() == IDOK)
+ {
+ SendMessage(hwndEnt[EntKeyField], WM_SETTEXT, 0, (LPARAM)"model");
+ CString str = dlgFile.GetPathName().GetBuffer(0);
+ str.MakeLower();
+ strBasePath.MakeLower();
+ QE_ConvertDOSToUnixName(str.GetBuffer(0), str.GetBuffer(0));
+ QE_ConvertDOSToUnixName(strBasePath.GetBuffer(0), strBasePath.GetBuffer(0));
+ int n = str.Find(strBasePath);
+ if (n == 0)
+ {
+ str = str.Right(str.GetLength() - strBasePath.GetLength());
+ }
+
+ SendMessage(hwndEnt[EntValueField], WM_SETTEXT, 0, (LPARAM)str.GetBuffer(0));
+ AddProp();
+ edit_entity->md3Class = NULL;
+ edit_entity->brushes.onext->bModelFailed = false;
+ g_pParentWnd->GetXYWnd()->SetFocus();
+ }
+}
+
+
+/*
+=========================
+EntityWndProc
+=========================
+*/
+BOOL CALLBACK EntityWndProc(
+ HWND hwndDlg, // handle to dialog box
+ UINT uMsg, // message
+ WPARAM wParam, // first message parameter
+ LPARAM lParam) // second message parameter
+{
+ LPNMHDR lpnmh = NULL;
+ RECT rc;
+
+ GetClientRect(hwndDlg, &rc);
+
+ switch (uMsg)
+ {
+
+ case WM_CHAR :
+ {
+ char c = toupper(LOWORD(wParam));
+ // escape: hide the window
+ if (c == 27)
+ ShowWindow(hwndDlg, SW_HIDE);
+ if (c == 'N')
+ g_pParentWnd->PostMessage(WM_COMMAND, ID_VIEW_ENTITY, 0);
+ else
+ if (c == 'O')
+ g_pParentWnd->PostMessage(WM_COMMAND, ID_VIEW_CONSOLE, 0);
+ else
+ if (c == 'T')
+ g_pParentWnd->PostMessage(WM_COMMAND, ID_VIEW_TEXTURE, 0);
+ else
+ if (c == 'G')
+ g_pParentWnd->PostMessage(WM_COMMAND, ID_VIEW_GROUPS, 0);
+ else
+ DefWindowProc (hwndDlg, uMsg, wParam, lParam);
+ break;
+ }
+
+ case WM_NOTIFY:
+ lpnmh = reinterpret_cast<LPNMHDR>(lParam);
+ if (lpnmh->hwndFrom == g_wndTabs.GetSafeHwnd()) {
+ if ( lpnmh->code == TCN_SELCHANGE)
+ {
+ int n = g_wndTabs.GetCurSel();
+ if (g_pParentWnd->CurrentStyle() == 2 || g_pParentWnd->CurrentStyle() == 1)
+ {
+ if (n == 0) {
+ SetInspectorMode(W_ENTITY);
+ } else if (n == 1) {
+ SetInspectorMode(W_TEXTURE);
+ } else if (n == 2) {
+ SetInspectorMode(W_CONSOLE);
+ } else {
+ SetInspectorMode(W_GROUP);
+ }
+ }
+ else
+ {
+ if (n == 0) {
+ SetInspectorMode(W_ENTITY);
+ } else if (n == 1) {
+ SetInspectorMode(W_GROUP);
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_SIZE:
+
+ DefWindowProc (hwndDlg, uMsg, wParam, lParam);
+ break;
+
+ case WM_DESTROY:
+ SaveWindowPlacement(g_qeglobals.d_hwndEntity, "EntityWindowPlace");
+ DefWindowProc(hwndDlg, uMsg, wParam, lParam);
+ break;
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpmmi;
+
+ lpmmi = (LPMINMAXINFO) lParam;
+ lpmmi->ptMinTrackSize.x = 320;
+ lpmmi->ptMinTrackSize.y = 500;
+ }
+ return 0;
+
+ case WM_WINDOWPOSCHANGING:
+ {
+ LPWINDOWPOS lpwp;
+ lpwp = (LPWINDOWPOS) lParam;
+
+ DefWindowProc (hwndDlg, uMsg, wParam, lParam);
+
+ lpwp->flags |= SWP_NOCOPYBITS;
+ SizeEntityDlg(lpwp->cx-8, lpwp->cy-32);
+ return 0;
+
+ }
+ return 0;
+
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+
+ case IDC_BTN_ASSIGNSOUND:
+ AssignSound();
+ break;
+
+ case IDC_BTN_ASSIGNMODEL:
+ AssignModel();
+ break;
+
+ case IDC_E_DELPROP:
+ DelProp();
+ SetFocus (g_qeglobals.d_hwndCamera);
+ break;
+
+ case IDC_E_0:
+ SetKeyValue (edit_entity, "angle", "360");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_45:
+ SetKeyValue (edit_entity, "angle", "45");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_90:
+ SetKeyValue (edit_entity, "angle", "90");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_135:
+ SetKeyValue (edit_entity, "angle", "135");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_180:
+ SetKeyValue (edit_entity, "angle", "180");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_225:
+ SetKeyValue (edit_entity, "angle", "225");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_270:
+ SetKeyValue (edit_entity, "angle", "270");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_315:
+ SetKeyValue (edit_entity, "angle", "315");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_UP:
+ SetKeyValue (edit_entity, "angle", "-1");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+ case IDC_E_DOWN:
+ SetKeyValue (edit_entity, "angle", "-2");
+ SetFocus (g_qeglobals.d_hwndCamera);
+ SetKeyValuePairs ();
+ break;
+
+ case IDC_BTN_HIDE:
+ ::PostMessage(g_qeglobals.d_hwndMain, WM_COMMAND, ID_VIEW_CAMERATOGGLE, 0);
+ break;
+
+ case IDC_CHECK1:
+ case IDC_CHECK2:
+ case IDC_CHECK3:
+ case IDC_CHECK4:
+ case IDC_CHECK5:
+ case IDC_CHECK6:
+ case IDC_CHECK7:
+ case IDC_CHECK8:
+ case IDC_CHECK9:
+ case IDC_CHECK10:
+ case IDC_CHECK11:
+ case IDC_CHECK12:
+ GetSpawnFlags();
+ SetFocus (g_qeglobals.d_hwndCamera);
+ break;
+
+
+ case IDC_E_PROPS:
+ switch (HIWORD(wParam))
+ {
+ case LBN_SELCHANGE:
+
+ EditProp();
+ return TRUE;
+ }
+ break;
+
+ case IDC_E_LIST:
+
+ switch (HIWORD(wParam)) {
+
+ case LBN_SELCHANGE:
+ {
+ int iIndex;
+ eclass_t *pec;
+
+ iIndex = SendMessage(hwndEnt[EntList], LB_GETCURSEL, 0, 0);
+ pec = (eclass_t *)SendMessage(hwndEnt[EntList], LB_GETITEMDATA,
+ iIndex, 0);
+
+ UpdateSel(iIndex, pec);
+
+ return TRUE;
+ break;
+ }
+
+ case LBN_DBLCLK:
+ CreateEntity ();
+ SetFocus (g_qeglobals.d_hwndCamera);
+ break;
+ }
+ break;
+
+
+ default:
+ return DefWindowProc( hwndDlg, uMsg, wParam, lParam );
+ }
+
+ return 0;
+ }
+
+ return DefWindowProc (hwndDlg, uMsg, wParam, lParam);
+}
+
diff --git a/q3radiant/Win_main.cpp b/q3radiant/Win_main.cpp
new file mode 100755
index 0000000..342749e
--- /dev/null
+++ b/q3radiant/Win_main.cpp
@@ -0,0 +1,1085 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+#include <process.h>
+#include "mru.h"
+#include "entityw.h"
+#include "PrefsDlg.h"
+
+static HWND s_hwndToolbar;
+
+BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize);
+BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize);
+
+static HWND CreateMyStatusWindow(HINSTANCE hInst);
+static HWND CreateToolBar(HINSTANCE hinst);
+
+extern void WXY_Print( void );
+
+/*
+==============================================================================
+
+ MENU
+
+==============================================================================
+*/
+
+void OpenDialog (void);
+void SaveAsDialog (bool bRegion);
+qboolean ConfirmModified (void);
+void Select_Ungroup (void);
+
+void QE_ExpandBspString (char *bspaction, char *out, char *mapname, bool useTemps)
+{
+ char *in;
+ char src[2048];
+ char rsh[2048];
+ char base[2048];
+
+ strcpy(src, mapname);
+ strlwr(src);
+ in = strstr(src, "maps/");
+ if (!in)
+ {
+ in = strstr(src, "maps\\");
+ }
+ if (in)
+ {
+ in += 5;
+ strcpy(base, in);
+ in = base;
+ while (*in)
+ {
+ if (*in == '\\')
+ {
+ *in = '/';
+ }
+ in++;
+ }
+ }
+ else
+ {
+ ExtractFileName (mapname, base);
+ }
+
+ if (useTemps) {
+ CString str;
+ CString strExt = "map";
+ if ( strstr(mapname, ".reg") ) {
+ strExt = "reg";
+ }
+ str.Format("%s/maps/%i.%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), ::GetTickCount(), strExt);
+ CopyFile(mapname, str, FALSE);
+ sprintf (src, "-tempname %s %s/maps/%s", str, ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
+ } else {
+ sprintf (src, "%s/maps/%s", ValueForKey(g_qeglobals.d_project_entity, "remotebasepath"), base);
+ }
+ strcpy (rsh, ValueForKey(g_qeglobals.d_project_entity, "rshcmd"));
+
+ QE_ConvertDOSToUnixName(src, src);
+
+ in = ValueForKey( g_qeglobals.d_project_entity, bspaction );
+ while (*in)
+ {
+ if (in[0] == '!')
+ {
+ strcpy (out, rsh);
+ out += strlen(rsh);
+ in++;
+ continue;
+ }
+ if (in[0] == '$')
+ {
+ strcpy (out, src);
+ out += strlen(src);
+ in++;
+ continue;
+ }
+ if (in[0] == '@')
+ {
+ *out++ = '"';
+ in++;
+ continue;
+ }
+ *out++ = *in++;
+ }
+ *out = 0;
+}
+
+void FindReplace(CString& strContents, const char* pTag, const char* pValue)
+{
+ if (strcmp(pTag, pValue) == 0)
+ return;
+ for (int nPos = strContents.Find(pTag); nPos >= 0; nPos = strContents.Find(pTag))
+ {
+ int nRightLen = strContents.GetLength() - strlen(pTag) - nPos;
+ CString strLeft = strContents.Left(nPos);
+ CString strRight = strContents.Right(nRightLen);
+ strLeft += pValue;
+ strLeft += strRight;
+ strContents = strLeft;
+ }
+}
+
+
+
+HWND g_hWnd = NULL;
+HANDLE g_hToolThread = NULL;
+CString g_strParams;
+
+UINT ToolThread(LPVOID pParam)
+{
+ char* p = reinterpret_cast<char*>(pParam);
+ if (g_PrefsDlg.m_bPAK)
+ RunTools(p, g_hWnd, g_PrefsDlg.m_strPAKFile);
+ else
+ RunTools(p, g_hWnd, "");
+ g_hToolThread = NULL;
+ delete []p;
+ return 0;
+}
+
+void ThreadTools(char* p)
+{
+ CWinThread* pThread = AfxBeginThread(ToolThread, reinterpret_cast<LPVOID>(p));
+ g_hToolThread = pThread->m_hThread;
+}
+
+HWND g_hwndFoundIt = NULL;
+
+BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) {
+ char buff[1024];
+ const char* p = reinterpret_cast<const char*>(lParam);
+ GetWindowText(hwnd, buff, 1024);
+ if (!strcmpi(p, buff)) {
+ g_hwndFoundIt = hwnd;
+ return 1;
+ }
+ return 1;
+}
+
+
+HWND FindAnyWindow(const char *pTitle) {
+ HWND hwndDesktop = GetDesktopWindow();
+ g_hwndFoundIt = NULL;
+ if ( hwndDesktop ) {
+ EnumChildWindows(hwndDesktop, (WNDENUMPROC)EnumChildProc, reinterpret_cast<LPARAM>(pTitle));
+ }
+ return g_hwndFoundIt;
+}
+
+
+const UINT wm_AddCommand = RegisterWindowMessage( "Q3MPC_AddCommand" );
+
+CTime g_tBegin;
+void RunBsp (char *command)
+{
+ char sys[2048];
+ char batpath[2048];
+ char outputpath[2048];
+ char temppath[1024];
+ char name[2048];
+ char cWork[2048];
+ FILE *hFile;
+ BOOL ret;
+ PROCESS_INFORMATION ProcessInformation;
+ STARTUPINFO startupinfo;
+ HWND hwndPClient = NULL;
+
+ g_hWnd = g_pParentWnd->GetSafeHwnd();
+ SetInspectorMode(W_CONSOLE);
+ g_tBegin = CTime::GetCurrentTime();
+
+
+ DWORD dwExitcode;
+ ret = GetExitCodeProcess (g_hToolThread, &dwExitcode);
+ if (dwExitcode != STILL_ACTIVE)
+ g_hToolThread = NULL;
+
+ if (bsp_process || g_hToolThread)
+ {
+ Sys_Printf ("BSP is still going...\n");
+ return;
+ }
+
+ outputpath[0] = '\0';
+ GetTempPath(512, temppath);
+
+ CString strOutFile = temppath;
+ AddSlash(strOutFile);
+ strOutFile += "junk.txt";
+
+ sprintf (outputpath, " >>%s\r\n", strOutFile);
+
+ strcpy (name, currentmap);
+ if (region_active)
+ {
+ Map_SaveFile (name, false);
+ StripExtension (name);
+ strcat (name, ".reg");
+ }
+
+ Map_SaveFile (name, region_active);
+
+ // FIXME: this code just gets worse and worse
+ CString strPath, strFile;
+
+ char *rsh = ValueForKey(g_qeglobals.d_project_entity, "rshcmd");
+ if (rsh == NULL)
+ {
+ ExtractPath_and_Filename(name, strPath, strFile);
+ AddSlash(strPath);
+ BuildShortPathName(strPath, cWork, 1024);
+ strcat(cWork, strFile);
+ }
+ else
+ {
+ strcpy(cWork, name);
+ }
+
+ hwndPClient = FindWindow(NULL, "Q3Map Process Client");
+ if ( hwndPClient == NULL ) {
+ hwndPClient = FindAnyWindow("Q3Map Process Client");
+ }
+
+ Sys_Printf("Window info for Process Client %i\n", reinterpret_cast<int>(hwndPClient));
+
+ bool processServer = (rsh && strlen(rsh) > 0 && hwndPClient);
+
+ QE_ExpandBspString (command, sys, cWork, processServer);
+
+ // if we can find the q3map process server running
+ // we will submit maps to it instead of via createprocess
+ //
+ if (processServer)
+ {
+ CString str;
+ char cBuff[2048];
+ char *pStart = sys;
+ char *pEnd = strstr(pStart, "&&");
+ while (pEnd)
+ {
+ int nLen = pEnd-pStart-1;
+ strncpy(cBuff, pStart, nLen);
+ cBuff[nLen] = 0;
+ str = cBuff;
+ FindReplace(str, rsh, "");
+ str.TrimLeft(' ');
+ str.TrimRight(' ');
+ ATOM a = GlobalAddAtom(str);
+ PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a);
+ pStart = pEnd+2;
+ pEnd = strstr(pStart, "&&");
+ }
+ str = pStart;
+ FindReplace(str, rsh, "");
+ str.TrimLeft(' ');
+ str.TrimRight(' ');
+ ATOM a = GlobalAddAtom(str);
+ PostMessage(hwndPClient, wm_AddCommand, 0, (LPARAM)a);
+ Sys_Printf("Commands sent to Q3Map Process Client\n");
+ return;
+ }
+
+ CString strSys = sys;
+
+ FindReplace(strSys, "&&", outputpath);
+ strcpy(sys, strSys);
+ strcat(sys, outputpath);
+
+ if (g_PrefsDlg.m_bInternalBSP)
+ {
+ g_tBegin = CTime::GetCurrentTime();
+ strSys.MakeLower();
+ char* p = new char[strSys.GetLength()+1];
+ strcpy(p, strSys.GetBuffer(0));
+ ThreadTools(p);
+ }
+ else
+ {
+ Sys_ClearPrintf ();
+ Sys_Printf ("==================\nRunning bsp command...\n");
+ Sys_Printf ("\n%s\n", sys);
+
+ //++timo removed the old way BSP commands .. dumping to junk.txt doesn't work on my win98 box
+ // FIXME : will most likely break Quake2 BSP commands, is fitted to a one-lined sys command
+ //
+ // write qe3bsp.bat
+ //
+
+ sprintf (batpath, "%sqe3bsp.bat", temppath);
+ hFile = fopen(batpath, "w");
+ if (!hFile)
+ Error ("Can't write to %s", batpath);
+ fprintf (hFile, sys);
+ fclose (hFile);
+
+ Pointfile_Delete ();
+
+ // delete junk.txt file
+ remove(strOutFile);
+
+ GetStartupInfo (&startupinfo);
+
+ ret = CreateProcess(
+ batpath,
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ &startupinfo,
+ &ProcessInformation
+ );
+
+ if (!ret)
+ Error ("CreateProcess failed");
+
+ bsp_process = ProcessInformation.hProcess;
+
+ Sleep (100); // give the new process a chance to open it's window
+
+ BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top
+#if 0
+ //
+ // write qe3bsp.bat
+ //
+ sprintf (batpath, "%sqe3bsp.bat", temppath);
+ hFile = fopen(batpath, "w");
+ if (!hFile)
+ Error ("Can't write to %s", batpath);
+ fprintf (hFile, sys);
+ fclose (hFile);
+
+ //
+ // write qe3bsp2.bat
+ //
+ sprintf (batpath, "%sqe3bsp2.bat", temppath);
+ hFile = fopen(batpath, "w");
+ if (!hFile)
+ Error ("Can't write to %s", batpath);
+ fprintf (hFile, "%sqe3bsp.bat > %s", temppath, outputpath);
+ fclose (hFile);
+
+ Pointfile_Delete ();
+
+ GetStartupInfo (&startupinfo);
+
+ ret = CreateProcess(
+ batpath, // pointer to name of executable module
+ NULL, // pointer to command line string
+ NULL, // pointer to process security attributes
+ NULL, // pointer to thread security attributes
+ FALSE, // handle inheritance flag
+ 0 /*DETACHED_PROCESS*/, // creation flags
+ NULL, // pointer to new environment block
+ NULL, // pointer to current directory name
+ &startupinfo, // pointer to STARTUPINFO
+ &ProcessInformation // pointer to PROCESS_INFORMATION
+ );
+
+ if (!ret)
+ Error ("CreateProcess failed");
+
+ bsp_process = ProcessInformation.hProcess;
+
+ Sleep (100); // give the new process a chance to open it's window
+
+ //BringWindowToTop( g_qeglobals.d_hwndMain ); // pop us back on top
+ //SetFocus (g_qeglobals.d_hwndCamera);
+#endif
+ }
+}
+
+void DLLBuildDone()
+{
+ g_hToolThread = NULL;
+ CTime tEnd = CTime::GetCurrentTime();
+ CTimeSpan tElapsed = tEnd - g_tBegin;
+ CString strElapsed;
+ strElapsed.Format("Run time was %i hours, %i minutes and %i seconds", tElapsed.GetHours(), tElapsed.GetMinutes(), tElapsed.GetSeconds());
+ Sys_Printf(strElapsed.GetBuffer(0));
+ Pointfile_Check();
+
+ if (g_PrefsDlg.m_bRunQuake == TRUE)
+ {
+ char cCurDir[1024];
+ GetCurrentDirectory(1024, cCurDir);
+ CString strExePath = g_PrefsDlg.m_strQuake2;
+ CString strOrgPath;
+ CString strOrgFile;
+ ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
+ if (g_PrefsDlg.m_bSetGame == TRUE) // run in place with set game.. don't copy map
+ {
+ CString strBasePath = ValueForKey(g_qeglobals.d_project_entity, "basepath");
+ strExePath += " +set game ";
+ strExePath += strBasePath;
+ WinExec(strExePath, SW_SHOW);
+ }
+ else
+ {
+ CString strCopyPath = strExePath;
+ char* pBuffer = strCopyPath.GetBufferSetLength(_MAX_PATH + 1);
+ pBuffer[strCopyPath.ReverseFind('\\') + 1] = '\0';
+ strCopyPath.ReleaseBuffer();
+ SetCurrentDirectory(strCopyPath);
+ CString strOrgPath;
+ CString strOrgFile;
+ ExtractPath_and_Filename(currentmap, strOrgPath, strOrgFile);
+ AddSlash(strCopyPath);
+ FindReplace(strOrgFile, ".map", ".bsp");
+ strCopyPath += "\\baseq2\\maps\\";
+ strCopyPath += strOrgFile;
+ AddSlash(strOrgPath);
+ strOrgPath += strOrgFile;
+ bool bRun = (strOrgPath.CompareNoCase(strCopyPath) == 0);
+ if (!bRun)
+ bRun = (CopyFile(strOrgPath, strCopyPath, FALSE) == TRUE);
+ if (bRun)
+ {
+ FindReplace(strOrgFile, ".bsp", "");
+ strExePath += " +map ";
+ strExePath += strOrgFile;
+ WinExec(strExePath, SW_SHOW);
+ }
+ }
+ SetCurrentDirectory(cCurDir);
+ }
+
+}
+
+/*
+=============
+DoColor
+
+=============
+*/
+
+class CMyColorDialog : public CColorDialog
+{
+ DECLARE_DYNCREATE(CMyColorDialog);
+ // Construction
+public:
+ CMyColorDialog( COLORREF clrInit = 0, DWORD dwFlags = 0, CWnd*
+pParentWnd = NULL );
+ // Statics
+protected:
+ enum { NCUSTCOLORS = 16 };
+ static COLORREF c_CustColors[NCUSTCOLORS];
+ static COLORREF c_LastCustColors[NCUSTCOLORS];
+ static bool c_NeedToInitCustColors;
+protected:
+ static void InitCustColors();
+ static void SaveCustColors();
+ // Dialog Data
+protected:
+ //{{AFX_DATA(CMyColorDialog)
+ //}}AFX_DATA
+ // Overrides
+protected:
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CMyColorDialog)
+public:
+ virtual int DoModal();
+protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+ // Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CMyColorDialog)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+IMPLEMENT_DYNCREATE(CMyColorDialog, CColorDialog)
+
+bool CMyColorDialog::c_NeedToInitCustColors = true;
+COLORREF CMyColorDialog::c_CustColors[];
+COLORREF CMyColorDialog::c_LastCustColors[];
+
+#define SECTION _T("Custom Colors")
+
+void CMyColorDialog::InitCustColors() {
+ for (int i = 0; i < NCUSTCOLORS; i++) {
+ CString entry; entry.Format("%d",i);
+ c_LastCustColors[i] = c_CustColors[i] =
+ ::AfxGetApp()->GetProfileInt(SECTION,entry,RGB(255,255,255));
+ }
+ c_NeedToInitCustColors= false;
+}
+
+void CMyColorDialog::SaveCustColors() {
+ for (int i = 0; i < NCUSTCOLORS; i++) {
+ if (c_LastCustColors[i] != c_CustColors[i]) {
+ CString entry; entry.Format("%d",i);
+ if (c_CustColors[i] == RGB(255,255,255)) {
+ ::AfxGetApp()->WriteProfileString(SECTION,entry,NULL);
+ } else {
+ ::AfxGetApp()->WriteProfileInt(SECTION, entry,c_CustColors[i]);
+ }
+ c_LastCustColors[i] = c_CustColors[i];
+ }
+ }
+}
+
+CMyColorDialog::CMyColorDialog( COLORREF clrInit, DWORD dwFlags,
+ CWnd* pParentWnd) : CColorDialog(clrInit,dwFlags,pParentWnd)
+{
+ //{{AFX_DATA_INIT(CMyColorDialog)
+ //}}AFX_DATA_INIT
+ if (c_NeedToInitCustColors) {
+ InitCustColors();
+ }
+ m_cc.lpCustColors = c_CustColors;
+}
+
+int CMyColorDialog::DoModal() {
+ int code = CColorDialog::DoModal();
+ SaveCustColors();
+ return code;
+}
+
+void CMyColorDialog::DoDataExchange(CDataExchange* pDX) {
+ // overridden (calls this base class)
+ CColorDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CMyColorDialog)
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CMyColorDialog, CColorDialog)
+//{{AFX_MSG_MAP(CMyColorDialog)
+//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void DoNewColor(int* i1, int* i2, int* i3)
+{
+ COLORREF cr = (*i1) +
+ ((*i2) <<8) +
+ ((*i3) <<16);
+ CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT);
+ if (dlg.DoModal() == IDOK)
+ {
+ *i1 = (dlg.m_cc.rgbResult & 255);
+ *i2 = ((dlg.m_cc.rgbResult >> 8) & 255);
+ *i3 = ((dlg.m_cc.rgbResult >> 16) & 255);
+ }
+
+}
+
+
+qboolean DoColor(int iIndex)
+{
+
+ COLORREF cr = (int)(g_qeglobals.d_savedinfo.colors[iIndex][0]*255) +
+ (((int)(g_qeglobals.d_savedinfo.colors[iIndex][1]*255))<<8) +
+ (((int)(g_qeglobals.d_savedinfo.colors[iIndex][2]*255))<<16);
+ CMyColorDialog dlg(cr, CC_FULLOPEN | CC_RGBINIT);
+ if (dlg.DoModal() == IDOK)
+ {
+ g_qeglobals.d_savedinfo.colors[iIndex][0] = (dlg.m_cc.rgbResult&255)/255.0;
+ g_qeglobals.d_savedinfo.colors[iIndex][1] = ((dlg.m_cc.rgbResult>>8)&255)/255.0;
+ g_qeglobals.d_savedinfo.colors[iIndex][2] = ((dlg.m_cc.rgbResult>>16)&255)/255.0;
+
+ /*
+ ** scale colors so that at least one component is at 1.0F
+ ** if this is meant to select an entity color
+ */
+ if ( iIndex == COLOR_ENTITY )
+ {
+ float largest = 0.0F;
+
+ if ( g_qeglobals.d_savedinfo.colors[iIndex][0] > largest )
+ largest = g_qeglobals.d_savedinfo.colors[iIndex][0];
+ if ( g_qeglobals.d_savedinfo.colors[iIndex][1] > largest )
+ largest = g_qeglobals.d_savedinfo.colors[iIndex][1];
+ if ( g_qeglobals.d_savedinfo.colors[iIndex][2] > largest )
+ largest = g_qeglobals.d_savedinfo.colors[iIndex][2];
+
+ if ( largest == 0.0F )
+ {
+ g_qeglobals.d_savedinfo.colors[iIndex][0] = 1.0F;
+ g_qeglobals.d_savedinfo.colors[iIndex][1] = 1.0F;
+ g_qeglobals.d_savedinfo.colors[iIndex][2] = 1.0F;
+ }
+ else
+ {
+ float scaler = 1.0F / largest;
+
+ g_qeglobals.d_savedinfo.colors[iIndex][0] *= scaler;
+ g_qeglobals.d_savedinfo.colors[iIndex][1] *= scaler;
+ g_qeglobals.d_savedinfo.colors[iIndex][2] *= scaler;
+ }
+ }
+
+ Sys_UpdateWindows (W_ALL);
+ return true;
+ }
+ else return false;
+
+}
+
+
+/* Copied from MSDN */
+
+BOOL DoMru(HWND hWnd,WORD wId)
+{
+ char szFileName[128];
+ OFSTRUCT of;
+ BOOL fExist;
+
+ GetMenuItem(g_qeglobals.d_lpMruMenu, wId, TRUE, szFileName, sizeof(szFileName));
+
+ // Test if the file exists.
+
+ fExist = OpenFile(szFileName ,&of,OF_EXIST) != HFILE_ERROR;
+
+ if (fExist) {
+
+ // Place the file on the top of MRU.
+ AddNewItem(g_qeglobals.d_lpMruMenu,(LPSTR)szFileName);
+
+ // Now perform opening this file !!!
+ Map_LoadFile (szFileName);
+ }
+ else
+ // Remove the file on MRU.
+ DelMenuItem(g_qeglobals.d_lpMruMenu,wId,TRUE);
+
+ // Refresh the File menu.
+ PlaceMenuMRUItem(g_qeglobals.d_lpMruMenu,GetSubMenu(GetMenu(hWnd),0),
+ ID_FILE_EXIT);
+
+ return fExist;
+}
+
+
+
+/*
+==============
+Main_Create
+==============
+*/
+
+void MFCCreate (HINSTANCE hInstance)
+{
+ HMENU hMenu = NULL;
+ int i = sizeof(g_qeglobals.d_savedinfo);
+ long l = i;
+
+ g_qeglobals.d_savedinfo.exclude |= (EXCLUDE_HINT | EXCLUDE_CLIP);
+ LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l);
+
+ int nOldSize = g_qeglobals.d_savedinfo.iSize;
+ if (g_qeglobals.d_savedinfo.iSize != sizeof(g_qeglobals.d_savedinfo))
+ {
+ // fill in new defaults
+ g_qeglobals.d_savedinfo.iSize = sizeof(g_qeglobals.d_savedinfo);
+ g_qeglobals.d_savedinfo.fGamma = 1.0;
+ g_qeglobals.d_savedinfo.iTexMenu = ID_VIEW_BILINEARMIPMAP;
+ g_qeglobals.d_savedinfo.m_nTextureTweak = 1;
+
+ //g_qeglobals.d_savedinfo.exclude = INCLUDE_EASY | INCLUDE_NORMAL | INCLUDE_HARD | INCLUDE_DEATHMATCH;
+ g_qeglobals.d_savedinfo.show_coordinates = true;
+ g_qeglobals.d_savedinfo.show_names = false;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][i] = 0.25;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][i] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR][i] = 0.75;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR][i] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_CAMERABACK][i] = 0.25;
+ }
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] = 1.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER][2] = 1.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][0] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES][2] = 0.0;
+
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][0] = 0.5;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][1] = 0.0;
+ g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME][2] = 0.75;
+
+
+ // old size was smaller, reload original prefs
+ if (nOldSize < sizeof(g_qeglobals.d_savedinfo))
+ {
+ long l = nOldSize;
+ LoadRegistryInfo("SavedInfo", &g_qeglobals.d_savedinfo, &l);
+ }
+
+ }
+ if ( ( hMenu = GetMenu( g_qeglobals.d_hwndMain ) ) != 0 )
+ {
+ // by default all of these are checked because that's how they're defined in the menu editor
+ if ( !g_qeglobals.d_savedinfo.show_names )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWNAMES, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( !g_qeglobals.d_savedinfo.show_coordinates )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWCOORDINATES, MF_BYCOMMAND | MF_UNCHECKED );
+
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWLIGHTS, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT )
+ CheckMenuItem( hMenu, ID_VIEW_ENTITY, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWPATH, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWWATER, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWWORLD, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWCLIP, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWHINT, MF_BYCOMMAND | MF_UNCHECKED );
+ if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK )
+ CheckMenuItem( hMenu, ID_VIEW_SHOWCAULK, MF_BYCOMMAND | MF_UNCHECKED );
+ }
+
+}
+
+
+/*
+=============================================================
+
+REGISTRY INFO
+
+=============================================================
+*/
+
+BOOL SaveRegistryInfo(const char *pszName, void *pvBuf, long lSize)
+{
+ LONG lres;
+ DWORD dwDisp;
+ HKEY hKeyId;
+
+ if (g_qeglobals.use_ini)
+ {
+ lres = RegCreateKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
+ }
+ else
+ {
+ lres = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyId, &dwDisp);
+ }
+
+ if (lres != ERROR_SUCCESS)
+ return FALSE;
+
+ lres = RegSetValueEx(hKeyId, pszName, 0, REG_BINARY, (unsigned char*)pvBuf, lSize);
+
+ RegCloseKey(hKeyId);
+
+ if (lres != ERROR_SUCCESS)
+ return FALSE;
+
+ return TRUE;
+}
+
+BOOL LoadRegistryInfo(const char *pszName, void *pvBuf, long *plSize)
+{
+ HKEY hKey;
+ long lres, lType, lSize;
+
+ if (plSize == NULL)
+ plSize = &lSize;
+
+ if (g_qeglobals.use_ini)
+ {
+ lres = RegOpenKeyEx(HKEY_CURRENT_USER, g_qeglobals.use_ini_registry, 0, KEY_READ, &hKey);
+ }
+ else
+ {
+ lres = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Q3Radiant\\Q3Radiant", 0, KEY_READ, &hKey);
+ }
+
+ lres = RegQueryValueEx(hKey, pszName, NULL, (unsigned long*)&lType, (unsigned char*)pvBuf, (unsigned long*)plSize);
+
+ RegCloseKey(hKey);
+
+ if (lres != ERROR_SUCCESS)
+ {
+#ifdef _DEBUG
+ char Message[1024];
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, lres, 0, &(Message[0]), 1024, NULL );
+ Sys_Printf( "WARNING: RegQueryValueEx failed in LoadRegistryInfo for %s : %s", pszName, Message );
+#endif
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL SaveWindowState(HWND hWnd, const char *pszName)
+{
+ RECT rc;
+ GetWindowRect(hWnd, &rc);
+ if (hWnd != g_qeglobals.d_hwndMain) // && g_pParentWnd->CurrentStyle() == QR_QE4)
+ {
+ if (::GetParent(hWnd) != g_qeglobals.d_hwndMain)
+ {
+ ::SetParent(hWnd, g_qeglobals.d_hwndMain);
+ }
+ MapWindowPoints(NULL, g_qeglobals.d_hwndMain, (POINT *)&rc, 2);
+
+ }
+ BOOL b = SaveRegistryInfo(pszName, &rc, sizeof(rc));
+ return b;
+}
+
+
+BOOL LoadWindowState(HWND hWnd, const char *pszName)
+{
+ RECT rc;
+ LONG lSize = sizeof(rc);
+
+ if (LoadRegistryInfo(pszName, &rc, &lSize))
+ {
+ if (rc.left < 0)
+ rc.left = 0;
+ if (rc.top < 0)
+ rc.top = 0;
+ if (rc.right < rc.left + 16)
+ rc.right = rc.left + 16;
+ if (rc.bottom < rc.top + 16)
+ rc.bottom = rc.top + 16;
+
+ MoveWindow(hWnd, rc.left, rc.top, rc.right - rc.left,
+ rc.bottom - rc.top, FALSE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+===============================================================
+
+ STATUS WINDOW
+
+===============================================================
+*/
+
+void Sys_UpdateStatusBar( void )
+{
+ extern int g_numbrushes, g_numentities;
+
+ char numbrushbuffer[100]="";
+
+ sprintf( numbrushbuffer, "Brushes: %d Entities: %d", g_numbrushes, g_numentities );
+ g_pParentWnd->SetStatusText(2, numbrushbuffer);
+ //Sys_Status( numbrushbuffer, 2 );
+}
+
+void Sys_Status(const char *psz, int part )
+{
+ SendMessage(g_qeglobals.d_hwndStatus, SB_SETTEXT, part, (LPARAM)psz);
+}
+
+static HWND CreateMyStatusWindow(HINSTANCE hInst)
+{
+ HWND hWnd;
+ int partsize[3] = { 300, 1100, -1 };
+
+ hWnd = CreateWindowEx( WS_EX_TOPMOST, // no extended styles
+ STATUSCLASSNAME, // status bar
+ "", // no text
+ WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
+ -100, -100, 10, 10, // x, y, cx, cy
+ g_qeglobals.d_hwndMain, // parent window
+ (HMENU)100, // window ID
+ hInst, // instance
+ NULL); // window data
+
+ SendMessage( hWnd, SB_SETPARTS, 3, ( long ) partsize );
+
+ return hWnd;
+}
+
+//==============================================================
+
+#define NUMBUTTONS 15
+HWND CreateToolBar(HINSTANCE hinst)
+{
+ HWND hwndTB;
+ TBADDBITMAP tbab;
+ TBBUTTON tbb[NUMBUTTONS];
+
+ // Ensure that the common control DLL is loaded.
+
+ InitCommonControls();
+
+ // Create a toolbar that the user can customize and that has a
+ // tooltip associated with it.
+
+ hwndTB = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR) NULL,
+ WS_CHILD | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE | WS_BORDER,
+ 0, 0, 0, 0, g_qeglobals.d_hwndMain, (HMENU) IDR_TOOLBAR1, hinst, NULL);
+
+ // Send the TB_BUTTONSTRUCTSIZE message, which is required for
+ // backward compatibility.
+
+ SendMessage(hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
+
+ // Add the bitmap containing button images to the toolbar.
+
+ tbab.hInst = hinst;
+ tbab.nID = IDR_TOOLBAR1;
+ SendMessage(hwndTB, TB_ADDBITMAP, (WPARAM)NUMBUTTONS, (WPARAM) &tbab);
+
+ // Fill the TBBUTTON array with button information, and add the
+ // buttons to the toolbar.
+
+ tbb[0].iBitmap = 0;
+ tbb[0].idCommand = ID_BRUSH_FLIPX;
+ tbb[0].fsState = TBSTATE_ENABLED;
+ tbb[0].fsStyle = TBSTYLE_BUTTON;
+ tbb[0].dwData = 0;
+ tbb[0].iString = 0;
+
+ tbb[1].iBitmap = 2;
+ tbb[1].idCommand = ID_BRUSH_FLIPY;
+ tbb[1].fsState = TBSTATE_ENABLED;
+ tbb[1].fsStyle = TBSTYLE_BUTTON;
+ tbb[1].dwData = 0;
+ tbb[1].iString = 0;
+
+ tbb[2].iBitmap = 4;
+ tbb[2].idCommand = ID_BRUSH_FLIPZ;
+ tbb[2].fsState = TBSTATE_ENABLED;
+ tbb[2].fsStyle = TBSTYLE_BUTTON;
+ tbb[2].dwData = 0;
+ tbb[2].iString = 0;
+
+ tbb[3].iBitmap = 1;
+ tbb[3].idCommand = ID_BRUSH_ROTATEX;
+ tbb[3].fsState = TBSTATE_ENABLED;
+ tbb[3].fsStyle = TBSTYLE_BUTTON;
+ tbb[3].dwData = 0;
+ tbb[3].iString = 0;
+
+ tbb[4].iBitmap = 3;
+ tbb[4].idCommand = ID_BRUSH_ROTATEY;
+ tbb[4].fsState = TBSTATE_ENABLED;
+ tbb[4].fsStyle = TBSTYLE_BUTTON;
+ tbb[4].dwData = 0;
+ tbb[4].iString = 0;
+
+ tbb[5].iBitmap = 5;
+ tbb[5].idCommand = ID_BRUSH_ROTATEZ;
+ tbb[5].fsState = TBSTATE_ENABLED;
+ tbb[5].fsStyle = TBSTYLE_BUTTON;
+ tbb[5].dwData = 0;
+ tbb[5].iString = 0;
+
+ tbb[6].iBitmap = 6;
+ tbb[6].idCommand = ID_SELECTION_SELECTCOMPLETETALL;
+ tbb[6].fsState = TBSTATE_ENABLED;
+ tbb[6].fsStyle = TBSTYLE_BUTTON;
+ tbb[6].dwData = 0;
+ tbb[6].iString = 0;
+
+ tbb[7].iBitmap = 7;
+ tbb[7].idCommand = ID_SELECTION_SELECTTOUCHING;
+ tbb[7].fsState = TBSTATE_ENABLED;
+ tbb[7].fsStyle = TBSTYLE_BUTTON;
+ tbb[7].dwData = 0;
+ tbb[7].iString = 0;
+
+ tbb[8].iBitmap = 8;
+ tbb[8].idCommand = ID_SELECTION_SELECTPARTIALTALL;
+ tbb[8].fsState = TBSTATE_ENABLED;
+ tbb[8].fsStyle = TBSTYLE_BUTTON;
+ tbb[8].dwData = 0;
+ tbb[8].iString = 0;
+
+
+ tbb[9].iBitmap = 9;
+ tbb[9].idCommand = ID_SELECTION_SELECTINSIDE;
+ tbb[9].fsState = TBSTATE_ENABLED;
+ tbb[9].fsStyle = TBSTYLE_BUTTON;
+ tbb[9].dwData = 0;
+ tbb[9].iString = 0;
+
+ tbb[10].iBitmap = 10;
+ tbb[10].idCommand = ID_SELECTION_CSGSUBTRACT;
+ tbb[10].fsState = TBSTATE_ENABLED;
+ tbb[10].fsStyle = TBSTYLE_BUTTON;
+ tbb[10].dwData = 0;
+ tbb[10].iString = 0;
+
+
+ tbb[11].iBitmap = 11;
+ tbb[11].idCommand = ID_SELECTION_MAKEHOLLOW;
+ tbb[11].fsState = TBSTATE_ENABLED;
+ tbb[11].fsStyle = TBSTYLE_BUTTON;
+ tbb[11].dwData = 0;
+ tbb[11].iString = 0;
+
+ tbb[12].iBitmap = 12;
+ tbb[12].idCommand = ID_TEXTURES_WIREFRAME;
+ tbb[12].fsState = TBSTATE_ENABLED;
+ tbb[12].fsStyle = TBSTYLE_BUTTON;
+ tbb[12].dwData = 0;
+ tbb[12].iString = 0;
+
+ tbb[13].iBitmap = 13;
+ tbb[13].idCommand = ID_TEXTURES_FLATSHADE;
+ tbb[13].fsState = TBSTATE_ENABLED;
+ tbb[13].fsStyle = TBSTYLE_BUTTON;
+ tbb[13].dwData = 0;
+ tbb[13].iString = 0;
+
+ tbb[14].iBitmap = 14;
+ tbb[14].idCommand = ID_VIEW_TRILINEAR;
+ tbb[14].fsState = TBSTATE_ENABLED;
+ tbb[14].fsStyle = TBSTYLE_BUTTON;
+ tbb[14].dwData = 0;
+ tbb[14].iString = 0;
+
+ SendMessage(hwndTB, TB_ADDBUTTONS, (WPARAM)NUMBUTTONS,
+ (LPARAM) (LPTBBUTTON) &tbb);
+
+ ShowWindow(hwndTB, SW_SHOW);
+
+ return hwndTB;
+}
+
diff --git a/q3radiant/Winding.cpp b/q3radiant/Winding.cpp
new file mode 100755
index 0000000..76e6df1
--- /dev/null
+++ b/q3radiant/Winding.cpp
@@ -0,0 +1,817 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+
+#include "stdafx.h"
+#include <assert.h>
+#include "qe3.h"
+#include "winding.h"
+
+#define BOGUS_RANGE 18000
+
+/*
+=============
+Plane_Equal
+=============
+*/
+#define NORMAL_EPSILON 0.0001
+#define DIST_EPSILON 0.02
+
+int Plane_Equal(plane_t *a, plane_t *b, int flip)
+{
+ vec3_t normal;
+ float dist;
+
+ if (flip) {
+ normal[0] = - b->normal[0];
+ normal[1] = - b->normal[1];
+ normal[2] = - b->normal[2];
+ dist = - b->dist;
+ }
+ else {
+ normal[0] = b->normal[0];
+ normal[1] = b->normal[1];
+ normal[2] = b->normal[2];
+ dist = b->dist;
+ }
+ if (
+ fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON
+ && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON
+ && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON
+ && fabs(a->dist - dist) < DIST_EPSILON )
+ return true;
+ return false;
+}
+
+/*
+============
+Plane_FromPoints
+============
+*/
+int Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane)
+{
+ vec3_t v1, v2;
+
+ VectorSubtract(p2, p1, v1);
+ VectorSubtract(p3, p1, v2);
+ //CrossProduct(v2, v1, plane->normal);
+ CrossProduct(v1, v2, plane->normal);
+ if (VectorNormalize(plane->normal) < 0.1) return false;
+ plane->dist = DotProduct(p1, plane->normal);
+ return true;
+}
+
+/*
+=================
+Point_Equal
+=================
+*/
+int Point_Equal(vec3_t p1, vec3_t p2, float epsilon)
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (fabs(p1[i] - p2[i]) > epsilon) return false;
+ }
+ return true;
+}
+
+
+/*
+=================
+Winding_BaseForPlane
+=================
+*/
+winding_t *Winding_BaseForPlane (plane_t *p)
+{
+ int i, x;
+ vec_t max, v;
+ vec3_t org, vright, vup;
+ winding_t *w;
+
+ // find the major axis
+
+ max = -BOGUS_RANGE;
+ x = -1;
+ for (i=0 ; i<3; i++)
+ {
+ v = fabs(p->normal[i]);
+ if (v > max)
+ {
+ x = i;
+ max = v;
+ }
+ }
+ if (x==-1)
+ Error ("Winding_BaseForPlane: no axis found");
+
+ VectorCopy (vec3_origin, vup);
+ switch (x)
+ {
+ case 0:
+ case 1:
+ vup[2] = 1;
+ break;
+ case 2:
+ vup[0] = 1;
+ break;
+ }
+
+
+ v = DotProduct (vup, p->normal);
+ VectorMA (vup, -v, p->normal, vup);
+ VectorNormalize (vup);
+
+ VectorScale (p->normal, p->dist, org);
+
+ CrossProduct (vup, p->normal, vright);
+
+ VectorScale (vup, BOGUS_RANGE, vup);
+ VectorScale (vright, BOGUS_RANGE, vright);
+
+ // project a really big axis aligned box onto the plane
+ w = Winding_Alloc (4);
+
+ VectorSubtract (org, vright, w->points[0]);
+ VectorAdd (w->points[0], vup, w->points[0]);
+
+ VectorAdd (org, vright, w->points[1]);
+ VectorAdd (w->points[1], vup, w->points[1]);
+
+ VectorAdd (org, vright, w->points[2]);
+ VectorSubtract (w->points[2], vup, w->points[2]);
+
+ VectorSubtract (org, vright, w->points[3]);
+ VectorSubtract (w->points[3], vup, w->points[3]);
+
+ w->numpoints = 4;
+
+ return w;
+}
+
+/*
+==================
+Winding_Alloc
+==================
+*/
+winding_t *Winding_Alloc (int points)
+{
+ winding_t *w;
+ int size;
+
+ if (points > MAX_POINTS_ON_WINDING)
+ Error ("Winding_Alloc: %i points", points);
+
+ size = (int)((winding_t *)0)->points[points];
+ w = (winding_t*) malloc (size);
+ memset (w, 0, size);
+ w->maxpoints = points;
+
+ return w;
+}
+
+
+void Winding_Free (winding_t *w)
+{
+ free(w);
+}
+
+
+/*
+==================
+Winding_Clone
+==================
+*/
+winding_t *Winding_Clone(winding_t *w)
+{
+ int size;
+ winding_t *c;
+
+ size = (int)((winding_t *)0)->points[w->numpoints];
+ c = (winding_t*)qmalloc (size);
+ memcpy (c, w, size);
+ return c;
+}
+
+/*
+==================
+ReverseWinding
+==================
+*/
+winding_t *Winding_Reverse(winding_t *w)
+{
+ int i;
+ winding_t *c;
+
+ c = Winding_Alloc(w->numpoints);
+ for (i = 0; i < w->numpoints; i++)
+ {
+ VectorCopy (w->points[w->numpoints-1-i], c->points[i]);
+ }
+ c->numpoints = w->numpoints;
+ return c;
+}
+
+
+/*
+==============
+Winding_RemovePoint
+==============
+*/
+void Winding_RemovePoint(winding_t *w, int point)
+{
+ if (point < 0 || point >= w->numpoints)
+ Error("Winding_RemovePoint: point out of range");
+
+ if (point < w->numpoints-1)
+ {
+ memmove(&w->points[point], &w->points[point+1], (int)((winding_t *)0)->points[w->numpoints - point - 1]);
+ }
+ w->numpoints--;
+}
+
+/*
+=============
+Winding_InsertPoint
+=============
+*/
+winding_t *Winding_InsertPoint(winding_t *w, vec3_t point, int spot)
+{
+ int i, j;
+ winding_t *neww;
+
+ if (spot > w->numpoints)
+ {
+ Error("Winding_InsertPoint: spot > w->numpoints");
+ } //end if
+ if (spot < 0)
+ {
+ Error("Winding_InsertPoint: spot < 0");
+ } //end if
+ neww = Winding_Alloc(w->numpoints + 1);
+ neww->numpoints = w->numpoints + 1;
+ for (i = 0, j = 0; i < neww->numpoints; i++)
+ {
+ if (i == spot)
+ {
+ VectorCopy(point, neww->points[i]);
+ }
+ else
+ {
+ VectorCopy(w->points[j], neww->points[i]);
+ j++;
+ }
+ }
+ return neww;
+}
+
+/*
+==============
+Winding_IsTiny
+==============
+*/
+#define EDGE_LENGTH 0.2
+
+int Winding_IsTiny (winding_t *w)
+{
+ int i, j;
+ vec_t len;
+ vec3_t delta;
+ int edges;
+
+ edges = 0;
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ j = i == w->numpoints - 1 ? 0 : i+1;
+ VectorSubtract (w->points[j], w->points[i], delta);
+ len = VectorLength (delta);
+ if (len > EDGE_LENGTH)
+ {
+ if (++edges == 3)
+ return false;
+ }
+ }
+ return true;
+}
+
+/*
+==============
+Winding_IsHuge
+==============
+*/
+int Winding_IsHuge(winding_t *w)
+{
+ int i, j;
+
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ if (w->points[i][j] < -BOGUS_RANGE+1 || w->points[i][j] > BOGUS_RANGE-1)
+ return true;
+ }
+ return false;
+}
+
+/*
+=============
+Winding_PlanesConcave
+=============
+*/
+#define WCONVEX_EPSILON 0.2
+
+int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
+ vec3_t normal1, vec3_t normal2,
+ float dist1, float dist2)
+{
+ int i;
+
+ if (!w1 || !w2) return false;
+
+ // check if one of the points of winding 1 is at the back of the plane of winding 2
+ for (i = 0; i < w1->numpoints; i++)
+ {
+ if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return true;
+ }
+ // check if one of the points of winding 2 is at the back of the plane of winding 1
+ for (i = 0; i < w2->numpoints; i++)
+ {
+ if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return true;
+ }
+
+ return false;
+}
+
+/*
+==================
+Winding_Clip
+
+Clips the winding to the plane, returning the new winding on the positive side
+Frees the input winding.
+If keepon is true, an exactly on-plane winding will be saved, otherwise
+it will be clipped away.
+==================
+*/
+winding_t *Winding_Clip (winding_t *in, plane_t *split, qboolean keepon)
+{
+ vec_t dists[MAX_POINTS_ON_WINDING];
+ int sides[MAX_POINTS_ON_WINDING];
+ int counts[3];
+ vec_t dot;
+ int i, j;
+ vec_t *p1, *p2;
+ vec3_t mid;
+ winding_t *neww;
+ int maxpts;
+
+ counts[0] = counts[1] = counts[2] = 0;
+
+ // determine sides for each point
+ for (i=0 ; i<in->numpoints ; i++)
+ {
+ dot = DotProduct (in->points[i], split->normal);
+ dot -= split->dist;
+ dists[i] = dot;
+ if (dot > ON_EPSILON)
+ sides[i] = SIDE_FRONT;
+ else if (dot < -ON_EPSILON)
+ sides[i] = SIDE_BACK;
+ else
+ {
+ sides[i] = SIDE_ON;
+ }
+ counts[sides[i]]++;
+ }
+ sides[i] = sides[0];
+ dists[i] = dists[0];
+
+ if (keepon && !counts[0] && !counts[1])
+ return in;
+
+ if (!counts[0])
+ {
+ Winding_Free (in);
+ return NULL;
+ }
+ if (!counts[1])
+ return in;
+
+ maxpts = in->numpoints+4; // can't use counts[0]+2 because
+ // of fp grouping errors
+ neww = Winding_Alloc (maxpts);
+
+ for (i=0 ; i<in->numpoints ; i++)
+ {
+ p1 = in->points[i];
+
+ if (sides[i] == SIDE_ON)
+ {
+ VectorCopy (p1, neww->points[neww->numpoints]);
+ neww->numpoints++;
+ continue;
+ }
+
+ if (sides[i] == SIDE_FRONT)
+ {
+ VectorCopy (p1, neww->points[neww->numpoints]);
+ neww->numpoints++;
+ }
+
+ if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+ continue;
+
+ // generate a split point
+ p2 = in->points[(i+1)%in->numpoints];
+
+ dot = dists[i] / (dists[i]-dists[i+1]);
+ for (j=0 ; j<3 ; j++)
+ { // avoid round off error when possible
+ if (split->normal[j] == 1)
+ mid[j] = split->dist;
+ else if (split->normal[j] == -1)
+ mid[j] = -split->dist;
+ else
+ mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+ }
+
+ VectorCopy (mid, neww->points[neww->numpoints]);
+ neww->numpoints++;
+ }
+
+ if (neww->numpoints > maxpts)
+ Error ("Winding_Clip: points exceeded estimate");
+
+ // free the original winding
+ Winding_Free (in);
+
+ return neww;
+}
+
+/*
+=============
+Winding_SplitEpsilon
+
+ split the input winding with the plane
+ the input winding stays untouched
+=============
+*/
+void Winding_SplitEpsilon (winding_t *in, vec3_t normal, double dist,
+ vec_t epsilon, winding_t **front, winding_t **back)
+{
+ vec_t dists[MAX_POINTS_ON_WINDING+4];
+ int sides[MAX_POINTS_ON_WINDING+4];
+ int counts[3];
+ vec_t dot;
+ int i, j;
+ vec_t *p1, *p2;
+ vec3_t mid;
+ winding_t *f, *b;
+ int maxpts;
+
+ counts[0] = counts[1] = counts[2] = 0;
+
+ // determine sides for each point
+ for (i = 0; i < in->numpoints; i++)
+ {
+ dot = DotProduct (in->points[i], normal);
+ dot -= dist;
+ dists[i] = dot;
+ if (dot > epsilon)
+ sides[i] = SIDE_FRONT;
+ else if (dot < -epsilon)
+ sides[i] = SIDE_BACK;
+ else
+ {
+ sides[i] = SIDE_ON;
+ }
+ counts[sides[i]]++;
+ }
+ sides[i] = sides[0];
+ dists[i] = dists[0];
+
+ *front = *back = NULL;
+
+ if (!counts[0])
+ {
+ *back = Winding_Clone(in);
+ return;
+ }
+ if (!counts[1])
+ {
+ *front = Winding_Clone(in);
+ return;
+ }
+
+ maxpts = in->numpoints+4; // cant use counts[0]+2 because
+ // of fp grouping errors
+
+ *front = f = Winding_Alloc (maxpts);
+ *back = b = Winding_Alloc (maxpts);
+
+ for (i = 0; i < in->numpoints; i++)
+ {
+ p1 = in->points[i];
+
+ if (sides[i] == SIDE_ON)
+ {
+ VectorCopy (p1, f->points[f->numpoints]);
+ f->numpoints++;
+ VectorCopy (p1, b->points[b->numpoints]);
+ b->numpoints++;
+ continue;
+ }
+
+ if (sides[i] == SIDE_FRONT)
+ {
+ VectorCopy (p1, f->points[f->numpoints]);
+ f->numpoints++;
+ }
+ if (sides[i] == SIDE_BACK)
+ {
+ VectorCopy (p1, b->points[b->numpoints]);
+ b->numpoints++;
+ }
+
+ if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+ continue;
+
+ // generate a split point
+ p2 = in->points[(i+1)%in->numpoints];
+
+ dot = dists[i] / (dists[i]-dists[i+1]);
+ for (j = 0; j < 3; j++)
+ {
+ // avoid round off error when possible
+ if (normal[j] == 1)
+ mid[j] = dist;
+ else if (normal[j] == -1)
+ mid[j] = -dist;
+ else
+ mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+ }
+
+ VectorCopy (mid, f->points[f->numpoints]);
+ f->numpoints++;
+ VectorCopy (mid, b->points[b->numpoints]);
+ b->numpoints++;
+ }
+
+ if (f->numpoints > maxpts || b->numpoints > maxpts)
+ Error ("Winding_Clip: points exceeded estimate");
+ if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
+ Error ("Winding_Clip: MAX_POINTS_ON_WINDING");
+}
+
+/*
+=============
+Winding_TryMerge
+
+If two windings share a common edge and the edges that meet at the
+common points are both inside the other polygons, merge them
+
+Returns NULL if the windings couldn't be merged, or the new winding.
+The originals will NOT be freed.
+
+if keep is true no points are ever removed
+=============
+*/
+#define CONTINUOUS_EPSILON 0.005
+
+winding_t *Winding_TryMerge(winding_t *f1, winding_t *f2, vec3_t planenormal, int keep)
+{
+ vec_t *p1, *p2, *p3, *p4, *back;
+ winding_t *newf;
+ int i, j, k, l;
+ vec3_t normal, delta;
+ vec_t dot;
+ qboolean keep1, keep2;
+
+
+ //
+ // find a common edge
+ //
+ p1 = p2 = NULL; // stop compiler warning
+ j = 0; //
+
+ for (i = 0; i < f1->numpoints; i++)
+ {
+ p1 = f1->points[i];
+ p2 = f1->points[(i+1) % f1->numpoints];
+ for (j = 0; j < f2->numpoints; j++)
+ {
+ p3 = f2->points[j];
+ p4 = f2->points[(j+1) % f2->numpoints];
+ for (k = 0; k < 3; k++)
+ {
+ if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
+ break;
+ if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
+ break;
+ } //end for
+ if (k==3)
+ break;
+ } //end for
+ if (j < f2->numpoints)
+ break;
+ } //end for
+
+ if (i == f1->numpoints)
+ return NULL; // no matching edges
+
+ //
+ // check slope of connected lines
+ // if the slopes are colinear, the point can be removed
+ //
+ back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
+ VectorSubtract (p1, back, delta);
+ CrossProduct (planenormal, delta, normal);
+ VectorNormalize (normal);
+
+ back = f2->points[(j+2)%f2->numpoints];
+ VectorSubtract (back, p1, delta);
+ dot = DotProduct (delta, normal);
+ if (dot > CONTINUOUS_EPSILON)
+ return NULL; // not a convex polygon
+ keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
+
+ back = f1->points[(i+2)%f1->numpoints];
+ VectorSubtract (back, p2, delta);
+ CrossProduct (planenormal, delta, normal);
+ VectorNormalize (normal);
+
+ back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
+ VectorSubtract (back, p2, delta);
+ dot = DotProduct (delta, normal);
+ if (dot > CONTINUOUS_EPSILON)
+ return NULL; // not a convex polygon
+ keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
+
+ //
+ // build the new polygon
+ //
+ newf = Winding_Alloc (f1->numpoints + f2->numpoints);
+
+ // copy first polygon
+ for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
+ {
+ if (!keep && k==(i+1)%f1->numpoints && !keep2)
+ continue;
+
+ VectorCopy (f1->points[k], newf->points[newf->numpoints]);
+ newf->numpoints++;
+ }
+
+ // copy second polygon
+ for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
+ {
+ if (!keep && l==(j+1)%f2->numpoints && !keep1)
+ continue;
+ VectorCopy (f2->points[l], newf->points[newf->numpoints]);
+ newf->numpoints++;
+ }
+
+ return newf;
+}
+
+/*
+============
+Winding_Plane
+============
+*/
+void Winding_Plane (winding_t *w, vec3_t normal, double *dist)
+{
+ vec3_t v1, v2;
+ int i;
+
+ //find two vectors each longer than 0.5 units
+ for (i = 0; i < w->numpoints; i++)
+ {
+ VectorSubtract(w->points[(i+1) % w->numpoints], w->points[i], v1);
+ VectorSubtract(w->points[(i+2) % w->numpoints], w->points[i], v2);
+ if (VectorLength(v1) > 0.5 && VectorLength(v2) > 0.5) break;
+ }
+ CrossProduct(v2, v1, normal);
+ VectorNormalize(normal);
+ *dist = DotProduct(w->points[0], normal);
+}
+
+/*
+=============
+Winding_Area
+=============
+*/
+float Winding_Area (winding_t *w)
+{
+ int i;
+ vec3_t d1, d2, cross;
+ float total;
+
+ total = 0;
+ for (i=2 ; i<w->numpoints ; i++)
+ {
+ VectorSubtract (w->points[i-1], w->points[0], d1);
+ VectorSubtract (w->points[i], w->points[0], d2);
+ CrossProduct (d1, d2, cross);
+ total += 0.5 * VectorLength ( cross );
+ }
+ return total;
+}
+
+/*
+=============
+Winding_Bounds
+=============
+*/
+void Winding_Bounds (winding_t *w, vec3_t mins, vec3_t maxs)
+{
+ vec_t v;
+ int i,j;
+
+ mins[0] = mins[1] = mins[2] = 99999;
+ maxs[0] = maxs[1] = maxs[2] = -99999;
+
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ for (j=0 ; j<3 ; j++)
+ {
+ v = w->points[i][j];
+ if (v < mins[j])
+ mins[j] = v;
+ if (v > maxs[j])
+ maxs[j] = v;
+ }
+ }
+}
+
+
+/*
+=================
+Winding_PointInside
+=================
+*/
+int Winding_PointInside(winding_t *w, plane_t *plane, vec3_t point, float epsilon)
+{
+ int i;
+ vec3_t dir, normal, pointvec;
+
+ for (i = 0; i < w->numpoints; i++)
+ {
+ VectorSubtract(w->points[(i+1) % w->numpoints], w->points[i], dir);
+ VectorSubtract(point, w->points[i], pointvec);
+ //
+ CrossProduct(dir, plane->normal, normal);
+ //
+ if (DotProduct(pointvec, normal) < -epsilon) return false;
+ }
+ return true;
+}
+
+/*
+=================
+Winding_VectorIntersect
+=================
+*/
+int Winding_VectorIntersect(winding_t *w, plane_t *plane, vec3_t p1, vec3_t p2, float epsilon)
+{
+ float front, back, frac;
+ vec3_t mid;
+
+ front = DotProduct(p1, plane->normal) - plane->dist;
+ back = DotProduct(p2, plane->normal) - plane->dist;
+ //if both points at the same side of the plane
+ if (front < -epsilon && back < -epsilon) return false;
+ if (front > epsilon && back > epsilon) return false;
+ //get point of intersection with winding plane
+ if (fabs(front-back) < 0.001)
+ {
+ VectorCopy(p2, mid);
+ }
+ else
+ {
+ frac = front/(front-back);
+ mid[0] = p1[0] + (p2[0] - p1[0]) * frac;
+ mid[1] = p1[1] + (p2[1] - p1[1]) * frac;
+ mid[2] = p1[2] + (p2[2] - p1[2]) * frac;
+ }
+ return Winding_PointInside(w, plane, mid, epsilon);
+}
+
diff --git a/q3radiant/Winding.h b/q3radiant/Winding.h
new file mode 100755
index 0000000..66858aa
--- /dev/null
+++ b/q3radiant/Winding.h
@@ -0,0 +1,70 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+
+
+//returns true if the planes are equal
+int Plane_Equal(plane_t *a, plane_t *b, int flip);
+//returns false if the points are colinear
+int Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane);
+//returns true if the points are equal
+int Point_Equal(vec3_t p1, vec3_t p2, float epsilon);
+
+//allocate a winding
+winding_t* Winding_Alloc(int points);
+//free the winding
+void Winding_Free(winding_t *w);
+//create a base winding for the plane
+winding_t* Winding_BaseForPlane (plane_t *p);
+//make a winding clone
+winding_t* Winding_Clone(winding_t *w );
+//creates the reversed winding
+winding_t* Winding_Reverse(winding_t *w);
+//remove a point from the winding
+void Winding_RemovePoint(winding_t *w, int point);
+//inserts a point to a winding, creating a new winding
+winding_t* Winding_InsertPoint(winding_t *w, vec3_t point, int spot);
+//returns true if the planes are concave
+int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
+ vec3_t normal1, vec3_t normal2,
+ float dist1, float dist2);
+//returns true if the winding is tiny
+int Winding_IsTiny(winding_t *w);
+//returns true if the winding is huge
+int Winding_IsHuge(winding_t *w);
+//clip the winding with the plane
+winding_t* Winding_Clip(winding_t *in, plane_t *split, qboolean keepon);
+//split the winding with the plane
+void Winding_SplitEpsilon(winding_t *in, vec3_t normal, double dist,
+ vec_t epsilon, winding_t **front, winding_t **back);
+//try to merge the windings, returns the new merged winding or NULL
+winding_t *Winding_TryMerge(winding_t *f1, winding_t *f2, vec3_t planenormal, int keep);
+//create a plane for the winding
+void Winding_Plane(winding_t *w, vec3_t normal, double *dist);
+//returns the winding area
+float Winding_Area(winding_t *w);
+//returns the bounds of the winding
+void Winding_Bounds(winding_t *w, vec3_t mins, vec3_t maxs);
+//returns true if the point is inside the winding
+int Winding_PointInside(winding_t *w, plane_t *plane, vec3_t point, float epsilon);
+//returns true if the vector intersects with the winding
+int Winding_VectorIntersect(winding_t *w, plane_t *plane, vec3_t p1, vec3_t p2, float epsilon);
diff --git a/q3radiant/XY.H b/q3radiant/XY.H
new file mode 100755
index 0000000..243d1b4
--- /dev/null
+++ b/q3radiant/XY.H
@@ -0,0 +1,39 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+// window system independent camera view code
+
+typedef struct
+{
+ int width, height;
+
+ qboolean timing;
+
+ vec3_t origin; // at center of window
+ float scale;
+
+ float topclip, bottomclip;
+
+ qboolean d_dirty;
+} xy_t;
+
+BOOL FilterBrush(brush_t *pb);
diff --git a/q3radiant/XYWnd.cpp b/q3radiant/XYWnd.cpp
new file mode 100755
index 0000000..653c976
--- /dev/null
+++ b/q3radiant/XYWnd.cpp
@@ -0,0 +1,3629 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// XYWnd.cpp : implementation file
+//
+// QERadiant
+//
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "XYWnd.h"
+#include "qe3.h"
+#include "PrefsDlg.h"
+#include "DialogInfo.h"
+#include "splines/splines.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define PAGEFLIPS 2
+
+
+const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"};
+const char* g_pOrgStrings[] = {"(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)"};
+CString g_strDim;
+CString g_strStatus;
+
+bool g_bCrossHairs = false;
+bool g_bScaleMode;
+int g_nScaleHow;
+bool g_bRotateMode;
+bool g_bClipMode;
+bool g_bRogueClipMode;
+bool g_bSwitch;
+CClipPoint g_Clip1;
+CClipPoint g_Clip2;
+CClipPoint g_Clip3;
+CClipPoint* g_pMovingClip;
+brush_t g_brFrontSplits;
+brush_t g_brBackSplits;
+
+brush_t g_brClipboard;
+brush_t g_brUndo;
+entity_t g_enClipboard;
+
+vec3_t g_vRotateOrigin;
+vec3_t g_vRotation;
+
+bool g_bPathMode;
+CClipPoint g_PathPoints[256];
+CClipPoint* g_pMovingPath;
+int g_nPathCount;
+int g_nPathLimit;
+
+bool g_bSmartGo;
+
+bool g_bPointMode;
+CClipPoint g_PointPoints[512];
+CClipPoint* g_pMovingPoint;
+int g_nPointCount;
+int g_nPointLimit;
+
+
+const int XY_LEFT = 0x01;
+const int XY_RIGHT = 0x02;
+const int XY_UP = 0x04;
+const int XY_DOWN = 0x08;
+
+PFNPathCallback* g_pPathFunc = NULL;
+
+void AcquirePath(int nCount, PFNPathCallback* pFunc)
+{
+ g_nPathCount = 0;
+ g_nPathLimit = nCount;
+ g_pPathFunc = pFunc;
+ g_bPathMode = true;
+}
+
+
+CPtrArray g_ptrMenus;
+
+CMemFile g_Clipboard(4096);
+CMemFile g_PatchClipboard(4096);
+
+extern int pressx;
+extern int pressy;
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CXYWnd
+
+IMPLEMENT_DYNCREATE(CXYWnd, CWnd);
+
+CXYWnd::CXYWnd()
+{
+ g_brClipboard.next = &g_brClipboard;
+ g_brUndo.next = &g_brUndo;
+ g_nScaleHow = 0;
+ g_bRotateMode = false;
+ g_bClipMode = false;
+ g_bRogueClipMode = false;
+ g_bSwitch = true;
+ g_pMovingClip = NULL;
+ g_pMovingPath = NULL;
+ g_brFrontSplits.next = &g_brFrontSplits;
+ g_brBackSplits.next = &g_brBackSplits;
+ m_bActive = false;
+ //m_bTiming = true;
+ m_bTiming = false;
+ m_bRButtonDown = false;
+ m_nUpdateBits = W_XY;
+ g_bPathMode = false;
+ g_nPathCount = 0;
+ g_nPathLimit = 0;
+ m_nTimerID = -1;
+ XY_Init();
+}
+
+CXYWnd::~CXYWnd()
+{
+ int nSize = g_ptrMenus.GetSize();
+ while (nSize > 0)
+ {
+ CMenu* pMenu = reinterpret_cast<CMenu*>(g_ptrMenus.GetAt(nSize-1));
+ ASSERT(pMenu);
+ pMenu->DestroyMenu();
+ delete pMenu;
+ nSize--;
+ }
+ g_ptrMenus.RemoveAll();
+ m_mnuDrop.DestroyMenu();
+}
+
+
+BEGIN_MESSAGE_MAP(CXYWnd, CWnd)
+ //{{AFX_MSG_MAP(CXYWnd)
+ ON_WM_CREATE()
+ ON_WM_LBUTTONDOWN()
+ ON_WM_MBUTTONDOWN()
+ ON_WM_RBUTTONDOWN()
+ ON_WM_LBUTTONUP()
+ ON_WM_MBUTTONUP()
+ ON_WM_RBUTTONUP()
+ ON_WM_MOUSEMOVE()
+ ON_WM_PAINT()
+ ON_WM_KEYDOWN()
+ ON_WM_SIZE()
+ ON_WM_DESTROY()
+ ON_COMMAND(ID_SELECT_MOUSEROTATE, OnSelectMouserotate)
+ ON_WM_TIMER()
+ ON_WM_KEYUP()
+ ON_WM_NCCALCSIZE()
+ ON_WM_KILLFOCUS()
+ ON_WM_SETFOCUS()
+ ON_WM_CLOSE()
+ ON_COMMAND(ID_SELECTION_MAKE_DETAIL, CMainFrame::OnSelectionMakeDetail)
+ ON_COMMAND(ID_SELECTION_MAKE_STRUCTURAL, CMainFrame::OnSelectionMakeStructural)
+ ON_COMMAND(ID_SELECTION_SELECTCOMPLETETALL, CMainFrame::OnSelectionSelectcompletetall)
+ ON_COMMAND(ID_SELECTION_SELECTINSIDE, CMainFrame::OnSelectionSelectinside)
+ ON_COMMAND(ID_SELECTION_SELECTPARTIALTALL, CMainFrame::OnSelectionSelectpartialtall)
+ ON_COMMAND(ID_SELECTION_SELECTTOUCHING, CMainFrame::OnSelectionSelecttouching)
+ ON_COMMAND(ID_SELECTION_UNGROUPENTITY, CMainFrame::OnSelectionUngroupentity)
+ //}}AFX_MSG_MAP
+ ON_COMMAND_RANGE(ID_ENTITY_START, ID_ENTITY_END, OnEntityCreate)
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CXYWnd message handlers
+LONG WINAPI XYWndProc(HWND, UINT, WPARAM, LPARAM);
+BOOL CXYWnd::PreCreateWindow(CREATESTRUCT& cs)
+{
+ WNDCLASS wc;
+ HINSTANCE hInstance = AfxGetInstanceHandle();
+ if (::GetClassInfo(hInstance, XY_WINDOW_CLASS, &wc) == FALSE)
+ {
+ // Register a new class
+ memset (&wc, 0, sizeof(wc));
+ wc.style = CS_NOCLOSE | CS_OWNDC;
+ wc.lpszClassName = XY_WINDOW_CLASS;
+ wc.hCursor = NULL; //LoadCursor (NULL,IDC_ARROW);
+ wc.lpfnWndProc = ::DefWindowProc;
+ if (AfxRegisterClass(&wc) == FALSE)
+ Error ("CCamWnd RegisterClass: failed");
+ }
+
+ cs.lpszClass = XY_WINDOW_CLASS;
+ cs.lpszName = "VIEW";
+ if (cs.style != QE3_CHILDSTYLE)
+ cs.style = QE3_SPLITTER_STYLE;
+
+ return CWnd::PreCreateWindow(cs);
+}
+
+HDC s_hdcXY;
+HGLRC s_hglrcXY;
+
+static unsigned s_stipple[32] =
+{
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+ 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
+};
+
+/*
+============
+WXY_WndProc
+============
+*/
+LONG WINAPI XYWndProc (
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ QEW_StopGL( hWnd, s_hglrcXY, s_hdcXY );
+ return 0;
+
+ case WM_NCCALCSIZE:// don't let windows copy pixels
+ DefWindowProc (hWnd, uMsg, wParam, lParam);
+ return WVR_REDRAW;
+
+ case WM_KILLFOCUS:
+ case WM_SETFOCUS:
+ SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 );
+ return 0;
+
+ case WM_CLOSE:
+ DestroyWindow (hWnd);
+ return 0;
+ }
+
+ return DefWindowProc (hWnd, uMsg, wParam, lParam);
+}
+
+
+static void WXY_InitPixelFormat( PIXELFORMATDESCRIPTOR *pPFD )
+{
+ memset( pPFD, 0, sizeof( *pPFD ) );
+
+ pPFD->nSize = sizeof( PIXELFORMATDESCRIPTOR );
+ pPFD->nVersion = 1;
+ pPFD->dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
+ pPFD->iPixelType = PFD_TYPE_RGBA;
+ pPFD->cColorBits = 24;
+ pPFD->cDepthBits = 32;
+ pPFD->iLayerType = PFD_MAIN_PLANE;
+
+}
+
+void WXY_Print( void )
+{
+ DOCINFO di;
+
+ PRINTDLG pd;
+
+ /*
+ ** initialize the PRINTDLG struct and execute it
+ */
+ memset( &pd, 0, sizeof( pd ) );
+ pd.lStructSize = sizeof( pd );
+ pd.hwndOwner = g_qeglobals.d_hwndXY;
+ pd.Flags = PD_RETURNDC;
+ pd.hInstance = 0;
+ if ( !PrintDlg( &pd ) || !pd.hDC )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ /*
+ ** StartDoc
+ */
+ memset( &di, 0, sizeof( di ) );
+ di.cbSize = sizeof( di );
+ di.lpszDocName = "QE4";
+ if ( StartDoc( pd.hDC, &di ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ /*
+ ** StartPage
+ */
+ if ( StartPage( pd.hDC ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ /*
+ ** read pixels from the XY window
+ */
+ {
+ int bmwidth = 320, bmheight = 320;
+ int pwidth, pheight;
+
+ RECT r;
+
+ GetWindowRect( g_qeglobals.d_hwndXY, &r );
+
+ bmwidth = r.right - r.left;
+ bmheight = r.bottom - r.top;
+
+ pwidth = GetDeviceCaps( pd.hDC, PHYSICALWIDTH ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETX );
+ pheight = GetDeviceCaps( pd.hDC, PHYSICALHEIGHT ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETY );
+
+ StretchBlt( pd.hDC,
+ 0, 0,
+ pwidth, pheight,
+ s_hdcXY,
+ 0, 0,
+ bmwidth, bmheight,
+ SRCCOPY );
+ }
+
+ /*
+ ** EndPage and EndDoc
+ */
+ if ( EndPage( pd.hDC ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR );
+ return;
+ }
+
+ if ( EndDoc( pd.hDC ) <= 0 )
+ {
+ MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR );
+ return;
+ }
+}
+
+int CXYWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ s_hdcXY = ::GetDC(GetSafeHwnd());
+ QEW_SetupPixelFormat(s_hdcXY, false);
+ if ( ( s_hglrcXY = qwglCreateContext( s_hdcXY ) ) == 0 )
+ Error( "wglCreateContext in WXY_WndProc failed" );
+
+ if (!qwglShareLists( g_qeglobals.d_hglrcBase, s_hglrcXY ) )
+ Error( "wglShareLists in WXY_WndProc failed" );
+
+ if (!qwglMakeCurrent( s_hdcXY, s_hglrcXY ))
+ Error ("wglMakeCurrent failed");
+
+ qglPolygonStipple ((unsigned char *)s_stipple);
+ qglLineStipple (3, 0xaaaa);
+ g_qeglobals.d_hwndXY = GetSafeHwnd();
+ return 0;
+}
+
+float ptSum(vec3_t pt)
+{
+ return pt[0] + pt[1] + pt[2];
+}
+
+void CXYWnd::DropClipPoint(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ if (g_pMovingClip)
+ {
+ SetCapture();
+ SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *g_pMovingClip);
+ }
+ else
+ {
+ vec3_t* pPt = NULL;
+ if (g_Clip1.Set() == false)
+ {
+ pPt = g_Clip1;
+ g_Clip1.Set(true);
+ g_Clip1.m_ptScreen = point;
+ }
+ else
+ if (g_Clip2.Set() == false)
+ {
+ pPt = g_Clip2;
+ g_Clip2.Set(true);
+ g_Clip2.m_ptScreen = point;
+ }
+ else
+ if (g_Clip3.Set() == false)
+ {
+ pPt = g_Clip3;
+ g_Clip3.Set(true);
+ g_Clip3.m_ptScreen = point;
+ }
+ else
+ {
+ RetainClipMode(true);
+ pPt = g_Clip1;
+ g_Clip1.Set(true);
+ g_Clip1.m_ptScreen = point;
+ }
+ SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *pPt);
+ }
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+}
+
+
+void CXYWnd::DropPathPoint(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ if (g_pMovingPath)
+ {
+ SetCapture();
+ SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *g_pMovingPath);
+ }
+ else
+ {
+ g_PathPoints[g_nPathCount].Set(true);
+ g_PathPoints[g_nPathCount].m_ptScreen = point;
+ SnapToPoint(point.x, rctZ.Height() - 1 - point.y, g_PathPoints[g_nPathCount]);
+ g_nPathCount++;
+ if (g_nPathCount == g_nPathLimit)
+ {
+ if (g_pPathFunc)
+ g_pPathFunc(true, g_nPathCount);
+ g_nPathCount = 0;
+ g_bPathMode = false;
+ g_pPathFunc = NULL;
+ }
+ }
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+}
+
+void CXYWnd::AddPointPoint(UINT nFlags, vec3_t* pVec)
+{
+ g_PointPoints[g_nPointCount].Set(true);
+ //g_PointPoints[g_nPointCount].m_ptScreen = point;
+ _VectorCopy(*pVec, g_PointPoints[g_nPointCount]);
+ g_PointPoints[g_nPointCount].SetPointPtr(pVec);
+ g_nPointCount++;
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+}
+
+
+void CXYWnd::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ g_pParentWnd->SetActiveXY(this);
+ UndoCopy();
+
+ // plugin entities
+ if (DispatchOnLButtonDown(nFlags, point.x, point.y ))
+ return;
+
+ if (ClipMode() && !RogueClipMode())
+ {
+ DropClipPoint(nFlags, point);
+ }
+ else if (PathMode())
+ {
+ DropPathPoint(nFlags, point);
+ }
+ else OriginalButtonDown(nFlags, point);
+}
+
+void CXYWnd::OnMButtonDown(UINT nFlags, CPoint point)
+{
+ OriginalButtonDown(nFlags, point);
+}
+
+
+float Betwixt(float f1, float f2)
+{
+ if (f1 > f2)
+ return f2 + ((f1 - f2) / 2);
+ else
+ return f1 + ((f2 - f1) / 2);
+}
+
+void CXYWnd::ProduceSplits(brush_t** pFront, brush_t** pBack)
+{
+ *pFront = NULL;
+ *pBack = NULL;
+ if (ClipMode())
+ {
+ if (g_Clip1.Set() && g_Clip2.Set())
+ {
+ face_t face;
+ VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
+ VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
+ VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
+ if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes))
+ {
+ if (g_Clip3.Set() == false)
+ {
+ if (m_nViewType == XY)
+ {
+ face.planepts[0][2] = selected_brushes.next->mins[2];
+ face.planepts[1][2] = selected_brushes.next->mins[2];
+ face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
+ face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
+ face.planepts[2][2] = selected_brushes.next->maxs[2];
+ }
+ else if (m_nViewType == YZ)
+ {
+ face.planepts[0][0] = selected_brushes.next->mins[0];
+ face.planepts[1][0] = selected_brushes.next->mins[0];
+ face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
+ face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
+ face.planepts[2][0] = selected_brushes.next->maxs[0];
+ }
+ else
+ {
+ face.planepts[0][1] = selected_brushes.next->mins[1];
+ face.planepts[1][1] = selected_brushes.next->mins[1];
+ face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
+ face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
+ face.planepts[2][1] = selected_brushes.next->maxs[1];
+ }
+ }
+
+ Brush_SplitBrushByFace (selected_brushes.next, &face, pFront, pBack);
+ }
+
+ }
+ }
+}
+
+void CleanList(brush_t* pList)
+{
+ brush_t* pBrush = pList->next;
+ while (pBrush != NULL && pBrush != pList)
+ {
+ brush_t* pNext = pBrush->next;
+ Brush_Free(pBrush);
+ pBrush = pNext;
+ }
+}
+
+void CXYWnd::ProduceSplitLists()
+{
+ if (AnyPatchesSelected())
+ {
+ Sys_Printf("Deslecting patches for clip operation.\n");
+ brush_t *next;
+ for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = next)
+ {
+ next = pb->next;
+ if (pb->patchBrush)
+ {
+ Brush_RemoveFromList (pb);
+ Brush_AddToList (pb, &active_brushes);
+ UpdatePatchInspector();
+ }
+ if (pb->terrainBrush)
+ {
+ Brush_RemoveFromList (pb);
+ Brush_AddToList (pb, &active_brushes);
+ UpdateTerrainInspector();
+ }
+ }
+ }
+
+ CleanList(&g_brFrontSplits);
+ CleanList(&g_brBackSplits);
+ g_brFrontSplits.next = &g_brFrontSplits;
+ g_brBackSplits.next = &g_brBackSplits;
+ brush_t* pBrush;
+ for (pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
+ {
+ brush_t* pFront = NULL;
+ brush_t* pBack = NULL;
+ if (ClipMode())
+ {
+ if (g_Clip1.Set() && g_Clip2.Set())
+ {
+ face_t face;
+ VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
+ VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
+ VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
+ if (g_Clip3.Set() == false)
+ {
+ if (g_pParentWnd->ActiveXY()->GetViewType() == XY)
+ {
+ face.planepts[0][2] = pBrush->mins[2];
+ face.planepts[1][2] = pBrush->mins[2];
+ face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
+ face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
+ face.planepts[2][2] = pBrush->maxs[2];
+ }
+ else if (g_pParentWnd->ActiveXY()->GetViewType() == YZ)
+ {
+ face.planepts[0][0] = pBrush->mins[0];
+ face.planepts[1][0] = pBrush->mins[0];
+ face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
+ face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
+ face.planepts[2][0] = pBrush->maxs[0];
+ }
+ else
+ {
+ face.planepts[0][1] = pBrush->mins[1];
+ face.planepts[1][1] = pBrush->mins[1];
+ face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
+ face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
+ face.planepts[2][1] = pBrush->maxs[1];
+ }
+ }
+ Brush_SplitBrushByFace (pBrush, &face, &pFront, &pBack);
+ if (pBack)
+ Brush_AddToList(pBack, &g_brBackSplits);
+ if (pFront)
+ Brush_AddToList(pFront, &g_brFrontSplits);
+ }
+ }
+ }
+}
+
+void Brush_CopyList (brush_t* pFrom, brush_t* pTo)
+{
+ brush_t* pBrush = pFrom->next;
+ while (pBrush != NULL && pBrush != pFrom)
+ {
+ brush_t* pNext = pBrush->next;
+ Brush_RemoveFromList(pBrush);
+ Brush_AddToList(pBrush, pTo);
+ pBrush = pNext;
+ }
+}
+
+void CXYWnd::OnRButtonDown(UINT nFlags, CPoint point)
+{
+ g_pParentWnd->SetActiveXY(this);
+ m_ptDown = point;
+ m_bRButtonDown = true;
+
+ if (g_PrefsDlg.m_nMouseButtons == 3) // 3 button mouse
+ {
+ if ((GetKeyState(VK_CONTROL) & 0x8000))
+ {
+ if (ClipMode()) // already there?
+ DropClipPoint(nFlags, point);
+ else
+ {
+ SetClipMode(true);
+ g_bRogueClipMode = true;
+ DropClipPoint(nFlags, point);
+ }
+ return;
+ }
+ }
+ OriginalButtonDown(nFlags, point);
+}
+
+void CXYWnd::OnLButtonUp(UINT nFlags, CPoint point)
+{
+ // plugin entities
+ if (DispatchOnLButtonUp(nFlags, point.x, point.y ))
+ return;
+
+ if (ClipMode())
+ {
+ if (g_pMovingClip)
+ {
+ ReleaseCapture();
+ g_pMovingClip = NULL;
+ }
+ }
+ OriginalButtonUp(nFlags, point);
+}
+
+void CXYWnd::OnMButtonUp(UINT nFlags, CPoint point)
+{
+ OriginalButtonUp(nFlags, point);
+}
+
+void CXYWnd::OnRButtonUp(UINT nFlags, CPoint point)
+{
+ m_bRButtonDown = false;
+ if (point == m_ptDown) // mouse didn't move
+ {
+ bool bGo = true;
+ if ((GetKeyState(VK_MENU) & 0x8000))
+ bGo = false;
+ if ((GetKeyState(VK_CONTROL) & 0x8000))
+ bGo = false;
+ if ((GetKeyState(VK_SHIFT) & 0x8000))
+ bGo = false;
+ if (bGo)
+ HandleDrop();
+ }
+ OriginalButtonUp(nFlags, point);
+}
+
+void CXYWnd::OriginalButtonDown(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ SetWindowPos(&wndTop, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);
+ if (::GetTopWindow( g_qeglobals.d_hwndMain ) != GetSafeHwnd())
+ ::BringWindowToTop(GetSafeHwnd());
+ SetFocus();
+ SetCapture();
+ XY_MouseDown (point.x, rctZ.Height() - 1 - point.y , nFlags);
+ m_nScrollFlags = nFlags;
+}
+
+void CXYWnd::OriginalButtonUp(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ XY_MouseUp (point.x, rctZ.Height() - 1 - point.y , nFlags);
+ if (! (nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+}
+
+
+float fDiff(float f1, float f2)
+{
+ if (f1 > f2)
+ return f1 - f2;
+ else
+ return f2 - f1;
+}
+
+
+vec3_t tdp;
+void CXYWnd::OnMouseMove(UINT nFlags, CPoint point)
+{
+ // plugin entities
+ //++timo TODO: handle return code
+ DispatchOnMouseMove( nFlags, point.x, point.y );
+
+ m_ptDown.x = 0;
+ m_ptDown.y = 0;
+
+ if ( g_PrefsDlg.m_bChaseMouse == TRUE &&
+ (point.x < 0 || point.y < 0 ||
+ point.x > m_nWidth || point.y > m_nHeight) &&
+ GetCapture() == this)
+ {
+ float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
+ //m_ptDrag = point;
+ m_ptDragAdj.x = 0;
+ m_ptDragAdj.y = 0;
+ if (point.x < 0)
+ {
+ m_ptDragAdj.x = -fAdjustment;
+ }
+ else
+ if (point.x > m_nWidth)
+ {
+ m_ptDragAdj.x = fAdjustment;
+ }
+ if (point.y < 0)
+ {
+ m_ptDragAdj.y = -fAdjustment;
+ }
+ else
+ if (point.y > m_nHeight)
+ {
+ m_ptDragAdj.y = fAdjustment;
+ }
+ if (m_nTimerID == -1)
+ {
+ m_nTimerID = SetTimer(100, 50, NULL);
+ m_ptDrag = point;
+ m_ptDragTotal = 0;
+ }
+ return;
+ }
+ //else if (m_nTimerID != -1)
+ if (m_nTimerID != -1)
+ {
+ KillTimer(m_nTimerID);
+ pressx -= m_ptDragTotal.x;
+ pressy += m_ptDragTotal.y;
+ m_nTimerID = -1;
+ //return;
+ }
+
+ bool bCrossHair = false;
+ if (!m_bRButtonDown)
+ {
+ tdp[0] = tdp[1] = tdp[2] = 0.0;
+ SnapToPoint (point.x, m_nHeight - 1 - point.y , tdp);
+
+ g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]);
+ g_pParentWnd->SetStatusText(1, g_strStatus);
+
+ // i need to generalize the point code.. having 3 flavors pretty much sucks..
+ // once the new curve stuff looks like it is going to stick i will
+ // rationalize this down to a single interface..
+ if (PointMode())
+ {
+ if (g_pMovingPoint && GetCapture() == this)
+ {
+ bCrossHair = true;
+ SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingPoint->m_ptClip);
+ g_pMovingPoint->UpdatePointPtr();
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+ }
+ else
+ {
+ g_pMovingPoint = NULL;
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ for (int n = 0; n < g_nPointCount; n++)
+ {
+ if ( fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
+ fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
+ {
+ bCrossHair = true;
+ g_pMovingPoint = &g_PointPoints[n];
+ }
+ }
+ }
+ }
+ else if (ClipMode())
+ {
+ if (g_pMovingClip && GetCapture() == this)
+ {
+ bCrossHair = true;
+ SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingClip->m_ptClip);
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+ }
+ else
+ {
+ g_pMovingClip = NULL;
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ if (g_Clip1.Set())
+ {
+ if ( fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
+ fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3 )
+ {
+ bCrossHair = true;
+ g_pMovingClip = &g_Clip1;
+ }
+ }
+ if (g_Clip2.Set())
+ {
+ if ( fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
+ fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3 )
+ {
+ bCrossHair = true;
+ g_pMovingClip = &g_Clip2;
+ }
+ }
+ if (g_Clip3.Set())
+ {
+ if ( fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
+ fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3 )
+ {
+ bCrossHair = true;
+ g_pMovingClip = &g_Clip3;
+ }
+ }
+ }
+ if (bCrossHair == false)
+ XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags);
+ }
+ else if (PathMode())
+ {
+ if (g_pMovingPath && GetCapture() == this)
+ {
+ bCrossHair = true;
+ SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingPath->m_ptClip);
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+ }
+ else
+ {
+ g_pMovingPath = NULL;
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ for (int n = 0; n < g_nPathCount; n++)
+ {
+ if ( fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
+ fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
+ {
+ bCrossHair = true;
+ g_pMovingPath = &g_PathPoints[n];
+ }
+ }
+ }
+ }
+ else
+ {
+ XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags);
+ }
+ }
+ else
+ {
+ XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags);
+ }
+ if (bCrossHair)
+ SetCursor(::LoadCursor(NULL, IDC_CROSS));
+ else
+ SetCursor(::LoadCursor(NULL, IDC_ARROW));
+}
+
+void CXYWnd::RetainClipMode(bool bMode)
+{
+ bool bSave = g_bRogueClipMode;
+ SetClipMode(bMode);
+ if (bMode == true)
+ g_bRogueClipMode = bSave;
+ else
+ g_bRogueClipMode = false;
+}
+
+void CXYWnd::SetClipMode(bool bMode)
+{
+ g_bClipMode = bMode;
+ g_bRogueClipMode = false;
+ if (bMode)
+ {
+ g_Clip1.Reset();
+ g_Clip2.Reset();
+ g_Clip3.Reset();
+ CleanList(&g_brFrontSplits);
+ CleanList(&g_brBackSplits);
+ g_brFrontSplits.next = &g_brFrontSplits;
+ g_brBackSplits.next = &g_brBackSplits;
+ }
+ else
+ {
+ if (g_pMovingClip)
+ {
+ ReleaseCapture();
+ g_pMovingClip = NULL;
+ }
+ CleanList(&g_brFrontSplits);
+ CleanList(&g_brBackSplits);
+ g_brFrontSplits.next = &g_brFrontSplits;
+ g_brBackSplits.next = &g_brBackSplits;
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+ }
+}
+
+bool CXYWnd::ClipMode()
+{
+ return g_bClipMode;
+}
+
+bool CXYWnd::RogueClipMode()
+{
+ return g_bRogueClipMode;
+}
+
+bool CXYWnd::PathMode()
+{
+ return g_bPathMode;
+}
+
+
+bool CXYWnd::PointMode()
+{
+ return g_bPointMode;
+}
+
+void CXYWnd::SetPointMode(bool b)
+{
+ g_bPointMode = b;
+ if (!b)
+ g_nPointCount = 0;
+}
+
+
+void CXYWnd::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+ bool bPaint = true;
+ if (!qwglMakeCurrent(dc.m_hDC, s_hglrcXY))
+ {
+ Sys_Printf("ERROR: wglMakeCurrent failed.. Error:%i\n",qglGetError());
+ Sys_Printf("Please restart Q3Radiant if the Map view is not working\n");
+ bPaint = false;
+ }
+ if (bPaint)
+ {
+ QE_CheckOpenGLForErrors();
+ XY_Draw ();
+ QE_CheckOpenGLForErrors();
+
+ if (m_nViewType != XY)
+ {
+ qglPushMatrix();
+ if (m_nViewType == YZ)
+ qglRotatef (-90, 0, 1, 0); // put Z going up
+ qglRotatef (-90, 1, 0, 0); // put Z going up
+ }
+
+ if (g_bCrossHairs)
+ {
+ qglColor4f(0.2, 0.9, 0.2, 0.8);
+ qglBegin (GL_LINES);
+ if (m_nViewType == XY)
+ {
+ qglVertex2f(-16384, tdp[1]);
+ qglVertex2f(16384, tdp[1]);
+ qglVertex2f(tdp[0], -16384);
+ qglVertex2f(tdp[0], 16384);
+ }
+ else if (m_nViewType == YZ)
+ {
+ qglVertex3f(tdp[0], -16384, tdp[2]);
+ qglVertex3f(tdp[0], 16384, tdp[2]);
+ qglVertex3f(tdp[0], tdp[1], -16384);
+ qglVertex3f(tdp[0], tdp[1], 16384);
+ }
+ else
+ {
+ qglVertex3f(-16384, tdp[1], tdp[2]);
+ qglVertex3f( 16384, tdp[1], tdp[2]);
+ qglVertex3f(tdp[0], tdp[1], -16384);
+ qglVertex3f(tdp[0], tdp[1], 16384);
+ }
+ qglEnd();
+ }
+
+ if (ClipMode())
+ {
+ qglPointSize (4);
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
+ qglBegin (GL_POINTS);
+ if (g_Clip1.Set())
+ qglVertex3fv (g_Clip1);
+ if (g_Clip2.Set())
+ qglVertex3fv (g_Clip2);
+ if (g_Clip3.Set())
+ qglVertex3fv (g_Clip3);
+ qglEnd ();
+ qglPointSize (1);
+
+ CString strMsg;
+ if (g_Clip1.Set())
+ {
+ qglRasterPos3f (g_Clip1.m_ptClip[0]+2, g_Clip1.m_ptClip[1]+2, g_Clip1.m_ptClip[2]+2);
+ strMsg = "1";
+ //strMsg.Format("1 (%f, %f, %f)", g_Clip1[0], g_Clip1[1], g_Clip1[2]);
+ qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
+ }
+ if (g_Clip2.Set())
+ {
+ qglRasterPos3f (g_Clip2.m_ptClip[0]+2, g_Clip2.m_ptClip[1]+2, g_Clip2.m_ptClip[2]+2);
+ strMsg = "2";
+ //strMsg.Format("2 (%f, %f, %f)", g_Clip2[0], g_Clip2[1], g_Clip2[2]);
+ qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
+ }
+ if (g_Clip3.Set())
+ {
+ qglRasterPos3f (g_Clip3.m_ptClip[0]+2, g_Clip3.m_ptClip[1]+2, g_Clip3.m_ptClip[2]+2);
+ strMsg = "3";
+ //strMsg.Format("3 (%f, %f, %f)", g_Clip3[0], g_Clip3[1], g_Clip3[2]);
+ qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
+ }
+ if (g_Clip1.Set() && g_Clip2.Set())
+ {
+ ProduceSplitLists();
+ brush_t* pBrush;
+ brush_t* pList = ( (m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
+ for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next)
+ {
+ qglColor3f (1,1,0);
+ face_t *face;
+ int order;
+ for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++)
+ {
+ winding_t* w = face->face_winding;
+ if (!w)
+ continue;
+ // draw the polygon
+ qglBegin(GL_LINE_LOOP);
+ for (int i=0 ; i<w->numpoints ; i++)
+ qglVertex3fv(w->points[i]);
+ qglEnd();
+ }
+ }
+ }
+
+ }
+
+
+
+ if (PathMode())
+ {
+ qglPointSize (4);
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
+ qglBegin (GL_POINTS);
+
+ for (int n = 0; n < g_nPathCount; n++)
+ qglVertex3fv(g_PathPoints[n]);
+ qglEnd ();
+ qglPointSize (1);
+
+ CString strMsg;
+ for (n = 0; n < g_nPathCount; n++)
+ {
+ qglRasterPos3f (g_PathPoints[n].m_ptClip[0]+2, g_PathPoints[n].m_ptClip[1]+2, g_PathPoints[n].m_ptClip[2]+2);
+ strMsg.Format("%i", n+1);
+ qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
+ }
+
+ }
+ if (m_nViewType != XY)
+ qglPopMatrix();
+
+ qwglSwapBuffers(dc.m_hDC);
+ TRACE("XY Paint\n");
+ }
+ }
+
+void CXYWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
+}
+
+
+
+// FIXME: the brush_t *pBrush is never used. ( Entity_Create uses selected_brushes )
+void CreateEntityFromName(char* pName, brush_t* pBrush)
+{
+ eclass_t *pecNew;
+ entity_t *petNew;
+ if (stricmp(pName, "worldspawn") == 0)
+ {
+ MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0);
+ return;
+ }
+
+ pecNew = Eclass_ForName(pName, false);
+
+ // create it
+ petNew = Entity_Create(pecNew);
+ if (petNew == NULL)
+ {
+ if (!((selected_brushes.next == &selected_brushes)||(selected_brushes.next->next != &selected_brushes)))
+ {
+ brush_t* b = selected_brushes.next;
+ if (b->owner != world_entity && b->owner->eclass->fixedsize && pecNew->fixedsize)
+ {
+ vec3_t mins, maxs;
+ vec3_t origin;
+ for (int i=0 ; i<3 ; i++)
+ origin[i] = b->mins[i] - pecNew->mins[i];
+
+ VectorAdd (pecNew->mins, origin, mins);
+ VectorAdd (pecNew->maxs, origin, maxs);
+ brush_t* nb = Brush_Create (mins, maxs, &pecNew->texdef);
+ Entity_LinkBrush (b->owner, nb);
+ nb->owner->eclass = pecNew;
+ SetKeyValue (nb->owner, "classname", pName);
+ Brush_Free(b);
+ Brush_Build(nb);
+ Brush_AddToList (nb, &active_brushes);
+ Select_Brush(nb);
+ return;
+ }
+ }
+ MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0);
+ return;
+ }
+
+ Select_Deselect ();
+ //entity_t* pEntity = world_entity;
+ //if (selected_brushes.next != &selected_brushes)
+ // pEntity = selected_brushes.next->owner;
+ Select_Brush (petNew->brushes.onext);
+
+ if (stricmp(pName, "misc_model") == 0)
+ {
+ SetInspectorMode(W_ENTITY);
+ PostMessage(g_qeglobals.d_hwndEntity, WM_COMMAND, IDC_BTN_ASSIGNMODEL, 0);
+ }
+
+}
+
+
+brush_t* CreateEntityBrush(int x, int y, CXYWnd* pWnd)
+{
+ vec3_t mins, maxs;
+ int i;
+ float temp;
+ brush_t *n;
+
+ pWnd->SnapToPoint (x, y, mins);
+ x += 32;
+ y += 32;
+ pWnd->SnapToPoint (x, y, maxs);
+
+ int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
+ mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize));
+ maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize));
+
+ if (maxs[nDim] <= mins[nDim])
+ maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (mins[i] == maxs[i])
+ maxs[i] += 16; // don't create a degenerate brush
+ if (mins[i] > maxs[i])
+ {
+ temp = mins[i];
+ mins[i] = maxs[i];
+ maxs[i] = temp;
+ }
+ }
+
+ n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
+ if (!n)
+ return NULL;
+
+ Brush_AddToList (n, &selected_brushes);
+ Entity_LinkBrush (world_entity, n);
+ Brush_Build( n );
+ return n;
+}
+
+void CreateRightClickEntity(CXYWnd* pWnd, int x, int y, char* pName)
+{
+ CRect rctZ;
+ pWnd->GetClientRect(rctZ);
+ brush_t* pBrush = (selected_brushes.next == &selected_brushes) ? CreateEntityBrush(x, rctZ.Height() - 1 - y, pWnd) : selected_brushes.next;
+ CreateEntityFromName(pName, pBrush);
+ //Select_Brush(pBrush);
+}
+
+brush_t* CreateSmartBrush(vec3_t v)
+{
+ vec3_t mins, maxs;
+ int i;
+ brush_t *n;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ mins[i] = v[i] - 16;
+ maxs[i] = v[i] + 16;
+ }
+
+ n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
+ if (!n)
+ return NULL;
+
+ Brush_AddToList(n, &selected_brushes);
+ //Entity_LinkBrush(world_entity, n);
+ Brush_Build(n);
+ return n;
+}
+
+
+
+
+CString g_strSmartEntity;
+int g_nSmartX;
+int g_nSmartY;
+bool g_bSmartWaiting;
+void _SmartPointDone(bool b, int n)
+{
+ g_bSmartWaiting = false;
+}
+
+void CreateSmartEntity(CXYWnd* pWnd, int x, int y, const char* pName)
+{
+ g_nSmartX = x;
+ g_nSmartY = y;
+ g_strSmartEntity = pName;
+ if (g_strSmartEntity.Find("Smart_Train") >= 0)
+ {
+ ShowInfoDialog("Select the path of the train by left clicking in XY, YZ and/or XZ views. You can move an already dropped point by grabbing and moving it. When you are finished, press ENTER to accept and create the entity and path(s), press ESC to abandon the creation");
+ g_bPathMode = true;
+ g_nPathLimit = 0;
+ g_nPathCount = 0;
+ g_bSmartGo = true;
+ }
+ else
+ if (g_strSmartEntity.Find("Smart_Monster...") >= 0)
+ {
+ g_bPathMode = true;
+ g_nPathLimit = 0;
+ g_nPathCount = 0;
+ }
+ else
+ if (g_strSmartEntity.Find("Smart_Rotating") >= 0)
+ {
+ g_bSmartWaiting = true;
+ ShowInfoDialog("Left click to specify the rotation origin");
+ AcquirePath(1, &_SmartPointDone);
+ while (g_bSmartWaiting)
+ {
+ MSG msg;
+ if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ HideInfoDialog();
+ CPtrArray array;
+ g_bScreenUpdates = false;
+ CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
+ array.Add(reinterpret_cast<void*>(selected_brushes.next));
+ Select_Deselect();
+ brush_t* pBrush = CreateSmartBrush(g_PathPoints[0]);
+ array.Add(pBrush);
+ Select_Deselect();
+ Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(0)));
+ Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(1)));
+ ConnectEntities();
+ g_bScreenUpdates = true;
+ }
+}
+
+
+void FinishSmartCreation()
+{
+ CPtrArray array;
+ HideInfoDialog();
+ brush_t* pEntities = NULL;
+ if (g_strSmartEntity.Find("Smart_Train") >= 0)
+ {
+ g_bScreenUpdates = false;
+ CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
+ array.Add(reinterpret_cast<void*>(selected_brushes.next));
+ for (int n = 0; n < g_nPathCount; n++)
+ {
+ Select_Deselect();
+ CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_PathPoints[n].m_ptScreen.x,g_PathPoints[n].m_ptScreen.y, "path_corner");
+ array.Add(reinterpret_cast<void*>(selected_brushes.next));
+ }
+
+ for (n = 0; n < g_nPathCount; n++)
+ {
+ Select_Deselect();
+ Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n)));
+ Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n+1)));
+ ConnectEntities();
+ }
+ g_bScreenUpdates = true;
+
+ }
+ g_nPathCount = 0;
+ g_bPathMode = false;
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CXYWnd::KillPathMode()
+{
+ g_bSmartGo = false;
+ g_bPathMode = false;
+ if (g_pPathFunc)
+ g_pPathFunc(false, g_nPathCount);
+ g_nPathCount = 0;
+ g_pPathFunc = NULL;
+ Sys_UpdateWindows(W_ALL);
+}
+
+// gets called for drop down menu messages
+// TIP: it's not always about EntityCreate
+void CXYWnd::OnEntityCreate(unsigned int nID)
+{
+ if (m_mnuDrop.GetSafeHmenu())
+ {
+ CString strItem;
+ m_mnuDrop.GetMenuString(nID, strItem, MF_BYCOMMAND);
+
+ if (strItem.CompareNoCase("Add to...") == 0)
+ {
+ //++timo TODO: fill the menu with current groups?
+ // this one is for adding to existing groups only
+ Sys_Printf("TODO: Add to... in CXYWnd::OnEntityCreate\n");
+ }
+ else if (strItem.CompareNoCase("Remove") == 0)
+ {
+ // remove selected brushes from their current group
+ brush_t *b;
+ for( b = selected_brushes.next; b != &selected_brushes; b = b->next )
+ {
+
+ }
+ }
+
+ //++timo FIXME: remove when all hooks are in
+ if (strItem.CompareNoCase("Add to...") == 0
+ || strItem.CompareNoCase("Remove") == 0
+ || strItem.CompareNoCase("Name...") == 0
+ || strItem.CompareNoCase("New group...") == 0)
+ {
+ Sys_Printf("TODO: hook drop down group menu\n");
+ return;
+ }
+
+ if (strItem.Find("Smart_") >= 0)
+ {
+ CreateSmartEntity(this, m_ptDown.x, m_ptDown.y, strItem);
+ }
+ else
+ {
+ CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, strItem.GetBuffer(0));
+ }
+
+ Sys_UpdateWindows(W_ALL);
+ //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
+ }
+}
+
+
+void CXYWnd::HandleDrop()
+{
+ if (g_PrefsDlg.m_bRightClick == false)
+ return;
+ if (!m_mnuDrop.GetSafeHmenu()) // first time, load it up
+ {
+ m_mnuDrop.CreatePopupMenu();
+ int nID = ID_ENTITY_START;
+
+ CMenu* pChild2 = new CMenu;
+ pChild2->CreateMenu();
+ pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTCOMPLETETALL, "Select Complete Tall");
+ pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTTOUCHING, "Select Touching");
+ pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTPARTIALTALL, "Select Partial Tall");
+ pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTINSIDE, "Select Inside");
+ m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild2->GetSafeHmenu()), "Select");
+ m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
+
+ CMenu* pChild3 = new CMenu;
+ pChild3->CreateMenu();
+ pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_ADDTO, "Add to...");
+ pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_REMOVE, "Remove");
+ pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_NAME, "Name...");
+ pChild3->AppendMenu(MF_SEPARATOR, nID++, "");
+ pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_NEWGROUP, "New Group...");
+ m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild3->GetSafeHmenu()), "Group");
+ m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
+
+ m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_UNGROUPENTITY, "Ungroup Entity");
+ m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_MAKE_DETAIL, "Make Detail");
+ m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_MAKE_STRUCTURAL, "Make Structural");
+ m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
+
+ CMenu* pChild = new CMenu;
+ pChild->CreateMenu();
+ pChild->AppendMenu(MF_STRING, nID++, "Smart_Train");
+ //pChild->AppendMenu(MF_STRING, nID++, "Smart_Rotating");
+ m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), "Smart Entities");
+ m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, "");
+
+ pChild = NULL;
+ eclass_t *e;
+ CString strActive;
+ CString strLast;
+ CString strName;
+ for (e=eclass ; e ; e=e->next)
+ {
+ strLast = strName;
+ strName = e->name;
+ int n_ = strName.Find("_");
+ if (n_ > 0)
+ {
+ CString strLeft = strName.Left(n_);
+ CString strRight = strName.Right(strName.GetLength() - n_ - 1);
+ if (strLeft == strActive) // this is a child
+ {
+ ASSERT(pChild);
+ pChild->AppendMenu(MF_STRING, nID++, strName);
+ }
+ else
+ {
+ if (pChild)
+ {
+ m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), strActive);
+ g_ptrMenus.Add(pChild);
+ //pChild->DestroyMenu();
+ //delete pChild;
+ pChild = NULL;
+ }
+ strActive = strLeft;
+ pChild = new CMenu;
+ pChild->CreateMenu();
+ pChild->AppendMenu(MF_STRING, nID++, strName);
+ }
+ }
+ else
+ {
+ if (pChild)
+ {
+ m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), strActive);
+ g_ptrMenus.Add(pChild);
+ //pChild->DestroyMenu();
+ //delete pChild;
+ pChild = NULL;
+ }
+ strActive = "";
+ m_mnuDrop.AppendMenu(MF_STRING, nID++, strName);
+ }
+ }
+ }
+
+ CPoint ptMouse;
+ GetCursorPos(&ptMouse);
+ m_mnuDrop.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, this);
+}
+
+void CXYWnd::XY_Init()
+{
+ m_vOrigin[0] = 0;
+ m_vOrigin[1] = 20;
+ m_vOrigin[2] = 46;
+ m_fScale = 1;
+}
+
+void CXYWnd::SnapToPoint (int x, int y, vec3_t point)
+{
+ if (g_PrefsDlg.m_bNoClamp)
+ {
+ XY_ToPoint(x, y, point);
+ }
+ else
+ {
+ XY_ToGridPoint(x, y, point);
+ }
+//-- else
+//-- XY_ToPoint(x, y, point);
+//-- //XY_ToPoint(x, y, point);
+}
+
+
+void CXYWnd::XY_ToPoint (int x, int y, vec3_t point)
+{
+ float fx = x;
+ float fy = y;
+ float fw = m_nWidth;
+ float fh = m_nHeight;
+ if (m_nViewType == XY)
+ {
+ point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
+ point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
+ //point[2] = 0;
+ }
+ else if (m_nViewType == YZ)
+ {
+ ////point[0] = 0;
+ //point[1] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
+ //point[2] = m_vOrigin[1] + (fy - fh / 2 ) / m_fScale;
+ point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
+ point[2] = m_vOrigin[2] + (fy - fh / 2 ) / m_fScale;
+ }
+ else
+ {
+ //point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
+ ////point[1] = 0;
+ //point[2] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
+ point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
+ //point[1] = 0;
+ point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
+ }
+}
+
+
+void CXYWnd::XY_ToGridPoint (int x, int y, vec3_t point)
+{
+ if (m_nViewType == XY)
+ {
+ point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
+ point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
+ //point[2] = 0;
+ point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ }
+ else if (m_nViewType == YZ)
+ {
+ //point[0] = 0;
+ //point[1] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
+ //point[2] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
+ point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
+ point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
+ point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ }
+ else
+ {
+ //point[1] = 0;
+ //point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
+ //point[2] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
+ point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
+ point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
+ point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ }
+}
+
+
+void CXYWnd::XY_MouseDown (int x, int y, int buttons)
+{
+
+ vec3_t point;
+ vec3_t origin, dir, right, up;
+
+ m_nButtonstate = buttons;
+ m_nPressx = x;
+ m_nPressy = y;
+ VectorCopy (vec3_origin, m_vPressdelta);
+
+ XY_ToPoint (x, y, point);
+
+ VectorCopy (point, origin);
+
+ dir[0] = 0; dir[1] = 0; dir[2] = 0;
+ if (m_nViewType == XY)
+ {
+ origin[2] = 8192;
+ dir[2] = -1;
+ right[0] = 1 / m_fScale;
+ right[1] = 0;
+ right[2] = 0;
+ up[0] = 0;
+ up[1] = 1 / m_fScale;
+ up[2] = 0;
+ }
+ else if (m_nViewType == YZ)
+ {
+ origin[0] = 8192;
+ dir[0] = -1;
+ right[1] = 1 / m_fScale;
+ right[2] = 0;
+ right[0] = 0;
+ up[0] = 0;
+ up[2] = 1 / m_fScale;
+ up[1] = 0;
+ }
+ else
+ {
+ origin[1] = 8192;
+ dir[1] = -1;
+ right[0] = 1 / m_fScale;
+ right[2] = 0;
+ right[1] = 0;
+ up[0] = 0;
+ up[2] = 1 / m_fScale;
+ up[1] = 0;
+ }
+
+
+ m_bPress_selection = (selected_brushes.next != &selected_brushes);
+
+ GetCursorPos(&m_ptCursor);
+ //Sys_GetCursorPos (&m_ptCursor.x, &m_ptCursor.y);
+
+ // lbutton = manipulate selection
+ // shift-LBUTTON = select
+ if ( (buttons == MK_LBUTTON)
+ || (buttons == (MK_LBUTTON | MK_SHIFT))
+ || (buttons == (MK_LBUTTON | MK_CONTROL))
+ || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
+ {
+ if (g_qeglobals.d_select_mode == sel_addpoint) {
+ XY_ToGridPoint(x, y, point);
+ if (g_qeglobals.selectObject) {
+ g_qeglobals.selectObject->addPoint(point[0], point[1], point[2]);
+ }
+ return;
+ }
+ Patch_SetView( (m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
+ Drag_Begin (x, y, buttons, right, up, origin, dir);
+ return;
+ }
+
+ int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+
+ // control mbutton = move camera
+ if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
+ {
+ VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
+ Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
+ }
+
+ // mbutton = angle camera
+ if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
+ (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
+ {
+ VectorSubtract (point, g_pParentWnd->GetCamera()->Camera().origin, point);
+
+ int n1 = (m_nViewType == XY) ? 1 : 2;
+ int n2 = (m_nViewType == YZ) ? 1 : 0;
+ int nAngle = (m_nViewType == XY) ? YAW : PITCH;
+ if (point[n1] || point[n2])
+ {
+ g_pParentWnd->GetCamera()->Camera().angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
+ Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
+ }
+ }
+
+ // shift mbutton = move z checker
+ if (m_nButtonstate == (MK_SHIFT | nMouseButton))
+ {
+ if (RotateMode() || g_bPatchBendMode)
+ {
+ SnapToPoint (x, y, point);
+ VectorCopyXY(point, g_vRotateOrigin);
+ if (g_bPatchBendMode)
+ {
+ VectorCopy(point, g_vBendOrigin);
+ }
+ Sys_UpdateWindows (W_XY);
+ return;
+ }
+ else
+ {
+ SnapToPoint (x, y, point);
+ if (m_nViewType == XY)
+ {
+ z.origin[0] = point[0];
+ z.origin[1] = point[1];
+ }
+ else if (m_nViewType == YZ)
+ {
+ z.origin[0] = point[1];
+ z.origin[1] = point[2];
+ }
+ else
+ {
+ z.origin[0] = point[0];
+ z.origin[1] = point[2];
+ }
+ Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
+ return;
+ }
+ }
+}
+
+
+void CXYWnd::XY_MouseUp(int x, int y, int buttons)
+{
+ Drag_MouseUp (buttons);
+ if (!m_bPress_selection)
+ Sys_UpdateWindows (W_ALL);
+ m_nButtonstate = 0;
+ while (::ShowCursor(TRUE) < 0)
+ ;
+}
+
+qboolean CXYWnd::DragDelta (int x, int y, vec3_t move)
+{
+ vec3_t xvec, yvec, delta;
+ int i;
+
+ xvec[0] = 1 / m_fScale;
+ xvec[1] = xvec[2] = 0;
+ yvec[1] = 1 / m_fScale;
+ yvec[0] = yvec[2] = 0;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
+ if (!g_PrefsDlg.m_bNoClamp)
+ {
+ delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ }
+ }
+ VectorSubtract (delta, m_vPressdelta, move);
+ VectorCopy (delta, m_vPressdelta);
+
+ if (move[0] || move[1] || move[2])
+ return true;
+ return false;
+}
+
+
+/*
+==============
+NewBrushDrag
+==============
+*/
+void CXYWnd::NewBrushDrag (int x, int y)
+{
+ vec3_t mins, maxs, junk;
+ int i;
+ float temp;
+ brush_t *n;
+
+ if (!DragDelta (x,y, junk))
+ return;
+
+ // delete the current selection
+ if (selected_brushes.next != &selected_brushes)
+ Brush_Free (selected_brushes.next);
+
+ SnapToPoint (m_nPressx, m_nPressy, mins);
+
+ int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
+
+ mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z / g_qeglobals.d_gridsize));
+ SnapToPoint (x, y, maxs);
+ maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z / g_qeglobals.d_gridsize));
+ if (maxs[nDim] <= mins[nDim])
+ maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
+
+ for (i=0 ; i<3 ; i++)
+ {
+ if (mins[i] == maxs[i])
+ return; // don't create a degenerate brush
+ if (mins[i] > maxs[i])
+ {
+ temp = mins[i];
+ mins[i] = maxs[i];
+ maxs[i] = temp;
+ }
+ }
+
+ n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
+ if (!n)
+ return;
+
+ vec3_t vSize;
+ VectorSubtract(maxs, mins, vSize);
+ g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
+ g_pParentWnd->SetStatusText(2, g_strStatus);
+
+ Brush_AddToList (n, &selected_brushes);
+
+ Entity_LinkBrush (world_entity, n);
+
+ Brush_Build( n );
+
+ // Sys_UpdateWindows (W_ALL);
+ Sys_UpdateWindows (W_XY| W_CAMERA);
+
+}
+
+/*
+==============
+XY_MouseMoved
+==============
+*/
+void CXYWnd::XY_MouseMoved (int x, int y, int buttons)
+{
+ vec3_t point;
+
+
+ if (!m_nButtonstate)
+ {
+ if (g_bCrossHairs)
+ {
+ ::ShowCursor(FALSE);
+ Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
+ ::ShowCursor(TRUE);
+ }
+ return;
+ }
+
+ // lbutton without selection = drag new brush
+ //if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint && g_qeglobals.d_select_mode != sel_splineedit)
+ if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode == sel_brush)
+ {
+ NewBrushDrag (x, y);
+ return;
+ }
+
+ // lbutton (possibly with control and or shift)
+ // with selection = drag selection
+ if (m_nButtonstate & MK_LBUTTON)
+ {
+ Drag_MouseMoved (x, y, buttons);
+ Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
+ return;
+ }
+
+ int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+ // control mbutton = move camera
+ if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
+ {
+ SnapToPoint (x, y, point);
+ VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
+ Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
+ return;
+ }
+
+ // shift mbutton = move z checker
+ if (m_nButtonstate == (MK_SHIFT|nMouseButton) )
+ {
+ if (RotateMode() || g_bPatchBendMode)
+ {
+ SnapToPoint (x, y, point);
+ VectorCopyXY(point, g_vRotateOrigin);
+ if (g_bPatchBendMode)
+ {
+ VectorCopy(point, g_vBendOrigin);
+ }
+ Sys_UpdateWindows (W_XY);
+ return;
+ }
+ else
+ {
+ SnapToPoint (x, y, point);
+ if (m_nViewType == XY)
+ {
+ z.origin[0] = point[0];
+ z.origin[1] = point[1];
+ }
+ else if (m_nViewType == YZ)
+ {
+ z.origin[0] = point[1];
+ z.origin[1] = point[2];
+ }
+ else
+ {
+ z.origin[0] = point[0];
+ z.origin[1] = point[2];
+ }
+ }
+ Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
+ return;
+ }
+
+ // mbutton = angle camera
+ if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
+ (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
+ {
+ SnapToPoint (x, y, point);
+ VectorSubtract (point, g_pParentWnd->GetCamera()->Camera().origin, point);
+
+ int n1 = (m_nViewType == XY) ? 1 : 2;
+ int n2 = (m_nViewType == YZ) ? 1 : 0;
+ int nAngle = (m_nViewType == XY) ? YAW : PITCH;
+ if (point[n1] || point[n2])
+ {
+ g_pParentWnd->GetCamera()->Camera().angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
+ Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
+ }
+ return;
+ }
+
+
+ // rbutton = drag xy origin
+ if (m_nButtonstate == MK_RBUTTON)
+ {
+ Sys_GetCursorPos (&x, &y);
+ if (x != m_ptCursor.x || y != m_ptCursor.y)
+ {
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ m_vOrigin[nDim1] -= (x - m_ptCursor.x) / m_fScale;
+ m_vOrigin[nDim2] += (y - m_ptCursor.y) / m_fScale;
+ SetCursorPos (m_ptCursor.x, m_ptCursor.y);
+ ::ShowCursor(FALSE);
+ //XY_Draw();
+ //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
+ //::ShowCursor(TRUE);
+ }
+ return;
+ }
+
+}
+
+
+/*
+============================================================================
+
+DRAWING
+
+============================================================================
+*/
+
+
+/*
+==============
+XY_DrawGrid
+==============
+*/
+void CXYWnd::XY_DrawGrid()
+{
+ float x, y, xb, xe, yb, ye;
+ int w, h;
+ char text[32];
+
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglDisable(GL_DEPTH_TEST);
+ qglDisable(GL_BLEND);
+
+ w = m_nWidth / 2 / m_fScale;
+ h = m_nHeight / 2 / m_fScale;
+
+
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ //int nDim1 = 0;
+ //int nDim2 = 1;
+
+
+ xb = m_vOrigin[nDim1] - w;
+ if (xb < region_mins[nDim1])
+ xb = region_mins[nDim1];
+ xb = 64 * floor (xb/64);
+
+ xe = m_vOrigin[nDim1] + w;
+ if (xe > region_maxs[nDim1])
+ xe = region_maxs[nDim1];
+ xe = 64 * ceil (xe/64);
+
+ yb = m_vOrigin[nDim2] - h;
+ if (yb < region_mins[nDim2])
+ yb = region_mins[nDim2];
+ yb = 64 * floor (yb/64);
+
+ ye = m_vOrigin[nDim2] + h;
+ if (ye > region_maxs[nDim2])
+ ye = region_maxs[nDim2];
+ ye = 64 * ceil (ye/64);
+
+ // draw major blocks
+
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]);
+
+ int stepSize = 64 * 0.1 / m_fScale;
+ if (stepSize < 64) {
+ stepSize = 64;
+ } else {
+ int i;
+ for (i = 1; i < stepSize; i <<= 1) {
+ }
+ stepSize = i;
+ }
+
+ if ( g_qeglobals.d_showgrid )
+ {
+
+ qglBegin (GL_LINES);
+
+ for (x=xb ; x<=xe ; x+=stepSize)
+ {
+ qglVertex2f (x, yb);
+ qglVertex2f (x, ye);
+ }
+ for (y=yb ; y<=ye ; y+=stepSize)
+ {
+ qglVertex2f (xb, y);
+ qglVertex2f (xe, y);
+ }
+
+ qglEnd ();
+
+ }
+
+ // draw minor blocks
+ if ( m_fScale > .1 && g_qeglobals.d_showgrid && g_qeglobals.d_gridsize * m_fScale >= 4 &&
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR] != g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK])
+ {
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
+
+ qglBegin (GL_LINES);
+ for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
+ {
+ if ( ! ((int)x & 63) )
+ continue;
+ qglVertex2f (x, yb);
+ qglVertex2f (x, ye);
+ }
+ for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
+ {
+ if ( ! ((int)y & 63) )
+ continue;
+ qglVertex2f (xb, y);
+ qglVertex2f (xe, y);
+ }
+ qglEnd ();
+ }
+
+ // draw coordinate text if needed
+
+ if ( g_qeglobals.d_savedinfo.show_coordinates)
+ {
+ //glColor4f(0, 0, 0, 0);
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]);
+
+ for (x=xb ; x<xe ; x+=stepSize)
+ {
+ qglRasterPos2f (x, m_vOrigin[nDim2] + h - 6 / m_fScale);
+ sprintf (text, "%i",(int)x);
+ qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
+ }
+ for (y=yb ; y<ye ; y+=stepSize)
+ {
+ qglRasterPos2f (m_vOrigin[nDim1] - w + 1, y);
+ sprintf (text, "%i",(int)y);
+ qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
+ }
+
+
+ if (Active())
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
+
+ qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
+
+ char cView[20];
+ if (m_nViewType == XY)
+ strcpy(cView, "XY Top");
+ else
+ if (m_nViewType == XZ)
+ strcpy(cView, "XZ Front");
+ else
+ strcpy(cView, "YZ Side");
+
+ qglCallLists (strlen(cView), GL_UNSIGNED_BYTE, cView);
+
+
+ }
+
+
+/*
+ if (true)
+ {
+ qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
+ qglBegin (GL_LINES);
+ qglVertex2f (x, yb);
+ qglVertex2f (x, ye);
+ qglEnd();
+ }
+ */
+
+}
+
+/*
+==============
+XY_DrawBlockGrid
+==============
+*/
+void CXYWnd::XY_DrawBlockGrid()
+{
+ float x, y, xb, xe, yb, ye;
+ int w, h;
+ char text[32];
+
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglDisable(GL_DEPTH_TEST);
+ qglDisable(GL_BLEND);
+
+ w = m_nWidth / 2 / m_fScale;
+ h = m_nHeight / 2 / m_fScale;
+
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+
+ xb = m_vOrigin[nDim1] - w;
+ if (xb < region_mins[nDim1])
+ xb = region_mins[nDim1];
+ xb = 1024 * floor (xb/1024);
+
+ xe = m_vOrigin[nDim1] + w;
+ if (xe > region_maxs[nDim1])
+ xe = region_maxs[nDim1];
+ xe = 1024 * ceil (xe/1024);
+
+ yb = m_vOrigin[nDim2] - h;
+ if (yb < region_mins[nDim2])
+ yb = region_mins[nDim2];
+ yb = 1024 * floor (yb/1024);
+
+ ye = m_vOrigin[nDim2] + h;
+ if (ye > region_maxs[nDim2])
+ ye = region_maxs[nDim2];
+ ye = 1024 * ceil (ye/1024);
+
+ // draw major blocks
+
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]);
+ qglLineWidth (2);
+
+ qglBegin (GL_LINES);
+
+ for (x=xb ; x<=xe ; x+=1024)
+ {
+ qglVertex2f (x, yb);
+ qglVertex2f (x, ye);
+ }
+ for (y=yb ; y<=ye ; y+=1024)
+ {
+ qglVertex2f (xb, y);
+ qglVertex2f (xe, y);
+ }
+
+ qglEnd ();
+ qglLineWidth (1);
+
+ // draw coordinate text if needed
+
+ for (x=xb ; x<xe ; x+=1024)
+ for (y=yb ; y<ye ; y+=1024)
+ {
+ qglRasterPos2f (x+512, y+512);
+ sprintf (text, "%i,%i",(int)floor(x/1024), (int)floor(y/1024) );
+ qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
+ }
+
+ qglColor4f(0, 0, 0, 0);
+}
+
+void CXYWnd::DrawRotateIcon()
+{
+ float x, y;
+
+ if (m_nViewType == XY)
+ {
+ x = g_vRotateOrigin[0];
+ y = g_vRotateOrigin[1];
+ }
+ else if (m_nViewType == YZ)
+ {
+ x = g_vRotateOrigin[1];
+ y = g_vRotateOrigin[2];
+ }
+ else
+ {
+ x = g_vRotateOrigin[0];
+ y = g_vRotateOrigin[2];
+ }
+
+ qglEnable (GL_BLEND);
+ qglDisable (GL_TEXTURE_2D);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglDisable (GL_CULL_FACE);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglColor4f (0.8, 0.1, 0.9, 0.25);
+
+ qglBegin(GL_QUADS);
+ qglVertex3f (x-4,y-4,0);
+ qglVertex3f (x+4,y-4,0);
+ qglVertex3f (x+4,y+4,0);
+ qglVertex3f (x-4,y+4,0);
+ qglEnd ();
+ qglDisable (GL_BLEND);
+
+ qglColor4f (1.0, 0.2, 1.0, 1);
+ qglBegin(GL_POINTS);
+ qglVertex3f (x,y,0);
+ qglEnd ();
+
+#if 0
+ qglBegin(GL_LINES);
+ qglVertex3f (x-6,y+6,0);
+ qglVertex3f (x+6,y+6,0);
+ qglVertex3f (x-6,y-6,0);
+ qglVertex3f (x+6,y-6,0);
+ qglEnd ();
+#endif
+
+}
+
+void CXYWnd::DrawCameraIcon()
+{
+ float x, y, a;
+
+ if (m_nViewType == XY)
+ {
+ x = g_pParentWnd->GetCamera()->Camera().origin[0];
+ y = g_pParentWnd->GetCamera()->Camera().origin[1];
+ a = g_pParentWnd->GetCamera()->Camera().angles[YAW]/180*Q_PI;
+ }
+ else if (m_nViewType == YZ)
+ {
+ x = g_pParentWnd->GetCamera()->Camera().origin[1];
+ y = g_pParentWnd->GetCamera()->Camera().origin[2];
+ a = g_pParentWnd->GetCamera()->Camera().angles[PITCH]/180*Q_PI;
+ }
+ else
+ {
+ x = g_pParentWnd->GetCamera()->Camera().origin[0];
+ y = g_pParentWnd->GetCamera()->Camera().origin[2];
+ a = g_pParentWnd->GetCamera()->Camera().angles[PITCH]/180*Q_PI;
+ }
+
+ qglColor3f (0.0, 0.0, 1.0);
+ qglBegin(GL_LINE_STRIP);
+ qglVertex3f (x-16,y,0);
+ qglVertex3f (x,y+8,0);
+ qglVertex3f (x+16,y,0);
+ qglVertex3f (x,y-8,0);
+ qglVertex3f (x-16,y,0);
+ qglVertex3f (x+16,y,0);
+ qglEnd ();
+
+ qglBegin(GL_LINE_STRIP);
+ qglVertex3f (x+48*cos(a+Q_PI/4), y+48*sin(a+Q_PI/4), 0);
+ qglVertex3f (x, y, 0);
+ qglVertex3f (x+48*cos(a-Q_PI/4), y+48*sin(a-Q_PI/4), 0);
+ qglEnd ();
+
+#if 0
+ char text[128];
+ qglRasterPos2f (x+64, y+64);
+ sprintf (text, "%f",g_pParentWnd->GetCamera()->Camera().angles[YAW]);
+ qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
+#endif
+
+}
+
+void CXYWnd::DrawZIcon (void)
+{
+ if (m_nViewType == XY)
+ {
+ float x = z.origin[0];
+ float y = z.origin[1];
+ qglEnable (GL_BLEND);
+ qglDisable (GL_TEXTURE_2D);
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+ qglDisable (GL_CULL_FACE);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglColor4f (0.0, 0.0, 1.0, 0.25);
+ qglBegin(GL_QUADS);
+ qglVertex3f (x-8,y-8,0);
+ qglVertex3f (x+8,y-8,0);
+ qglVertex3f (x+8,y+8,0);
+ qglVertex3f (x-8,y+8,0);
+ qglEnd ();
+ qglDisable (GL_BLEND);
+
+ qglColor4f (0.0, 0.0, 1.0, 1);
+
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f (x-8,y-8,0);
+ qglVertex3f (x+8,y-8,0);
+ qglVertex3f (x+8,y+8,0);
+ qglVertex3f (x-8,y+8,0);
+ qglEnd ();
+
+ qglBegin(GL_LINE_STRIP);
+ qglVertex3f (x-4,y+4,0);
+ qglVertex3f (x+4,y+4,0);
+ qglVertex3f (x-4,y-4,0);
+ qglVertex3f (x+4,y-4,0);
+ qglEnd ();
+ }
+}
+
+
+/*
+==================
+FilterBrush
+==================
+*/
+BOOL FilterBrush(brush_t *pb)
+{
+ if (!pb->owner)
+ return FALSE; // during construction
+
+ if (pb->hiddenBrush)
+ {
+ return TRUE;
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK)
+ {
+ // filter out the brush only if all faces are caulk
+ // if not don't hide the whole brush, proceed on a per-face basis (Cam_Draw)
+ //++timo TODO: set this as a preference .. show caulk: hide any brush with caulk // don't draw caulk faces
+ face_t *f;
+ f=pb->brush_faces;
+ while (f)
+ {
+ if (!strstr(f->texdef.name, "caulk"))
+ break;
+ f = f->next;
+ }
+ if (!f)
+ return TRUE;
+
+#if 0
+ if (strstr(pb->brush_faces->texdef.name, "caulk"))
+ return TRUE;
+#endif
+
+ //++timo FIXME: .. same deal here?
+ if (strstr(pb->brush_faces->texdef.name, "donotenter"))
+ return TRUE;
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT)
+ {
+ if (strstr(pb->brush_faces->texdef.name, "hint"))
+ return TRUE;
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP)
+ {
+ if (strstr(pb->brush_faces->texdef.name, "clip"))
+ return TRUE;
+
+ if (strstr(pb->brush_faces->texdef.name, "skip"))
+ return TRUE;
+
+ //if (!strncmp(pb->brush_faces->texdef.name, "clip", 4))
+ // return TRUE;
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER)
+ {
+ for (face_t* f = pb->brush_faces ; f ; f=f->next)
+ {
+ if (f->texdef.contents & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA))
+ return TRUE;
+ }
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL)
+ {
+ if (pb->brush_faces->texdef.contents & CONTENTS_DETAIL)
+ return TRUE;
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CURVES)
+ {
+ if (pb->patchBrush)
+ return TRUE;
+ }
+
+ if( g_qeglobals.d_savedinfo.exclude & EXCLUDE_TERRAIN )
+ {
+ if( pb->terrainBrush )
+ {
+ return TRUE;
+ }
+ }
+
+ if (pb->owner == world_entity)
+ {
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD)
+ return TRUE;
+ return FALSE;
+ }
+ else
+ {
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT)
+ {
+ return (strncmp(pb->owner->eclass->name, "func_group", 10));
+ }
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS)
+ {
+ return (pb->owner->eclass->nShowFlags & ECLASS_LIGHT);
+ //if (!strncmp(pb->owner->eclass->name, "light", 5))
+ // return TRUE;
+ }
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
+ {
+ return (pb->owner->eclass->nShowFlags & ECLASS_PATH);
+ //if (!strncmp(pb->owner->eclass->name, "path", 4))
+ // return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+=============================================================
+
+ PATH LINES
+
+=============================================================
+*/
+
+/*
+==================
+DrawPathLines
+
+Draws connections between entities.
+Needs to consider all entities, not just ones on screen,
+because the lines can be visible when neither end is.
+Called for both camera view and xy view.
+==================
+*/
+void DrawPathLines (void)
+{
+ int i, j, k;
+ vec3_t mid, mid1;
+ entity_t *se, *te;
+ brush_t *sb, *tb;
+ char *psz;
+ vec3_t dir, s1, s2;
+ vec_t len, f;
+ int arrows;
+ int num_entities;
+ char *ent_target[MAX_MAP_ENTITIES];
+ entity_t *ent_entity[MAX_MAP_ENTITIES];
+
+ if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
+ return;
+
+ num_entities = 0;
+ for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
+ {
+ ent_target[num_entities] = ValueForKey (te, "target");
+ if (ent_target[num_entities][0])
+ {
+ ent_entity[num_entities] = te;
+ num_entities++;
+ }
+ }
+
+ for (se = entities.next ; se != &entities ; se = se->next)
+ {
+ psz = ValueForKey(se, "targetname");
+
+ if (psz == NULL || psz[0] == '\0')
+ continue;
+
+ sb = se->brushes.onext;
+ if (sb == &se->brushes)
+ continue;
+
+ for (k=0 ; k<num_entities ; k++)
+ {
+ if (strcmp (ent_target[k], psz))
+ continue;
+
+ te = ent_entity[k];
+ tb = te->brushes.onext;
+ if (tb == &te->brushes)
+ continue;
+
+ for (i=0 ; i<3 ; i++)
+ mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
+
+ for (i=0 ; i<3 ; i++)
+ mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
+
+ VectorSubtract (mid1, mid, dir);
+ len = VectorNormalize (dir);
+ s1[0] = -dir[1]*8 + dir[0]*8;
+ s2[0] = dir[1]*8 + dir[0]*8;
+ s1[1] = dir[0]*8 + dir[1]*8;
+ s2[1] = -dir[0]*8 + dir[1]*8;
+
+ qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
+
+ qglBegin(GL_LINES);
+ qglVertex3fv(mid);
+ qglVertex3fv(mid1);
+
+ arrows = (int)(len / 256) + 1;
+
+ for (i=0 ; i<arrows ; i++)
+ {
+ f = len * (i + 0.5) / arrows;
+
+ for (j=0 ; j<3 ; j++)
+ mid1[j] = mid[j] + f*dir[j];
+ qglVertex3fv (mid1);
+ qglVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
+ qglVertex3fv (mid1);
+ qglVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
+ }
+
+ qglEnd();
+ }
+ }
+
+ return;
+}
+
+//=============================================================
+
+// can be greatly simplified but per usual i am in a hurry
+// which is not an excuse, just a fact
+void CXYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds)
+{
+
+ vec3_t vSize;
+ VectorSubtract(vMaxBounds, vMinBounds, vSize);
+
+ qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
+ g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65);
+
+ if (m_nViewType == XY)
+ {
+ qglBegin (GL_LINES);
+
+ qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
+ qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
+
+ qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
+ qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
+
+ qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
+ qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
+
+
+ qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
+
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
+
+ qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
+
+ qglEnd();
+
+ qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
+ g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
+ g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
+ g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ }
+ else
+ if (m_nViewType == XZ)
+ {
+ qglBegin (GL_LINES);
+
+ qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
+ qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
+
+ qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
+ qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
+
+ qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale);
+ qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
+
+
+ qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2]);
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
+
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
+
+ qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2]);
+ qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
+
+ qglEnd();
+
+ qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
+ g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
+ g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
+ g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ }
+ else
+ {
+ qglBegin (GL_LINES);
+
+ qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
+ qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
+
+ qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
+ qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
+
+ qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
+ qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
+
+
+ qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
+ qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
+
+ qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
+ qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
+
+ qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
+ qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
+
+ qglEnd();
+
+ qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
+ g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
+ g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
+ g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
+ qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
+
+ }
+}
+
+
+
+/*
+==============
+XY_Draw
+==============
+*/
+long g_lCount = 0;
+long g_lTotal = 0;
+extern void DrawBrushEntityName (brush_t *b);
+
+void CXYWnd::XY_Draw()
+{
+ brush_t *brush;
+ float w, h;
+ entity_t *e;
+ double start, end;
+ double start2, end2;
+ vec3_t mins, maxs;
+ int drawn, culled;
+ int i;
+
+ if (!active_brushes.next)
+ return; // not valid yet
+
+ if (m_bTiming)
+ start = Sys_DoubleTime();
+ //
+ // clear
+ //
+ m_bDirty = false;
+
+ qglViewport(0, 0, m_nWidth, m_nHeight);
+ qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0);
+
+ qglClear(GL_COLOR_BUFFER_BIT);
+
+ //
+ // set up viewpoint
+ //
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadIdentity ();
+
+ w = m_nWidth / 2 / m_fScale;
+ h = m_nHeight / 2/ m_fScale;
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ mins[0] = m_vOrigin[nDim1] - w;
+ maxs[0] = m_vOrigin[nDim1] + w;
+ mins[1] = m_vOrigin[nDim2] - h;
+ maxs[1] = m_vOrigin[nDim2] + h;
+
+
+ qglOrtho (mins[0], maxs[0], mins[1], maxs[1], -8192, 8192);
+ //glRotatef
+ //
+ // now draw the grid
+ //
+ XY_DrawGrid ();
+
+ //
+ // draw stuff
+ //
+ qglShadeModel (GL_FLAT);
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglDisable(GL_DEPTH_TEST);
+ qglDisable(GL_BLEND);
+ qglColor3f(0, 0, 0);
+
+ //glEnable (GL_LINE_SMOOTH);
+
+ drawn = culled = 0;
+
+ if (m_nViewType != XY)
+ {
+ qglPushMatrix();
+ if (m_nViewType == YZ)
+ qglRotatef (-90, 0, 1, 0); // put Z going up
+ //else
+ qglRotatef (-90, 1, 0, 0); // put Z going up
+ }
+
+ e = world_entity;
+
+ if (m_bTiming)
+ start2 = Sys_DoubleTime();
+
+ for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
+ {
+ if (brush->mins[nDim1] > maxs[0] ||
+ brush->mins[nDim2] > maxs[1] ||
+ brush->maxs[nDim1] < mins[0] ||
+ brush->maxs[nDim2] < mins[1])
+ {
+ culled++;
+ continue; // off screen
+ }
+
+ if (FilterBrush (brush))
+ continue;
+
+ drawn++;
+
+ if (brush->owner != e && brush->owner)
+ {
+
+ qglColor3fv(brush->owner->eclass->color);
+ }
+ else
+ {
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
+ }
+
+ Brush_DrawXY(brush, m_nViewType);
+ }
+
+
+ if (m_bTiming)
+ end2 = Sys_DoubleTime();
+
+
+ DrawPathLines ();
+
+ //
+ // draw pointfile
+ //
+ if ( g_qeglobals.d_pointfile_display_list)
+ qglCallList (g_qeglobals.d_pointfile_display_list);
+
+
+ if (!(m_nViewType == XY))
+ qglPopMatrix();
+
+ //
+ // draw block grid
+ //
+ if ( g_qeglobals.show_blocks)
+ XY_DrawBlockGrid ();
+
+ //
+ // now draw selected brushes
+ //
+ if (m_nViewType != XY)
+ {
+ qglPushMatrix();
+ if (m_nViewType == YZ)
+ qglRotatef (-90, 0, 1, 0); // put Z going up
+ //else
+ qglRotatef (-90, 1, 0, 0); // put Z going up
+ }
+
+
+ qglPushMatrix();
+ qglTranslatef( g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]);
+
+ if (RotateMode())
+ qglColor3f(0.8, 0.1, 0.9);
+ else
+ if (ScaleMode())
+ qglColor3f(0.1, 0.8, 0.1);
+ else
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
+
+
+ if (g_PrefsDlg.m_bNoStipple == FALSE)
+ {
+ qglEnable (GL_LINE_STIPPLE);
+ qglLineStipple (3, 0xaaaa);
+ }
+ qglLineWidth (2);
+
+ vec3_t vMinBounds;
+ vec3_t vMaxBounds;
+ vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = 9999.9f;
+ vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = -9999.9f;
+
+ int nSaveDrawn = drawn;
+ bool bFixedSize = false;
+ for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
+ {
+ drawn++;
+ Brush_DrawXY(brush, m_nViewType);
+
+ if (!bFixedSize)
+ {
+ if (brush->owner->eclass->fixedsize)
+ bFixedSize = true;
+ if (g_PrefsDlg.m_bSizePaint)
+ {
+ for (i = 0; i < 3; i ++)
+ {
+ if (brush->mins[i] < vMinBounds[i])
+ vMinBounds[i] = brush->mins[i];
+ if (brush->maxs[i] > vMaxBounds[i])
+ vMaxBounds[i] = brush->maxs[i];
+ }
+ }
+ }
+ }
+
+ if (g_PrefsDlg.m_bNoStipple == FALSE)
+ {
+ qglDisable (GL_LINE_STIPPLE);
+ }
+ qglLineWidth (1);
+
+ if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint)
+ PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
+
+
+ // edge / vertex flags
+
+ if (g_qeglobals.d_select_mode == sel_vertex)
+ {
+ qglPointSize (4);
+ qglColor3f (0,1,0);
+ qglBegin (GL_POINTS);
+ for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
+ qglVertex3fv (g_qeglobals.d_points[i]);
+ qglEnd ();
+ qglPointSize (1);
+ }
+ else if (g_qeglobals.d_select_mode == sel_edge)
+ {
+ float *v1, *v2;
+
+ qglPointSize (4);
+ qglColor3f (0,0,1);
+ qglBegin (GL_POINTS);
+ for (i=0 ; i<g_qeglobals.d_numedges ; i++)
+ {
+ v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
+ v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
+ qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
+ }
+ qglEnd ();
+ qglPointSize (1);
+ }
+
+
+ g_splineList->draw(static_cast<qboolean>(g_qeglobals.d_select_mode == sel_editpoint || g_qeglobals.d_select_mode == sel_addpoint));
+
+ qglPopMatrix();
+
+ qglTranslatef (-g_qeglobals.d_select_translate[0], -g_qeglobals.d_select_translate[1], -g_qeglobals.d_select_translate[2]);
+
+
+ if (!(m_nViewType == XY))
+ qglPopMatrix();
+
+ // area selection hack
+ if (g_qeglobals.d_select_mode == sel_area)
+ {
+ qglEnable (GL_BLEND);
+ qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ qglColor4f(0.0, 0.0, 1.0, 0.25);
+ qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]);
+ qglDisable (GL_BLEND);
+ }
+
+
+ //
+ // now draw camera point
+ //
+ DrawCameraIcon ();
+ DrawZIcon ();
+
+ if (RotateMode())
+ {
+ DrawRotateIcon();
+ }
+
+ // plugin entities
+ //++timo TODO: use an object for the 2D view
+ DrawPluginEntities( (VIEWTYPE)m_nViewType );
+
+ qglFinish();
+ //QE_CheckOpenGLForErrors();
+
+ if (m_bTiming)
+ {
+ end = Sys_DoubleTime ();
+ i = (int)(1000*(end-start));
+ int i3 = (int)(1000*(end2-start2));
+ g_lCount++;
+ g_lTotal += i;
+ int i2 = g_lTotal / g_lCount;
+ Sys_Printf ("xy: %i ab: %i avg: %i\n", i, i3, i2);
+ }
+}
+
+/*
+==============
+XY_Overlay
+==============
+*/
+void CXYWnd::XY_Overlay()
+{
+ int w, h;
+ int r[4];
+ static vec3_t lastz;
+ static vec3_t lastcamera;
+
+
+ qglViewport(0, 0, m_nWidth, m_nHeight);
+
+ //
+ // set up viewpoint
+ //
+ qglMatrixMode(GL_PROJECTION);
+ qglLoadIdentity ();
+
+ w = m_nWidth / 2 / m_fScale;
+ h = m_nHeight / 2 / m_fScale;
+
+ qglOrtho (m_vOrigin[0] - w, m_vOrigin[0] + w , m_vOrigin[1] - h, m_vOrigin[1] + h, -8000, 8000);
+ //
+ // erase the old camera and z checker positions
+ // if the entire xy hasn't been redrawn
+ //
+ if (m_bDirty)
+ {
+ qglReadBuffer (GL_BACK);
+ qglDrawBuffer (GL_FRONT);
+
+ qglRasterPos2f (lastz[0]-9, lastz[1]-9);
+ qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
+ qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
+
+ qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
+ qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
+ qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
+ }
+ m_bDirty = true;
+
+ //
+ // save off underneath where we are about to draw
+ //
+ VectorCopy (z.origin, lastz);
+ VectorCopy (g_pParentWnd->GetCamera()->Camera().origin, lastcamera);
+
+ qglReadBuffer (GL_FRONT);
+ qglDrawBuffer (GL_BACK);
+
+ qglRasterPos2f (lastz[0]-9, lastz[1]-9);
+ qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
+ qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
+
+ qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
+ qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
+ qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
+
+ //
+ // draw the new icons
+ //
+ qglDrawBuffer (GL_FRONT);
+
+ qglShadeModel (GL_FLAT);
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglDisable(GL_DEPTH_TEST);
+ qglDisable(GL_BLEND);
+ qglColor3f(0, 0, 0);
+
+ DrawCameraIcon ();
+ DrawZIcon ();
+
+ qglDrawBuffer (GL_BACK);
+ qglFinish();
+}
+
+
+vec3_t& CXYWnd::GetOrigin()
+{
+ return m_vOrigin;
+}
+
+void CXYWnd::SetOrigin(vec3_t org)
+{
+ m_vOrigin[0] = org[0];
+ m_vOrigin[1] = org[1];
+ m_vOrigin[2] = org[2];
+}
+
+void CXYWnd::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+ CRect rect;
+ GetClientRect(rect);
+ m_nWidth = rect.Width();
+ m_nHeight = rect.Height();
+}
+
+brush_t hold_brushes;
+void CXYWnd::Clip()
+{
+ if (ClipMode())
+ {
+ hold_brushes.next = &hold_brushes;
+ ProduceSplitLists();
+ //brush_t* pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
+ brush_t* pList;
+ if (g_PrefsDlg.m_bSwitchClip)
+ pList = ( (m_nViewType == XZ) ? g_bSwitch: !g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
+ else
+ pList = ( (m_nViewType == XZ) ? !g_bSwitch: g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
+
+
+ if (pList->next != pList)
+ {
+ Brush_CopyList(pList, &hold_brushes);
+ CleanList(&g_brFrontSplits);
+ CleanList(&g_brBackSplits);
+ Select_Delete();
+ Brush_CopyList(&hold_brushes, &selected_brushes);
+ if (RogueClipMode())
+ RetainClipMode(false);
+ else
+ RetainClipMode(true);
+ Sys_UpdateWindows(W_ALL);
+ }
+ }
+ else if (PathMode())
+ {
+ FinishSmartCreation();
+ if (g_pPathFunc)
+ g_pPathFunc(true, g_nPathCount);
+ g_pPathFunc = NULL;
+ g_nPathCount = 0;
+ g_bPathMode = false;
+ }
+}
+
+void CXYWnd::SplitClip()
+{
+ ProduceSplitLists();
+ if ((g_brFrontSplits.next != &g_brFrontSplits) &&
+ (g_brBackSplits.next != &g_brBackSplits))
+ {
+ Select_Delete();
+ Brush_CopyList(&g_brFrontSplits, &selected_brushes);
+ Brush_CopyList(&g_brBackSplits, &selected_brushes);
+ CleanList(&g_brFrontSplits);
+ CleanList(&g_brBackSplits);
+ if (RogueClipMode())
+ RetainClipMode(false);
+ else
+ RetainClipMode(true);
+ }
+}
+
+void CXYWnd::FlipClip()
+{
+ g_bSwitch = !g_bSwitch;
+ Sys_UpdateWindows(XY | W_CAMERA_IFON);
+}
+
+
+// makes sure the selected brush or camera is in view
+void CXYWnd::PositionView()
+{
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ brush_t* b = selected_brushes.next;
+ if (b && b->next != b)
+ {
+ m_vOrigin[nDim1] = b->mins[nDim1];
+ m_vOrigin[nDim2] = b->mins[nDim2];
+ }
+ else
+ {
+ m_vOrigin[nDim1] = g_pParentWnd->GetCamera()->Camera().origin[nDim1];
+ m_vOrigin[nDim2] = g_pParentWnd->GetCamera()->Camera().origin[nDim2];
+ }
+}
+
+void CXYWnd::VectorCopyXY(vec3_t in, vec3_t out)
+{
+ if (m_nViewType == XY)
+ {
+ out[0] = in[0];
+ out[1] = in[1];
+ }
+ else
+ if (m_nViewType == XZ)
+ {
+ out[0] = in[0];
+ out[2] = in[2];
+ }
+ else
+ {
+ out[1] = in[1];
+ out[2] = in[2];
+ }
+}
+
+
+void CXYWnd::OnDestroy()
+{
+ QEW_StopGL( GetSafeHwnd(), s_hglrcXY, s_hdcXY );
+ CWnd::OnDestroy();
+ // delete this;
+}
+
+void CXYWnd::SetViewType(int n)
+{
+ m_nViewType = n;
+ if (g_pParentWnd->CurrentStyle() == QR_QE4)
+ {
+ CString str = "YZ Side";
+ if (m_nViewType == XY)
+ str = "XY Top";
+ else if (m_nViewType == XZ)
+ str = "XZ Front";
+ SetWindowText(str);
+ }
+};
+
+void CXYWnd::Redraw(unsigned int nBits)
+{
+ m_nUpdateBits = nBits;
+ RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
+ m_nUpdateBits = W_XY;
+}
+
+bool CXYWnd::RotateMode()
+{
+ return g_bRotateMode;
+}
+
+bool CXYWnd::ScaleMode()
+{
+ return g_bScaleMode;
+}
+
+bool CXYWnd::SetRotateMode(bool bMode)
+{
+ if (bMode && selected_brushes.next != &selected_brushes)
+ {
+ g_bRotateMode = true;
+ Select_GetTrueMid(g_vRotateOrigin);
+ g_vRotation[0] = g_vRotation[1] = g_vRotation[2] = 0.0;
+ }
+ else
+ {
+ if (bMode)
+ Sys_Printf("Need a brush selected to turn on Mouse Rotation mode\n");
+ g_bRotateMode = false;
+ }
+ RedrawWindow();
+ return g_bRotateMode;
+}
+
+void CXYWnd::SetScaleMode(bool bMode)
+{
+ g_bScaleMode = bMode;
+ RedrawWindow();
+}
+
+
+
+
+// xy - z
+// xz - y
+// yz - x
+
+void CXYWnd::OnSelectMouserotate()
+{
+ // TODO: Add your command handler code here
+
+}
+
+void CleanCopyEntities()
+{
+ entity_t* pe = g_enClipboard.next;
+ while (pe != NULL && pe != &g_enClipboard)
+ {
+ entity_t* next = pe->next;
+ epair_t* enext = NULL;
+ for (epair_t* ep = pe->epairs ; ep ; ep=enext)
+ {
+ enext = ep->next;
+ free (ep->key);
+ free (ep->value);
+ free (ep);
+ }
+ free (pe);
+ pe = next;
+ }
+ g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
+}
+
+entity_t *Entity_CopyClone (entity_t *e)
+{
+ entity_t *n;
+ epair_t *ep, *np;
+
+ n = (entity_t*)qmalloc(sizeof(*n));
+ n->brushes.onext = n->brushes.oprev = &n->brushes;
+ n->eclass = e->eclass;
+
+ // add the entity to the entity list
+ n->next = g_enClipboard.next;
+ g_enClipboard.next = n;
+ n->next->prev = n;
+ n->prev = &g_enClipboard;
+
+ for (ep = e->epairs ; ep ; ep=ep->next)
+ {
+ np = (epair_t*)qmalloc(sizeof(*np));
+ np->key = copystring(ep->key);
+ np->value = copystring(ep->value);
+ np->next = n->epairs;
+ n->epairs = np;
+ }
+ return n;
+}
+
+bool OnList(entity_t* pFind, CPtrArray* pList)
+{
+ int nSize = pList->GetSize();
+ while (nSize-- > 0)
+ {
+ entity_t* pEntity = reinterpret_cast<entity_t*>(pList->GetAt(nSize));
+ if (pEntity == pFind)
+ return true;
+ }
+ return false;
+}
+
+void CXYWnd::Copy()
+{
+#if 1
+ CWaitCursor WaitCursor;
+ g_Clipboard.SetLength(0);
+ g_PatchClipboard.SetLength(0);
+
+ Map_SaveSelected(&g_Clipboard, &g_PatchClipboard);
+ bool bClipped = false;
+ UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
+ if (nClipboard > 0)
+ {
+ if (OpenClipboard())
+ {
+ ::EmptyClipboard();
+ long lSize = g_Clipboard.GetLength();
+ HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, lSize + sizeof(long));
+ if (h != NULL)
+ {
+ unsigned char *cp = reinterpret_cast<unsigned char*>(::GlobalLock(h));
+ memcpy(cp, &lSize, sizeof(long));
+ cp += sizeof(long);
+ g_Clipboard.SeekToBegin();
+ g_Clipboard.Read(cp, lSize);
+ ::GlobalUnlock(h);
+ ::SetClipboardData(nClipboard, h);
+ ::CloseClipboard();
+ bClipped = true;
+ }
+ }
+ }
+
+ if (!bClipped)
+ {
+ Sys_Printf("Unable to register Windows clipboard formats, copy/paste between editors will not be possible");
+ }
+
+/*
+ CString strOut;
+ ::GetTempPath(1024, strOut.GetBuffer(1024));
+ strOut.ReleaseBuffer();
+ AddSlash(strOut);
+ strOut += "RadiantClipboard.$$$";
+ Map_SaveSelected(strOut.GetBuffer(0));
+*/
+
+#else
+ CPtrArray holdArray;
+ CleanList(&g_brClipboard);
+ CleanCopyEntities();
+ for (brush_t* pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
+ {
+ if (pBrush->owner == world_entity)
+ {
+ brush_t* pClone = Brush_Clone(pBrush);
+ pClone->owner = NULL;
+ Brush_AddToList (pClone, &g_brClipboard);
+ }
+ else
+ {
+ if (!OnList(pBrush->owner, &holdArray))
+ {
+ entity_t* e = pBrush->owner;
+ holdArray.Add(reinterpret_cast<void*>(e));
+ entity_t* pEClone = Entity_CopyClone(e);
+ for (brush_t* pEB = e->brushes.onext ; pEB != &e->brushes ; pEB=pEB->onext)
+ {
+ brush_t* pClone = Brush_Clone(pEB);
+ //Brush_AddToList (pClone, &g_brClipboard);
+ Entity_LinkBrush(pEClone, pClone);
+ Brush_Build(pClone);
+ }
+ }
+ }
+ }
+#endif
+}
+
+void CXYWnd::Undo()
+{
+/*
+ if (g_brUndo.next != &g_brUndo)
+ {
+ g_bScreenUpdates = false;
+ Select_Delete();
+ for (brush_t* pBrush = g_brUndo.next ; pBrush != NULL && pBrush != &g_brUndo ; pBrush=pBrush->next)
+ {
+ brush_t* pClone = Brush_Clone(pBrush);
+ Brush_AddToList (pClone, &active_brushes);
+ Entity_LinkBrush (pBrush->pUndoOwner, pClone);
+ Brush_Build(pClone);
+ Select_Brush(pClone);
+ }
+ CleanList(&g_brUndo);
+ g_bScreenUpdates = true;
+ Sys_UpdateWindows(W_ALL);
+ }
+ else Sys_Printf("Nothing to undo.../n");
+*/
+}
+
+void CXYWnd::UndoClear()
+{
+/*
+ CleanList(&g_brUndo);
+*/
+}
+
+void CXYWnd::UndoCopy()
+{
+/*
+ CleanList(&g_brUndo);
+ for (brush_t* pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
+ {
+ brush_t* pClone = Brush_Clone(pBrush);
+ pClone->pUndoOwner = pBrush->owner;
+ Brush_AddToList (pClone, &g_brUndo);
+ }
+*/
+}
+
+bool CXYWnd::UndoAvailable()
+{
+ return (g_brUndo.next != &g_brUndo);
+}
+
+
+
+void CXYWnd::Paste()
+{
+#if 1
+
+ CWaitCursor WaitCursor;
+ bool bPasted = false;
+ UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
+ if (nClipboard > 0 && OpenClipboard() && ::IsClipboardFormatAvailable(nClipboard))
+ {
+ HANDLE h = ::GetClipboardData(nClipboard);
+ if (h)
+ {
+ g_Clipboard.SetLength(0);
+ unsigned char *cp = reinterpret_cast<unsigned char*>(::GlobalLock(h));
+ long lSize = 0;
+ memcpy(&lSize, cp, sizeof(long));
+ cp += sizeof(long);
+ g_Clipboard.Write(cp, lSize);
+ }
+ ::GlobalUnlock(h);
+ ::CloseClipboard();
+ }
+
+ if (g_Clipboard.GetLength() > 0)
+ {
+ g_Clipboard.SeekToBegin();
+ int nLen = g_Clipboard.GetLength();
+ char* pBuffer = new char[nLen+1];
+ memset( pBuffer, 0, sizeof(pBuffer) );
+ g_Clipboard.Read(pBuffer, nLen);
+ pBuffer[nLen] = '\0';
+ Map_ImportBuffer(pBuffer);
+ delete []pBuffer;
+ }
+
+#if 0
+ if (g_PatchClipboard.GetLength() > 0)
+ {
+ g_PatchClipboard.SeekToBegin();
+ int nLen = g_PatchClipboard.GetLength();
+ char* pBuffer = new char[nLen+1];
+ g_PatchClipboard.Read(pBuffer, nLen);
+ pBuffer[nLen] = '\0';
+ Patch_ReadBuffer(pBuffer, true);
+ delete []pBuffer;
+ }
+#endif
+
+#else
+ if (g_brClipboard.next != &g_brClipboard || g_enClipboard.next != &g_enClipboard)
+ {
+ Select_Deselect();
+
+ for (brush_t* pBrush = g_brClipboard.next ; pBrush != NULL && pBrush != &g_brClipboard ; pBrush=pBrush->next)
+ {
+ brush_t* pClone = Brush_Clone(pBrush);
+ //pClone->owner = pBrush->owner;
+ if (pClone->owner == NULL)
+ Entity_LinkBrush (world_entity, pClone);
+
+ Brush_AddToList (pClone, &selected_brushes);
+ Brush_Build(pClone);
+ }
+
+ for (entity_t* pEntity = g_enClipboard.next; pEntity != NULL && pEntity != &g_enClipboard; pEntity = pEntity->next)
+ {
+ entity_t* pEClone = Entity_Clone(pEntity);
+ for (brush_t* pEB = pEntity->brushes.onext ; pEB != &pEntity->brushes ; pEB=pEB->onext)
+ {
+ brush_t* pClone = Brush_Clone(pEB);
+ Brush_AddToList (pClone, &selected_brushes);
+ Entity_LinkBrush(pEClone, pClone);
+ Brush_Build(pClone);
+ if (pClone->owner && pClone->owner != world_entity)
+ {
+ UpdateEntitySel(pClone->owner->eclass);
+ }
+ }
+ }
+
+ Sys_UpdateWindows(W_ALL);
+ }
+ else Sys_Printf("Nothing to paste.../n");
+#endif
+}
+
+
+vec3_t& CXYWnd::Rotation()
+{
+ return g_vRotation;
+}
+
+vec3_t& CXYWnd::RotateOrigin()
+{
+ return g_vRotateOrigin;
+}
+
+
+void CXYWnd::OnTimer(UINT nIDEvent)
+{
+ int nDim1 = (m_nViewType == YZ) ? 1 : 0;
+ int nDim2 = (m_nViewType == XY) ? 1 : 2;
+ m_vOrigin[nDim1] += m_ptDragAdj.x / m_fScale;
+ m_vOrigin[nDim2] -= m_ptDragAdj.y / m_fScale;
+ Sys_UpdateWindows(W_XY | W_CAMERA);
+ //int nH = (m_ptDrag.y == 0) ? -1 : m_ptDrag.y;
+ m_ptDrag += m_ptDragAdj;
+ m_ptDragTotal += m_ptDragAdj;
+ XY_MouseMoved (m_ptDrag.x, m_nHeight - 1 - m_ptDrag.y , m_nScrollFlags);
+ //m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale;
+ //m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale;
+}
+
+void CXYWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
+ //CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
+}
+
+void CXYWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
+{
+ CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
+}
+
+void CXYWnd::OnKillFocus(CWnd* pNewWnd)
+{
+ CWnd::OnKillFocus(pNewWnd);
+ SendMessage(WM_NCACTIVATE, FALSE , 0 );
+}
+
+void CXYWnd::OnSetFocus(CWnd* pOldWnd)
+{
+ CWnd::OnSetFocus(pOldWnd);
+ SendMessage(WM_NCACTIVATE, TRUE , 0 );
+}
+
+void CXYWnd::OnClose()
+{
+ CWnd::OnClose();
+}
+
+// should be static as should be the rotate scale stuff
+bool CXYWnd::AreaSelectOK()
+{
+ return RotateMode() ? false : ScaleMode() ? false : true;
+} \ No newline at end of file
diff --git a/q3radiant/XYWnd.h b/q3radiant/XYWnd.h
new file mode 100755
index 0000000..8806fe8
--- /dev/null
+++ b/q3radiant/XYWnd.h
@@ -0,0 +1,219 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_XYWND_H__44B4BA04_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
+#define AFX_XYWND_H__44B4BA04_781B_11D1_B53C_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// XYWnd.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CXYWnd window
+
+#include "qe3.h"
+#include "CamWnd.h"
+
+const int SCALE_X = 0x01;
+const int SCALE_Y = 0x02;
+const int SCALE_Z = 0x04;
+
+
+typedef void (PFNPathCallback)(bool, int);
+// as i didn't really encapsulate anything this
+// should really be a struct..
+class CClipPoint
+{
+public:
+ CClipPoint(){ Reset(); };
+ void Reset(){ m_ptClip[0] = m_ptClip[1] = m_ptClip[2] = 0.0; m_bSet = false; m_pVec3 = NULL;};
+ bool Set(){ return m_bSet; };
+ void Set(bool b) { m_bSet = b; };
+ void UpdatePointPtr() { if (m_pVec3) VectorCopy(m_ptClip, *m_pVec3); };
+ void SetPointPtr(vec3_t* p) { m_pVec3 = p; };
+ vec3_t m_ptClip; // the 3d point
+ vec3_t* m_pVec3; // optional ptr for 3rd party updates
+ CPoint m_ptScreen; // the onscreen xy point (for mousability)
+ bool m_bSet;
+ operator vec3_t&() {return m_ptClip;};
+ operator vec3_t*() {return &m_ptClip;};
+};
+
+class CXYWnd : public CWnd
+{
+ DECLARE_DYNCREATE(CXYWnd);
+// Construction
+public:
+ CXYWnd();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CXYWnd)
+ protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ bool AreaSelectOK();
+ vec3_t& RotateOrigin();
+ vec3_t& Rotation();
+ void UndoClear();
+ bool UndoAvailable();
+ void KillPathMode();
+ void Undo();
+ void UndoCopy();
+ void Copy();
+ void Paste();
+ void Redraw(unsigned int nBits);
+ void VectorCopyXY(vec3_t in, vec3_t out);
+ void PositionView();
+ void FlipClip();
+ void SplitClip();
+ void Clip();
+ vec3_t& GetOrigin();
+ void SetOrigin(vec3_t org); // PGM
+ void XY_Init();
+ void XY_Overlay();
+ void XY_Draw();
+ void DrawZIcon();
+ void DrawRotateIcon();
+ void DrawCameraIcon();
+ void XY_DrawBlockGrid();
+ void XY_DrawGrid();
+ void XY_MouseMoved (int x, int y, int buttons);
+ void NewBrushDrag (int x, int y);
+ qboolean DragDelta (int x, int y, vec3_t move);
+ void XY_MouseUp(int x, int y, int buttons);
+ void XY_MouseDown (int x, int y, int buttons);
+ void XY_ToGridPoint (int x, int y, vec3_t point);
+ void XY_ToPoint (int x, int y, vec3_t point);
+ void SnapToPoint (int x, int y, vec3_t point);
+ void SetActive(bool b) {m_bActive = b;};
+ bool Active() {return m_bActive;};
+ void DropClipPoint(UINT nFlags, CPoint point);
+
+ bool RogueClipMode();
+ bool ClipMode();
+ void SetClipMode(bool bMode);
+ void RetainClipMode(bool bMode);
+
+ bool RotateMode();
+ bool SetRotateMode(bool bMode);
+ bool ScaleMode();
+ void SetScaleMode(bool bMode);
+
+ bool PathMode();
+ void DropPathPoint(UINT nFlags, CPoint point);
+
+ bool PointMode();
+ void AddPointPoint(UINT nFlags, vec3_t* pVec);
+ void SetPointMode(bool b);
+
+
+ virtual ~CXYWnd();
+ void SetViewType(int n);
+ int GetViewType() {return m_nViewType; };
+ void SetScale(float f) {m_fScale = f;};
+ float Scale() {return m_fScale;};
+ int Width() {return m_nWidth;}
+ int Height() {return m_nHeight;}
+ bool m_bActive;
+
+ // Generated message map functions
+protected:
+ int m_nUpdateBits;
+ int m_nWidth;
+ int m_nHeight;
+ bool m_bTiming;
+ float m_fScale;
+ float m_TopClip;
+ float m_BottomClip;
+ bool m_bDirty;
+ vec3_t m_vOrigin;
+ CPoint m_ptCursor;
+ bool m_bRButtonDown;
+
+ int m_nButtonstate;
+ int m_nPressx;
+ int m_nPressy;
+ vec3_t m_vPressdelta;
+ bool m_bPress_selection;
+
+ friend CCamWnd;
+ //friend C3DFXCamWnd;
+
+ CMenu m_mnuDrop;
+ int m_nViewType;
+
+ unsigned int m_nTimerID;
+ int m_nScrollFlags;
+ CPoint m_ptDrag;
+ CPoint m_ptDragAdj;
+ CPoint m_ptDragTotal;
+
+ void OriginalButtonUp(UINT nFlags, CPoint point);
+ void OriginalButtonDown(UINT nFlags, CPoint point);
+ void ProduceSplits(brush_t** pFront, brush_t** pBack);
+ void ProduceSplitLists();
+ void HandleDrop();
+ void PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds);
+
+ void OnEntityCreate(unsigned int nID);
+ CPoint m_ptDown;
+ //{{AFX_MSG(CXYWnd)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnMButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg void OnPaint();
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnDestroy();
+ afx_msg void OnSelectMouserotate();
+ afx_msg void OnTimer(UINT nIDEvent);
+ afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);
+ afx_msg void OnKillFocus(CWnd* pNewWnd);
+ afx_msg void OnSetFocus(CWnd* pOldWnd);
+ afx_msg void OnClose();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_XYWND_H__44B4BA04_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/Z.CPP b/q3radiant/Z.CPP
new file mode 100755
index 0000000..8a454b1
--- /dev/null
+++ b/q3radiant/Z.CPP
@@ -0,0 +1,431 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "stdafx.h"
+#include "qe3.h"
+
+#define PAGEFLIPS 2
+
+z_t z;
+
+/*
+============
+Z_Init
+============
+*/
+void Z_Init (void)
+{
+ z.origin[0] = 0;
+ z.origin[1] = 20;
+ z.origin[2] = 46;
+
+ z.scale = 1;
+}
+
+
+
+/*
+============================================================================
+
+ MOUSE ACTIONS
+
+============================================================================
+*/
+
+static int cursorx, cursory;
+
+/*
+==============
+Z_MouseDown
+==============
+*/
+void Z_MouseDown (int x, int y, int buttons)
+{
+ vec3_t org, dir, vup, vright;
+ brush_t *b;
+
+ Sys_GetCursorPos (&cursorx, &cursory);
+
+ vup[0] = 0; vup[1] = 0; vup[2] = 1/z.scale;
+
+ VectorCopy (z.origin, org);
+ org[2] += (y - (z.height/2))/z.scale;
+ org[1] = -8192;
+
+ b = selected_brushes.next;
+ if (b != &selected_brushes)
+ {
+ org[0] = (b->mins[0] + b->maxs[0])/2;
+ }
+
+ dir[0] = 0; dir[1] = 1; dir[2] = 0;
+
+ vright[0] = 0; vright[1] = 0; vright[2] = 0;
+
+ // LBUTTON = manipulate selection
+ // shift-LBUTTON = select
+ // middle button = grab texture
+ // ctrl-middle button = set entire brush to texture
+ // ctrl-shift-middle button = set single face to texture
+
+ int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+ if ( (buttons == MK_LBUTTON)
+ || (buttons == (MK_LBUTTON | MK_SHIFT))
+ || (buttons == MK_MBUTTON)
+// || (buttons == (MK_MBUTTON|MK_CONTROL))
+ || (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL)) )
+ {
+ Drag_Begin (x, y, buttons,
+ vright, vup,
+ org, dir);
+ return;
+ }
+
+ // control mbutton = move camera
+ if ((buttons == (MK_CONTROL|nMouseButton) ) || (buttons == (MK_CONTROL|MK_LBUTTON)))
+ {
+ g_pParentWnd->GetCamera()->Camera().origin[2] = org[2] ;
+ Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z);
+ }
+
+
+}
+
+/*
+==============
+Z_MouseUp
+==============
+*/
+void Z_MouseUp (int x, int y, int buttons)
+{
+ Drag_MouseUp ();
+}
+
+/*
+==============
+Z_MouseMoved
+==============
+*/
+void Z_MouseMoved (int x, int y, int buttons)
+{
+ if (!buttons)
+ return;
+ if (buttons == MK_LBUTTON)
+ {
+ Drag_MouseMoved (x, y, buttons);
+ Sys_UpdateWindows (W_Z|W_CAMERA_IFON|W_XY);
+ return;
+ }
+ // rbutton = drag z origin
+ if (buttons == MK_RBUTTON)
+ {
+ Sys_GetCursorPos (&x, &y);
+ if ( y != cursory)
+ {
+ z.origin[2] += y-cursory;
+ Sys_SetCursorPos (cursorx, cursory);
+ Sys_UpdateWindows (W_Z);
+ }
+ return;
+ }
+ // control mbutton = move camera
+ int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
+ if ((buttons == (MK_CONTROL|nMouseButton) ) || (buttons == (MK_CONTROL|MK_LBUTTON)))
+ {
+ g_pParentWnd->GetCamera()->Camera().origin[2] = (y - (z.height/2))/z.scale;
+ Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY|W_Z);
+ }
+
+}
+
+
+/*
+============================================================================
+
+DRAWING
+
+============================================================================
+*/
+
+
+/*
+==============
+Z_DrawGrid
+==============
+*/
+void Z_DrawGrid (void)
+{
+ float zz, zb, ze;
+ int w, h;
+ char text[32];
+
+ w = z.width/2 / z.scale;
+ h = z.height/2 / z.scale;
+
+ zb = z.origin[2] - h;
+ if (zb < region_mins[2])
+ zb = region_mins[2];
+ zb = 64 * floor (zb/64);
+
+ ze = z.origin[2] + h;
+ if (ze > region_maxs[2])
+ ze = region_maxs[2];
+ ze = 64 * ceil (ze/64);
+
+ // draw major blocks
+
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]);
+
+ qglBegin (GL_LINES);
+
+ qglVertex2f (0, zb);
+ qglVertex2f (0, ze);
+
+ for (zz=zb ; zz<ze ; zz+=64)
+ {
+ qglVertex2f (-w, zz);
+ qglVertex2f (w, zz);
+ }
+
+ qglEnd ();
+
+ // draw minor blocks
+ if (g_qeglobals.d_showgrid && g_qeglobals.d_gridsize*z.scale >= 4 &&
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR] != g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK])
+ {
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
+
+ qglBegin (GL_LINES);
+ for (zz=zb ; zz<ze ; zz+=g_qeglobals.d_gridsize)
+ {
+ if ( ! ((int)zz & 63) )
+ continue;
+ qglVertex2f (-w, zz);
+ qglVertex2f (w, zz);
+ }
+ qglEnd ();
+ }
+
+ // draw coordinate text if needed
+
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]);
+
+ for (zz=zb ; zz<ze ; zz+=64)
+ {
+ qglRasterPos2f (-w+1, zz);
+ sprintf (text, "%i",(int)zz);
+ qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text);
+ }
+}
+
+#define CAM_HEIGHT 48 // height of main part
+#define CAM_GIZMO 8 // height of the gizmo
+
+void ZDrawCameraIcon (void)
+{
+ float x, y;
+ int xCam = z.width/4;
+
+ x = 0;
+ y = g_pParentWnd->GetCamera()->Camera().origin[2];
+
+ qglColor3f (0.0, 0.0, 1.0);
+ qglBegin(GL_LINE_STRIP);
+ qglVertex3f (x-xCam,y,0);
+ qglVertex3f (x,y+CAM_GIZMO,0);
+ qglVertex3f (x+xCam,y,0);
+ qglVertex3f (x,y-CAM_GIZMO,0);
+ qglVertex3f (x-xCam,y,0);
+ qglVertex3f (x+xCam,y,0);
+ qglVertex3f (x+xCam,y-CAM_HEIGHT,0);
+ qglVertex3f (x-xCam,y-CAM_HEIGHT,0);
+ qglVertex3f (x-xCam,y,0);
+ qglEnd ();
+
+}
+
+GLbitfield glbitClear = GL_COLOR_BUFFER_BIT; //HACK
+
+/*
+==============
+Z_Draw
+==============
+*/
+void Z_Draw (void)
+{
+ brush_t *brush;
+ float w, h;
+ double start, end;
+ qtexture_t *q;
+ float top, bottom;
+ vec3_t org_top, org_bottom, dir_up, dir_down;
+ int xCam = z.width/3;
+
+ if (!active_brushes.next)
+ return; // not valid yet
+
+ if (z.timing)
+ start = Sys_DoubleTime ();
+
+ //
+ // clear
+ //
+ qglViewport(0, 0, z.width, z.height);
+
+ qglClearColor (
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
+ g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],
+ 0);
+
+ /* GL Bug */
+ /* When not using hw acceleration, gl will fault if we clear the depth
+ buffer bit on the first pass. The hack fix is to set the GL_DEPTH_BUFFER_BIT
+ only after Z_Draw() has been called once. Yeah, right. */
+ qglClear(glbitClear);
+ glbitClear |= GL_DEPTH_BUFFER_BIT;
+
+ qglMatrixMode(GL_PROJECTION);
+
+ qglLoadIdentity ();
+ w = z.width/2 / z.scale;
+ h = z.height/2 / z.scale;
+ qglOrtho (-w, w, z.origin[2]-h, z.origin[2]+h, -8, 8);
+
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_TEXTURE_1D);
+ qglDisable(GL_DEPTH_TEST);
+ qglDisable(GL_BLEND);
+
+
+ //
+ // now draw the grid
+ //
+ Z_DrawGrid ();
+
+ //
+ // draw stuff
+ //
+
+ qglDisable(GL_CULL_FACE);
+
+ qglShadeModel (GL_FLAT);
+
+ qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+
+ qglDisable(GL_TEXTURE_2D);
+ qglDisable(GL_BLEND);
+ qglDisable(GL_DEPTH_TEST);
+
+
+ // draw filled interiors and edges
+ dir_up[0] = 0 ; dir_up[1] = 0; dir_up[2] = 1;
+ dir_down[0] = 0 ; dir_down[1] = 0; dir_down[2] = -1;
+ VectorCopy (z.origin, org_top);
+ org_top[2] = 4096;
+ VectorCopy (z.origin, org_bottom);
+ org_bottom[2] = -4096;
+
+ for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
+ {
+ if (brush->mins[0] >= z.origin[0]
+ || brush->maxs[0] <= z.origin[0]
+ || brush->mins[1] >= z.origin[1]
+ || brush->maxs[1] <= z.origin[1])
+ continue;
+
+ if (!Brush_Ray (org_top, dir_down, brush, &top))
+ continue;
+ top = org_top[2] - top;
+ if (!Brush_Ray (org_bottom, dir_up, brush, &bottom))
+ continue;
+ bottom = org_bottom[2] + bottom;
+
+ q = Texture_ForName (brush->brush_faces->texdef.name);
+ qglColor3f (q->color[0], q->color[1], q->color[2]);
+ qglBegin (GL_QUADS);
+ qglVertex2f (-xCam, bottom);
+ qglVertex2f (xCam, bottom);
+ qglVertex2f (xCam, top);
+ qglVertex2f (-xCam, top);
+ qglEnd ();
+
+ qglColor3f (1,1,1);
+ qglBegin (GL_LINE_LOOP);
+ qglVertex2f (-xCam, bottom);
+ qglVertex2f (xCam, bottom);
+ qglVertex2f (xCam, top);
+ qglVertex2f (-xCam, top);
+ qglEnd ();
+ }
+
+ //
+ // now draw selected brushes
+ //
+ for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
+ {
+ if ( !(brush->mins[0] >= z.origin[0]
+ || brush->maxs[0] <= z.origin[0]
+ || brush->mins[1] >= z.origin[1]
+ || brush->maxs[1] <= z.origin[1]) )
+ {
+ if (Brush_Ray (org_top, dir_down, brush, &top))
+ {
+ top = org_top[2] - top;
+ if (Brush_Ray (org_bottom, dir_up, brush, &bottom))
+ {
+ bottom = org_bottom[2] + bottom;
+
+ q = Texture_ForName (brush->brush_faces->texdef.name);
+ qglColor3f (q->color[0], q->color[1], q->color[2]);
+ qglBegin (GL_QUADS);
+ qglVertex2f (-xCam, bottom);
+ qglVertex2f (xCam, bottom);
+ qglVertex2f (xCam, top);
+ qglVertex2f (-xCam, top);
+ qglEnd ();
+ }
+ }
+ }
+
+ qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
+ qglBegin (GL_LINE_LOOP);
+ qglVertex2f (-xCam, brush->mins[2]);
+ qglVertex2f (xCam, brush->mins[2]);
+ qglVertex2f (xCam, brush->maxs[2]);
+ qglVertex2f (-xCam, brush->maxs[2]);
+ qglEnd ();
+ }
+
+
+ ZDrawCameraIcon ();
+
+ qglFinish();
+ QE_CheckOpenGLForErrors();
+
+ if (z.timing)
+ {
+ end = Sys_DoubleTime ();
+ Sys_Printf ("z: %i ms\n", (int)(1000*(end-start)));
+ }
+}
+
diff --git a/q3radiant/Z.H b/q3radiant/Z.H
new file mode 100755
index 0000000..75cbf83
--- /dev/null
+++ b/q3radiant/Z.H
@@ -0,0 +1,42 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+// window system independent camera view code
+
+typedef struct
+{
+ int width, height;
+
+ qboolean timing;
+
+ vec3_t origin; // at center of window
+ float scale;
+} z_t;
+
+extern z_t z;
+
+void Z_Init (void);
+void Z_MouseDown (int x, int y, int buttons);
+void Z_MouseUp (int x, int y, int buttons);
+void Z_MouseMoved (int x, int y, int buttons);
+void Z_Draw (void);
+
diff --git a/q3radiant/ZView.cpp b/q3radiant/ZView.cpp
new file mode 100755
index 0000000..d887345
--- /dev/null
+++ b/q3radiant/ZView.cpp
@@ -0,0 +1,163 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ZView.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ZView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CZView
+
+IMPLEMENT_DYNCREATE(CZView, CView)
+
+CZView::CZView()
+{
+}
+
+CZView::~CZView()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CZView, CView)
+ //{{AFX_MSG_MAP(CZView)
+ ON_WM_CREATE()
+ ON_WM_KEYDOWN()
+ ON_WM_SIZE()
+ ON_WM_DESTROY()
+ ON_WM_LBUTTONUP()
+ ON_WM_LBUTTONDOWN()
+ ON_WM_RBUTTONUP()
+ ON_WM_RBUTTONDOWN()
+ ON_WM_MOUSEMOVE()
+ ON_WM_GETMINMAXINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CZView drawing
+
+void CZView::OnDraw(CDC* pDC)
+{
+ CDocument* pDoc = GetDocument();
+ // TODO: add draw code here
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CZView diagnostics
+
+#ifdef _DEBUG
+void CZView::AssertValid() const
+{
+ CView::AssertValid();
+}
+
+void CZView::Dump(CDumpContext& dc) const
+{
+ CView::Dump(dc);
+}
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// CZView message handlers
+
+int CZView::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CView::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+
+ return 0;
+}
+
+void CZView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CZView::OnSize(UINT nType, int cx, int cy)
+{
+ CView::OnSize(nType, cx, cy);
+
+ // TODO: Add your message handler code here
+
+}
+
+void CZView::OnDestroy()
+{
+ CView::OnDestroy();
+
+ // TODO: Add your message handler code here
+
+}
+
+void CZView::OnLButtonUp(UINT nFlags, CPoint point)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnLButtonUp(nFlags, point);
+}
+
+void CZView::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnLButtonDown(nFlags, point);
+}
+
+void CZView::OnRButtonUp(UINT nFlags, CPoint point)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnRButtonUp(nFlags, point);
+}
+
+void CZView::OnRButtonDown(UINT nFlags, CPoint point)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnRButtonDown(nFlags, point);
+}
+
+void CZView::OnMouseMove(UINT nFlags, CPoint point)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnMouseMove(nFlags, point);
+}
+
+void CZView::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ CView::OnGetMinMaxInfo(lpMMI);
+}
diff --git a/q3radiant/ZView.h b/q3radiant/ZView.h
new file mode 100755
index 0000000..682dfcd
--- /dev/null
+++ b/q3radiant/ZView.h
@@ -0,0 +1,83 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_ZVIEW_H__5B906AE2_76E3_11D1_8A6E_0000C0B006B6__INCLUDED_)
+#define AFX_ZVIEW_H__5B906AE2_76E3_11D1_8A6E_0000C0B006B6__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// ZView.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CZView view
+
+class CZView : public CView
+{
+protected:
+ CZView(); // protected constructor used by dynamic creation
+ DECLARE_DYNCREATE(CZView)
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CZView)
+ protected:
+ virtual void OnDraw(CDC* pDC); // overridden to draw this view
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ virtual ~CZView();
+#ifdef _DEBUG
+ virtual void AssertValid() const;
+ virtual void Dump(CDumpContext& dc) const;
+#endif
+
+ // Generated message map functions
+protected:
+ //{{AFX_MSG(CZView)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnDestroy();
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ZVIEW_H__5B906AE2_76E3_11D1_8A6E_0000C0B006B6__INCLUDED_)
diff --git a/q3radiant/ZWnd.cpp b/q3radiant/ZWnd.cpp
new file mode 100755
index 0000000..9708e66
--- /dev/null
+++ b/q3radiant/ZWnd.cpp
@@ -0,0 +1,264 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// ZWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "Radiant.h"
+#include "ZWnd.h"
+#include "qe3.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CZWnd
+IMPLEMENT_DYNCREATE(CZWnd, CWnd);
+
+
+CZWnd::CZWnd()
+{
+}
+
+CZWnd::~CZWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CZWnd, CWnd)
+ //{{AFX_MSG_MAP(CZWnd)
+ ON_WM_CREATE()
+ ON_WM_DESTROY()
+ ON_WM_KEYDOWN()
+ ON_WM_LBUTTONDOWN()
+ ON_WM_MBUTTONDOWN()
+ ON_WM_RBUTTONDOWN()
+ ON_WM_PAINT()
+ ON_WM_GETMINMAXINFO()
+ ON_WM_MOUSEMOVE()
+ ON_WM_SIZE()
+ ON_WM_NCCALCSIZE()
+ ON_WM_KILLFOCUS()
+ ON_WM_SETFOCUS()
+ ON_WM_CLOSE()
+ ON_WM_LBUTTONUP()
+ ON_WM_MBUTTONUP()
+ ON_WM_RBUTTONUP()
+ ON_WM_KEYUP()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CZWnd message handlers
+
+int CZWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (CWnd::OnCreate(lpCreateStruct) == -1)
+ return -1;
+
+ g_qeglobals.d_hwndZ = GetSafeHwnd();
+
+ m_dcZ = ::GetDC(GetSafeHwnd());
+ QEW_SetupPixelFormat(m_dcZ, false);
+ if ((m_hglrcZ = qwglCreateContext(m_dcZ )) == 0)
+ Error("wglCreateContext in CZWnd::OnCreate failed");
+
+ if (!qwglShareLists(g_qeglobals.d_hglrcBase, m_hglrcZ))
+ Error( "wglShareLists in CZWnd::OnCreate failed");
+
+ if (!qwglMakeCurrent(m_dcZ, m_hglrcZ))
+ Error ("wglMakeCurrent in CZWnd::OnCreate failed");
+
+ return 0;
+}
+
+void CZWnd::OnDestroy()
+{
+ QEW_StopGL(GetSafeHwnd(), m_hglrcZ, m_dcZ);
+ CWnd::OnDestroy();
+}
+
+void CZWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
+}
+
+void CZWnd::OnLButtonDown(UINT nFlags, CPoint point)
+{
+ SetFocus();
+ SetCapture();
+ CRect rctZ;
+ GetClientRect(rctZ);
+ Z_MouseDown (point.x, rctZ.Height() - 1 - point.y , nFlags);
+}
+
+void CZWnd::OnMButtonDown(UINT nFlags, CPoint point)
+{
+ SetFocus();
+ SetCapture();
+ CRect rctZ;
+ GetClientRect(rctZ);
+ Z_MouseDown (point.x, rctZ.Height() - 1 - point.y , nFlags);
+}
+
+void CZWnd::OnRButtonDown(UINT nFlags, CPoint point)
+{
+ SetFocus();
+ SetCapture();
+ CRect rctZ;
+ GetClientRect(rctZ);
+ Z_MouseDown (point.x, rctZ.Height() - 1 - point.y , nFlags);
+}
+
+void CZWnd::OnPaint()
+{
+ CPaintDC dc(this); // device context for painting
+ //if (!wglMakeCurrent(m_dcZ, m_hglrcZ))
+ if (!qwglMakeCurrent(dc.m_hDC, m_hglrcZ))
+ {
+ Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
+ Sys_Printf("Please restart Q3Radiant if the Z view is not working\n");
+ }
+ else
+ {
+ QE_CheckOpenGLForErrors();
+ Z_Draw ();
+ //qwglSwapBuffers(m_dcZ);
+ qwglSwapBuffers(dc.m_hDC);
+ TRACE("Z Paint\n");
+ }
+}
+
+void CZWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
+{
+ lpMMI->ptMinTrackSize.x = ZWIN_WIDTH;
+}
+
+void CZWnd::OnMouseMove(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ float fz = z.origin[2] + ((rctZ.Height() - 1 - point.y) - (z.height/2)) / z.scale;
+ fz = floor(fz / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
+ CString strStatus;
+ strStatus.Format("Z:: %.1f", fz);
+ g_pParentWnd->SetStatusText(1, strStatus);
+ Z_MouseMoved (point.x, rctZ.Height() - 1 - point.y, nFlags);
+}
+
+void CZWnd::OnSize(UINT nType, int cx, int cy)
+{
+ CWnd::OnSize(nType, cx, cy);
+ CRect rctZ;
+ GetClientRect(rctZ);
+ z.width = rctZ.right;
+ z.height = rctZ.bottom;
+ if (z.width < 10)
+ z.width = 10;
+ if (z.height < 10)
+ z.height = 10;
+ Invalidate();
+}
+
+void CZWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp)
+{
+ CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
+}
+
+void CZWnd::OnKillFocus(CWnd* pNewWnd)
+{
+ CWnd::OnKillFocus(pNewWnd);
+ SendMessage(WM_NCACTIVATE, FALSE , 0 );
+}
+
+void CZWnd::OnSetFocus(CWnd* pOldWnd)
+{
+ CWnd::OnSetFocus(pOldWnd);
+ SendMessage(WM_NCACTIVATE, TRUE , 0 );
+}
+
+void CZWnd::OnClose()
+{
+ CWnd::OnClose();
+}
+
+void CZWnd::OnLButtonUp(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ Z_MouseUp (point.x, rctZ.bottom - 1 - point.y, nFlags);
+ if (! (nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+}
+
+void CZWnd::OnMButtonUp(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ Z_MouseUp (point.x, rctZ.bottom - 1 - point.y, nFlags);
+ if (! (nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+}
+
+void CZWnd::OnRButtonUp(UINT nFlags, CPoint point)
+{
+ CRect rctZ;
+ GetClientRect(rctZ);
+ Z_MouseUp (point.x, rctZ.bottom - 1 - point.y, nFlags);
+ if (! (nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+ ReleaseCapture ();
+}
+
+
+BOOL CZWnd::PreCreateWindow(CREATESTRUCT& cs)
+{
+ WNDCLASS wc;
+ HINSTANCE hInstance = AfxGetInstanceHandle();
+ if (::GetClassInfo(hInstance, Z_WINDOW_CLASS, &wc) == FALSE)
+ {
+ // Register a new class
+ memset (&wc, 0, sizeof(wc));
+ wc.style = CS_NOCLOSE | CS_OWNDC;
+ wc.lpszClassName = Z_WINDOW_CLASS;
+ wc.hCursor = LoadCursor (NULL,IDC_ARROW);
+ wc.lpfnWndProc = ::DefWindowProc;
+ if (AfxRegisterClass(&wc) == FALSE)
+ Error ("CZWnd RegisterClass: failed");
+ }
+
+ cs.lpszClass = Z_WINDOW_CLASS;
+ cs.lpszName = "Z";
+ if (cs.style != QE3_CHILDSTYLE)
+ cs.style = QE3_SPLITTER_STYLE;
+
+ return CWnd::PreCreateWindow(cs);
+}
+
+
+void CZWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+ g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
+}
diff --git a/q3radiant/ZWnd.h b/q3radiant/ZWnd.h
new file mode 100755
index 0000000..b05c6be
--- /dev/null
+++ b/q3radiant/ZWnd.h
@@ -0,0 +1,90 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_ZWND_H__44B4BA02_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
+#define AFX_ZWND_H__44B4BA02_781B_11D1_B53C_00AA00A410FC__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// ZWnd.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CZWnd window
+
+class CZWnd : public CWnd
+{
+ DECLARE_DYNCREATE(CZWnd);
+// Construction
+public:
+ CZWnd();
+
+// Attributes
+public:
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CZWnd)
+ protected:
+ virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~CZWnd();
+
+ // Generated message map functions
+protected:
+ HDC m_dcZ;
+ HGLRC m_hglrcZ;
+ //{{AFX_MSG(CZWnd)
+ afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+ afx_msg void OnDestroy();
+ afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+ afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
+ afx_msg void OnPaint();
+ afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI);
+ afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+ afx_msg void OnSize(UINT nType, int cx, int cy);
+ afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);
+ afx_msg void OnKillFocus(CWnd* pNewWnd);
+ afx_msg void OnSetFocus(CWnd* pOldWnd);
+ afx_msg void OnClose();
+ afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnMButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+ afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ZWND_H__44B4BA02_781B_11D1_B53C_00AA00A410FC__INCLUDED_)
diff --git a/q3radiant/brush_primit.cpp b/q3radiant/brush_primit.cpp
new file mode 100755
index 0000000..bdcaa96
--- /dev/null
+++ b/q3radiant/brush_primit.cpp
@@ -0,0 +1,461 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+
+// compute a determinant using Sarrus rule
+//++timo "inline" this with a macro
+// NOTE : the three vec3_t are understood as columns of the matrix
+vec_t SarrusDet(vec3_t a, vec3_t b, vec3_t c)
+{
+ return a[0]*b[1]*c[2]+b[0]*c[1]*a[2]+c[0]*a[1]*b[2]
+ -c[0]*b[1]*a[2]-a[1]*b[0]*c[2]-a[0]*b[2]*c[1];
+}
+
+//++timo replace everywhere texX by texS etc. ( ----> and in q3map !)
+// NOTE : ComputeAxisBase here and in q3map code must always BE THE SAME !
+// WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0
+// rotation by (0,RotY,RotZ) assigns X to normal
+void ComputeAxisBase(vec3_t normal,vec3_t texS,vec3_t texT )
+{
+ vec_t RotY,RotZ;
+ // do some cleaning
+ if (fabs(normal[0])<1e-6)
+ normal[0]=0.0f;
+ if (fabs(normal[1])<1e-6)
+ normal[1]=0.0f;
+ if (fabs(normal[2])<1e-6)
+ normal[2]=0.0f;
+ RotY=-atan2(normal[2],sqrt(normal[1]*normal[1]+normal[0]*normal[0]));
+ RotZ=atan2(normal[1],normal[0]);
+ // rotate (0,1,0) and (0,0,1) to compute texS and texT
+ texS[0]=-sin(RotZ);
+ texS[1]=cos(RotZ);
+ texS[2]=0;
+ // the texT vector is along -Z ( T texture coorinates axis )
+ texT[0]=-sin(RotY)*cos(RotZ);
+ texT[1]=-sin(RotY)*sin(RotZ);
+ texT[2]=-cos(RotY);
+}
+
+void FaceToBrushPrimitFace(face_t *f)
+{
+ vec3_t texX,texY;
+ vec3_t proj;
+ // ST of (0,0) (1,0) (0,1)
+ vec_t ST[3][5]; // [ point index ] [ xyz ST ]
+ //++timo not used as long as brushprimit_texdef and texdef are static
+/* f->brushprimit_texdef.contents=f->texdef.contents;
+ f->brushprimit_texdef.flags=f->texdef.flags;
+ f->brushprimit_texdef.value=f->texdef.value;
+ strcpy(f->brushprimit_texdef.name,f->texdef.name); */
+#ifdef _DEBUG
+ if ( f->plane.normal[0]==0.0f && f->plane.normal[1]==0.0f && f->plane.normal[2]==0.0f )
+ {
+ Sys_Printf("Warning : f->plane.normal is (0,0,0) in FaceToBrushPrimitFace\n");
+ }
+ // check d_texture
+ if (!f->d_texture)
+ {
+ Sys_Printf("Warning : f.d_texture is NULL in FaceToBrushPrimitFace\n");
+ return;
+ }
+#endif
+ // compute axis base
+ ComputeAxisBase(f->plane.normal,texX,texY);
+ // compute projection vector
+ VectorCopy(f->plane.normal,proj);
+ VectorScale(proj,f->plane.dist,proj);
+ // (0,0) in plane axis base is (0,0,0) in world coordinates + projection on the affine plane
+ // (1,0) in plane axis base is texX in world coordinates + projection on the affine plane
+ // (0,1) in plane axis base is texY in world coordinates + projection on the affine plane
+ // use old texture code to compute the ST coords of these points
+ VectorCopy(proj,ST[0]);
+ EmitTextureCoordinates(ST[0], f->d_texture, f);
+ VectorCopy(texX,ST[1]);
+ VectorAdd(ST[1],proj,ST[1]);
+ EmitTextureCoordinates(ST[1], f->d_texture, f);
+ VectorCopy(texY,ST[2]);
+ VectorAdd(ST[2],proj,ST[2]);
+ EmitTextureCoordinates(ST[2], f->d_texture, f);
+ // compute texture matrix
+ f->brushprimit_texdef.coords[0][2]=ST[0][3];
+ f->brushprimit_texdef.coords[1][2]=ST[0][4];
+ f->brushprimit_texdef.coords[0][0]=ST[1][3]-f->brushprimit_texdef.coords[0][2];
+ f->brushprimit_texdef.coords[1][0]=ST[1][4]-f->brushprimit_texdef.coords[1][2];
+ f->brushprimit_texdef.coords[0][1]=ST[2][3]-f->brushprimit_texdef.coords[0][2];
+ f->brushprimit_texdef.coords[1][1]=ST[2][4]-f->brushprimit_texdef.coords[1][2];
+}
+
+// compute texture coordinates for the winding points
+void EmitBrushPrimitTextureCoordinates(face_t * f, winding_t * w)
+{
+ vec3_t texX,texY;
+ vec_t x,y;
+ // compute axis base
+ ComputeAxisBase(f->plane.normal,texX,texY);
+ // in case the texcoords matrix is empty, build a default one
+ // same behaviour as if scale[0]==0 && scale[1]==0 in old code
+ if (f->brushprimit_texdef.coords[0][0]==0 && f->brushprimit_texdef.coords[1][0]==0 && f->brushprimit_texdef.coords[0][1]==0 && f->brushprimit_texdef.coords[1][1]==0)
+ {
+ f->brushprimit_texdef.coords[0][0] = 1.0f;
+ f->brushprimit_texdef.coords[1][1] = 1.0f;
+ ConvertTexMatWithQTexture( &f->brushprimit_texdef, NULL, &f->brushprimit_texdef, f->d_texture );
+ }
+ int i;
+ for (i=0 ; i<w->numpoints ; i++)
+ {
+ x=DotProduct(w->points[i],texX);
+ y=DotProduct(w->points[i],texY);
+#ifdef _DEBUG
+ if (g_qeglobals.bNeedConvert)
+ {
+ // check we compute the same ST as the traditional texture computation used before
+ vec_t S=f->brushprimit_texdef.coords[0][0]*x+f->brushprimit_texdef.coords[0][1]*y+f->brushprimit_texdef.coords[0][2];
+ vec_t T=f->brushprimit_texdef.coords[1][0]*x+f->brushprimit_texdef.coords[1][1]*y+f->brushprimit_texdef.coords[1][2];
+ if ( fabs(S-w->points[i][3])>1e-2 || fabs(T-w->points[i][4])>1e-2 )
+ {
+ if ( fabs(S-w->points[i][3])>1e-4 || fabs(T-w->points[i][4])>1e-4 )
+ Sys_Printf("Warning : precision loss in brush -> brush primitive texture computation\n");
+ else
+ Sys_Printf("Warning : brush -> brush primitive texture computation bug detected\n");
+ }
+ }
+#endif
+ w->points[i][3]=f->brushprimit_texdef.coords[0][0]*x+f->brushprimit_texdef.coords[0][1]*y+f->brushprimit_texdef.coords[0][2];
+ w->points[i][4]=f->brushprimit_texdef.coords[1][0]*x+f->brushprimit_texdef.coords[1][1]*y+f->brushprimit_texdef.coords[1][2];
+ }
+}
+
+// parse a brush in brush primitive format
+void BrushPrimit_Parse(brush_t *b)
+{
+ epair_t *ep;
+ face_t *f;
+ int i,j;
+ GetToken (true);
+ if (strcmp (token, "{"))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ do
+ {
+ if (!GetToken (true))
+ break;
+ if (!strcmp (token, "}") )
+ break;
+ // reading of b->epairs if any
+ if (strcmp (token, "(") )
+ {
+ ep = ParseEpair();
+ ep->next = b->epairs;
+ b->epairs = ep;
+ }
+ else
+ // it's a face
+ {
+ f = Face_Alloc();
+ f->next = NULL;
+ if (!b->brush_faces)
+ b->brush_faces = f;
+ else
+ {
+ face_t *scan;
+ for (scan=b->brush_faces ; scan->next ; scan=scan->next)
+ ;
+ scan->next = f;
+ }
+
+ // read the three point plane definition
+ for (i=0 ; i<3 ; i++)
+ {
+ if (i != 0)
+ GetToken (true);
+ if (strcmp (token, "(") )
+ {
+ Warning ("parsing brush");
+ return;
+ }
+ for (j=0 ; j<3 ; j++)
+ {
+ GetToken (false);
+ f->planepts[i][j] = atof(token);
+ }
+ GetToken (false);
+ if (strcmp (token, ")") )
+ {
+ Warning ("parsing brush");
+ return;
+ }
+ }
+ // texture coordinates
+ GetToken (false);
+ if (strcmp(token, "("))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ GetToken (false);
+ if (strcmp(token, "("))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ for (j=0;j<3;j++)
+ {
+ GetToken(false);
+ f->brushprimit_texdef.coords[0][j]=atof(token);
+ }
+ GetToken (false);
+ if (strcmp(token, ")"))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ GetToken (false);
+ if (strcmp(token, "("))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ for (j=0;j<3;j++)
+ {
+ GetToken(false);
+ f->brushprimit_texdef.coords[1][j]=atof(token);
+ }
+ GetToken (false);
+ if (strcmp(token, ")"))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ GetToken (false);
+ if (strcmp(token, ")"))
+ {
+ Warning ("parsing brush primitive");
+ return;
+ }
+ // read the texturedef
+ GetToken (false);
+ //strcpy(f->texdef.name, token);
+ f->texdef.SetName(token);
+ if (TokenAvailable ())
+ {
+ GetToken (false);
+ f->texdef.contents = atoi(token);
+ GetToken (false);
+ f->texdef.flags = atoi(token);
+ GetToken (false);
+ f->texdef.value = atoi(token);
+ }
+ }
+ } while (1);
+}
+
+// compute a fake shift scale rot representation from the texture matrix
+// these shift scale rot values are to be understood in the local axis base
+void TexMatToFakeTexCoords( vec_t texMat[2][3], float shift[2], float *rot, float scale[2] )
+{
+#ifdef _DEBUG
+ // check this matrix is orthogonal
+ if (fabs(texMat[0][0]*texMat[0][1]+texMat[1][0]*texMat[1][1])>ZERO_EPSILON)
+ Sys_Printf("Warning : non orthogonal texture matrix in TexMatToFakeTexCoords\n");
+#endif
+ scale[0]=sqrt(texMat[0][0]*texMat[0][0]+texMat[1][0]*texMat[1][0]);
+ scale[1]=sqrt(texMat[0][1]*texMat[0][1]+texMat[1][1]*texMat[1][1]);
+#ifdef _DEBUG
+ if (scale[0]<ZERO_EPSILON || scale[1]<ZERO_EPSILON)
+ Sys_Printf("Warning : unexpected scale==0 in TexMatToFakeTexCoords\n");
+#endif
+ // compute rotate value
+ if (fabs(texMat[0][0])<ZERO_EPSILON)
+ {
+#ifdef _DEBUG
+ // check brushprimit_texdef[1][0] is not zero
+ if (fabs(texMat[1][0])<ZERO_EPSILON)
+ Sys_Printf("Warning : unexpected texdef[1][0]==0 in TexMatToFakeTexCoords\n");
+#endif
+ // rotate is +-90
+ if (texMat[1][0]>0)
+ *rot=90.0f;
+ else
+ *rot=-90.0f;
+ }
+ else
+ *rot = RAD2DEG( atan2( texMat[1][0], texMat[0][0] ) );
+ shift[0] = -texMat[0][2];
+ shift[1] = texMat[1][2];
+}
+
+// compute back the texture matrix from fake shift scale rot
+// the matrix returned must be understood as a qtexture_t with width=2 height=2 ( the default one )
+void FakeTexCoordsToTexMat( float shift[2], float rot, float scale[2], vec_t texMat[2][3] )
+{
+ texMat[0][0] = scale[0] * cos( DEG2RAD( rot ) );
+ texMat[1][0] = scale[0] * sin( DEG2RAD( rot ) );
+ texMat[0][1] = -1.0f * scale[1] * sin( DEG2RAD( rot ) );
+ texMat[1][1] = scale[1] * cos( DEG2RAD( rot ) );
+ texMat[0][2] = -shift[0];
+ texMat[1][2] = shift[1];
+}
+
+// convert a texture matrix between two qtexture_t
+// if NULL for qtexture_t, basic 2x2 texture is assumed ( straight mapping between s/t coordinates and geometric coordinates )
+void ConvertTexMatWithQTexture( brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2 )
+{
+ float s1,s2;
+ s1 = ( qtex1 ? static_cast<float>( qtex1->width ) : 2.0f ) / ( qtex2 ? static_cast<float>( qtex2->width ) : 2.0f );
+ s2 = ( qtex1 ? static_cast<float>( qtex1->height ) : 2.0f ) / ( qtex2 ? static_cast<float>( qtex2->height ) : 2.0f );
+ texMat2->coords[0][0]=s1*texMat1->coords[0][0];
+ texMat2->coords[0][1]=s1*texMat1->coords[0][1];
+ texMat2->coords[0][2]=s1*texMat1->coords[0][2];
+ texMat2->coords[1][0]=s2*texMat1->coords[1][0];
+ texMat2->coords[1][1]=s2*texMat1->coords[1][1];
+ texMat2->coords[1][2]=s2*texMat1->coords[1][2];
+}
+
+// texture locking
+void Face_MoveTexture_BrushPrimit(face_t *f, vec3_t delta)
+{
+ vec3_t texS,texT;
+ vec_t tx,ty;
+ vec3_t M[3]; // columns of the matrix .. easier that way
+ vec_t det;
+ vec3_t D[2];
+ // compute plane axis base ( doesn't change with translation )
+ ComputeAxisBase( f->plane.normal, texS, texT );
+ // compute translation vector in plane axis base
+ tx = DotProduct( delta, texS );
+ ty = DotProduct( delta, texT );
+ // fill the data vectors
+ M[0][0]=tx; M[0][1]=1.0f+tx; M[0][2]=tx;
+ M[1][0]=ty; M[1][1]=ty; M[1][2]=1.0f+ty;
+ M[2][0]=1.0f; M[2][1]=1.0f; M[2][2]=1.0f;
+ D[0][0]=f->brushprimit_texdef.coords[0][2];
+ D[0][1]=f->brushprimit_texdef.coords[0][0]+f->brushprimit_texdef.coords[0][2];
+ D[0][2]=f->brushprimit_texdef.coords[0][1]+f->brushprimit_texdef.coords[0][2];
+ D[1][0]=f->brushprimit_texdef.coords[1][2];
+ D[1][1]=f->brushprimit_texdef.coords[1][0]+f->brushprimit_texdef.coords[1][2];
+ D[1][2]=f->brushprimit_texdef.coords[1][1]+f->brushprimit_texdef.coords[1][2];
+ // solve
+ det = SarrusDet( M[0], M[1], M[2] );
+ f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det;
+ f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det;
+ f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det;
+ f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det;
+ f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det;
+ f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det;
+}
+
+// call Face_MoveTexture_BrushPrimit after vec3_t computation
+void Select_ShiftTexture_BrushPrimit( face_t *f, int x, int y )
+{
+ vec3_t texS,texT;
+ vec3_t delta;
+ ComputeAxisBase( f->plane.normal, texS, texT );
+ VectorScale( texS, static_cast<float>(x), texS );
+ VectorScale( texT, static_cast<float>(y), texT );
+ VectorCopy( texS, delta );
+ VectorAdd( delta, texT, delta );
+ Face_MoveTexture_BrushPrimit( f, delta );
+}
+
+// texture locking
+// called before the points on the face are actually rotated
+void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, vec3_t vOrigin )
+{
+ vec3_t texS,texT; // axis base of the initial plane
+ vec3_t vRotate; // rotation vector
+ vec3_t Orig;
+ vec3_t rOrig,rvecS,rvecT; // (0,0) (1,0) (0,1) ( initial plane axis base ) after rotation ( world axis base )
+ vec3_t rNormal; // normal of the plane after rotation
+ vec3_t rtexS,rtexT; // axis base of the rotated plane
+ vec3_t lOrig,lvecS,lvecT; // [2] are not used ( but usefull for debugging )
+ vec3_t M[3];
+ vec_t det;
+ vec3_t D[2];
+ // compute plane axis base
+ ComputeAxisBase( f->plane.normal, texS, texT );
+ // compute coordinates of (0,0) (1,0) (0,1) ( initial plane axis base ) after rotation
+ // (0,0) (1,0) (0,1) ( initial plane axis base ) <-> (0,0,0) texS texT ( world axis base )
+ // rotation vector
+ VectorSet( vRotate, 0.0f, 0.0f, 0.0f );
+ vRotate[nAxis]=fDeg;
+ VectorSet( Orig, 0.0f, 0.0f, 0.0f );
+ VectorRotate( Orig, vRotate, vOrigin, rOrig );
+ VectorRotate( texS, vRotate, vOrigin, rvecS );
+ VectorRotate( texT, vRotate, vOrigin, rvecT );
+ // compute normal of plane after rotation
+ VectorRotate( f->plane.normal, vRotate, rNormal );
+ // compute rotated plane axis base
+ ComputeAxisBase( rNormal, rtexS, rtexT );
+ // compute S/T coordinates of the three points in rotated axis base ( in M matrix )
+ lOrig[0] = DotProduct( rOrig, rtexS );
+ lOrig[1] = DotProduct( rOrig, rtexT );
+ lvecS[0] = DotProduct( rvecS, rtexS );
+ lvecS[1] = DotProduct( rvecS, rtexT );
+ lvecT[0] = DotProduct( rvecT, rtexS );
+ lvecT[1] = DotProduct( rvecT, rtexT );
+ M[0][0] = lOrig[0]; M[1][0] = lOrig[1]; M[2][0] = 1.0f;
+ M[0][1] = lvecS[0]; M[1][1] = lvecS[1]; M[2][1] = 1.0f;
+ M[0][2] = lvecT[0]; M[1][2] = lvecT[1]; M[2][2] = 1.0f;
+ // fill data vector
+ D[0][0]=f->brushprimit_texdef.coords[0][2];
+ D[0][1]=f->brushprimit_texdef.coords[0][0]+f->brushprimit_texdef.coords[0][2];
+ D[0][2]=f->brushprimit_texdef.coords[0][1]+f->brushprimit_texdef.coords[0][2];
+ D[1][0]=f->brushprimit_texdef.coords[1][2];
+ D[1][1]=f->brushprimit_texdef.coords[1][0]+f->brushprimit_texdef.coords[1][2];
+ D[1][2]=f->brushprimit_texdef.coords[1][1]+f->brushprimit_texdef.coords[1][2];
+ // solve
+ det = SarrusDet( M[0], M[1], M[2] );
+ f->brushprimit_texdef.coords[0][0] = SarrusDet( D[0], M[1], M[2] ) / det;
+ f->brushprimit_texdef.coords[0][1] = SarrusDet( M[0], D[0], M[2] ) / det;
+ f->brushprimit_texdef.coords[0][2] = SarrusDet( M[0], M[1], D[0] ) / det;
+ f->brushprimit_texdef.coords[1][0] = SarrusDet( D[1], M[1], M[2] ) / det;
+ f->brushprimit_texdef.coords[1][1] = SarrusDet( M[0], D[1], M[2] ) / det;
+ f->brushprimit_texdef.coords[1][2] = SarrusDet( M[0], M[1], D[1] ) / det;
+}
+
+// best fitted 2D vector is x.X+y.Y
+void ComputeBest2DVector( vec3_t v, vec3_t X, vec3_t Y, int &x, int &y )
+{
+ double sx,sy;
+ sx = DotProduct( v, X );
+ sy = DotProduct( v, Y );
+ if ( fabs(sy) > fabs(sx) )
+ {
+ x = 0;
+ if ( sy > 0.0 )
+ y = 1;
+ else
+ y = -1;
+ }
+ else
+ {
+ y = 0;
+ if ( sx > 0.0 )
+ x = 1;
+ else
+ x = -1;
+ }
+}
diff --git a/q3radiant/cameratargetdlg.cpp b/q3radiant/cameratargetdlg.cpp
new file mode 100755
index 0000000..6a68a9d
--- /dev/null
+++ b/q3radiant/cameratargetdlg.cpp
@@ -0,0 +1,71 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// CameraTargetDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CameraTargetDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CCameraTargetDlg dialog
+
+
+CCameraTargetDlg::CCameraTargetDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CCameraTargetDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CCameraTargetDlg)
+ m_nType = 0;
+ m_strName = _T("");
+ //}}AFX_DATA_INIT
+}
+
+
+void CCameraTargetDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CCameraTargetDlg)
+ DDX_Radio(pDX, IDC_RADIO_FIXED, m_nType);
+ DDX_Text(pDX, IDC_EDIT_NAME, m_strName);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CCameraTargetDlg, CDialog)
+ //{{AFX_MSG_MAP(CCameraTargetDlg)
+ ON_COMMAND(ID_POPUP_NEWCAMERA_FIXED, OnPopupNewcameraFixed)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCameraTargetDlg message handlers
+
+void CCameraTargetDlg::OnPopupNewcameraFixed()
+{
+ // TODO: Add your command handler code here
+
+}
diff --git a/q3radiant/cameratargetdlg.h b/q3radiant/cameratargetdlg.h
new file mode 100755
index 0000000..a769f19
--- /dev/null
+++ b/q3radiant/cameratargetdlg.h
@@ -0,0 +1,68 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_CAMERATARGETDLG_H__DE6597C1_1F63_4835_8949_5D2D5F208C6B__INCLUDED_)
+#define AFX_CAMERATARGETDLG_H__DE6597C1_1F63_4835_8949_5D2D5F208C6B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// CameraTargetDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CCameraTargetDlg dialog
+
+class CCameraTargetDlg : public CDialog
+{
+// Construction
+public:
+ CCameraTargetDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CCameraTargetDlg)
+ enum { IDD = IDD_DLG_CAMERATARGET };
+ int m_nType;
+ CString m_strName;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CCameraTargetDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CCameraTargetDlg)
+ afx_msg void OnPopupNewcameraFixed();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CAMERATARGETDLG_H__DE6597C1_1F63_4835_8949_5D2D5F208C6B__INCLUDED_)
diff --git a/q3radiant/cbrushstub.cpp b/q3radiant/cbrushstub.cpp
new file mode 100755
index 0000000..e816045
--- /dev/null
+++ b/q3radiant/cbrushstub.cpp
@@ -0,0 +1,76 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "stdafx.h"
+#include "qe3.h"
+
+void Curve_Invert (void)
+{
+}
+
+void Curve_MakeCurvedBrush (qboolean negative, qboolean top, qboolean bottom,
+ qboolean s1, qboolean s2, qboolean s3, qboolean s4)
+{
+}
+
+
+void Curve_BuildPoints (brush_t *b)
+{
+}
+
+void Curve_CameraDraw (brush_t *b)
+{
+}
+
+void Curve_XYDraw (brush_t *b)
+{
+}
+
+void Curve_WriteFile (char *name)
+{
+}
+
+void Curve_StripFakePlanes( brush_t *b )
+{
+}
+
+void Curve_AddFakePlanes( brush_t *b )
+{
+}
+
+
+void Patch_BrushToMesh(){};
+void Patch_GenericMesh(int nWidth, int nHeight, int nOrientation){};
+void Patch_ReadFile (char *name){};
+void Patch_WriteFile (char *name){};
+void Patch_BuildPoints (brush_t *b){};
+void Patch_Move(int n, const vec3_t vMove){};
+void Patch_ApplyMatrix(int n, const vec3_t vOrigin, const vec3_t vMatrix[3]){};
+void Patch_EditPatch(int n){};
+void Patch_Deselect(){};
+void Patch_Delete(int n){};
+void Patch_Select(int n){};
+void Patch_Scale(int n, const vec3_t vOrigin, const vec3_t vAmt){};
+void Patch_Cleanup(){};
+bool g_bShowPatchBounds;
+bool g_bPatchWireFrame;
+
+
diff --git a/q3radiant/dlgcamera.cpp b/q3radiant/dlgcamera.cpp
new file mode 100755
index 0000000..6d6c51b
--- /dev/null
+++ b/q3radiant/dlgcamera.cpp
@@ -0,0 +1,395 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// DlgCamera.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "DlgCamera.h"
+#include "DlgEvent.h"
+#include "NameDlg.h"
+#include "splines/splines.h"
+#include "CameraTargetDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+CDlgCamera g_dlgCamera;
+
+/*
+============
+va
+
+does a varargs printf into a temp buffer, so I don't need to have
+varargs versions of all text functions.
+FIXME: make this buffer size safe someday
+============
+*/
+char *va( char *format, ... ) {
+ va_list argptr;
+ static char string[2][32000]; // in case va is called by nested functions
+ static int index = 0;
+ char *buf;
+
+ buf = string[index & 1];
+ index++;
+
+ va_start (argptr, format);
+ vsprintf (buf, format,argptr);
+ va_end (argptr);
+
+ return buf;
+}
+
+
+void showCameraInspector() {
+ if (g_dlgCamera.GetSafeHwnd() == NULL) {
+ g_dlgCamera.Create(IDD_DLG_CAMERA);
+ CRect rct;
+ LONG lSize = sizeof(rct);
+ if (LoadRegistryInfo("Radiant::CameraInspector", &rct, &lSize)) {
+ g_dlgCamera.SetWindowPos(NULL, rct.left, rct.top, 0,0, SWP_NOSIZE | SWP_SHOWWINDOW);
+ }
+ Sys_UpdateWindows(W_ALL);
+ }
+ g_dlgCamera.ShowWindow(SW_SHOW);
+ g_dlgCamera.setupFromCamera();
+}
+/////////////////////////////////////////////////////////////////////////////
+// CDlgCamera dialog
+
+
+CDlgCamera::CDlgCamera(CWnd* pParent /*=NULL*/)
+ : CDialog(CDlgCamera::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDlgCamera)
+ m_strName = _T("");
+ m_fSeconds = 0.0f;
+ m_trackCamera = TRUE;
+ m_numSegments = 0;
+ m_currentSegment = 0;
+ m_strType = _T("");
+ m_editPoints = 0;
+ //}}AFX_DATA_INIT
+}
+
+
+void CDlgCamera::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDlgCamera)
+ DDX_Control(pDX, IDC_SCROLLBAR_SEGMENT, m_wndSegments);
+ DDX_Control(pDX, IDC_LIST_EVENTS, m_wndEvents);
+ DDX_Control(pDX, IDC_COMBO_SPLINES, m_wndSplines);
+ DDX_Text(pDX, IDC_EDIT_CAM_NAME, m_strName);
+ DDX_Text(pDX, IDC_EDIT_LENGTH, m_fSeconds);
+ DDX_Check(pDX, IDC_CHECK_TRACKCAMERA, m_trackCamera);
+ DDX_Text(pDX, IDC_EDIT_TOTALSEGMENTS, m_numSegments);
+ DDX_Text(pDX, IDC_EDIT_SEGMENT, m_currentSegment);
+ DDX_Text(pDX, IDC_EDIT_TYPE, m_strType);
+ DDX_Radio(pDX, IDC_RADIO_EDITPOINTS, m_editPoints);
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDlgCamera, CDialog)
+ //{{AFX_MSG_MAP(CDlgCamera)
+ ON_BN_CLICKED(IDC_BTN_ADDEVENT, OnBtnAddevent)
+ ON_BN_CLICKED(IDC_BTN_ADDTARGET, OnBtnAddtarget)
+ ON_BN_CLICKED(IDC_BTN_DELEVENT, OnBtnDelevent)
+ ON_CBN_DBLCLK(IDC_COMBO_SPLINES, OnDblclkComboSplines)
+ ON_CBN_SELCHANGE(IDC_COMBO_SPLINES, OnSelchangeComboSplines)
+ ON_LBN_SELCHANGE(IDC_LIST_EVENTS, OnSelchangeListEvents)
+ ON_LBN_DBLCLK(IDC_LIST_EVENTS, OnDblclkListEvents)
+ ON_WM_DESTROY()
+ ON_BN_CLICKED(IDAPPLY, OnApply)
+ ON_WM_HSCROLL()
+ ON_BN_CLICKED(ID_FILE_NEW, OnFileNew)
+ ON_BN_CLICKED(ID_FILE_OPEN, OnFileOpen)
+ ON_BN_CLICKED(ID_FILE_SAVE, OnFileSave)
+ ON_BN_CLICKED(ID_TESTCAMERA, OnTestcamera)
+ ON_BN_CLICKED(IDC_BTN_DELETEPOINTS, OnBtnDeletepoints)
+ ON_BN_CLICKED(IDC_BTN_SELECTALL, OnBtnSelectall)
+ ON_BN_CLICKED(IDC_RADIO_EDITPOINTS, OnRadioEditpoints)
+ ON_BN_CLICKED(IDC_RADIO_EDITPOINTS2, OnRadioAddPoints)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDlgCamera message handlers
+
+void CDlgCamera::OnBtnAddevent()
+{
+ CDlgEvent dlg;
+ if (dlg.DoModal() == IDOK) {
+ long n = m_wndSegments.GetScrollPos() / 4 * 1000;
+ g_splineList->addEvent(static_cast<idCameraEvent::eventType>(dlg.m_event+1), dlg.m_strParm, n);
+ setupFromCamera();
+ }
+}
+
+void CDlgCamera::OnBtnAddtarget()
+{
+ CCameraTargetDlg dlg;
+ if (dlg.DoModal() == IDOK) {
+ g_splineList->addTarget(dlg.m_strName, static_cast<idCameraPosition::positionType>(dlg.m_nType));
+ setupFromCamera();
+ m_wndSplines.SetCurSel(g_splineList->numTargets());
+ OnSelchangeComboSplines();
+ OnRadioAddPoints();
+ }
+}
+
+void CDlgCamera::OnBtnDelevent()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::OnBtnDeltarget()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::OnDblclkComboSplines()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::OnSelchangeComboSplines()
+{
+ UpdateData(TRUE);
+ g_qeglobals.d_select_mode = (m_editPoints == 0) ? sel_editpoint : sel_addpoint;
+ g_qeglobals.d_numpoints = 0;
+ g_qeglobals.d_num_move_points = 0;
+ int i = m_wndSplines.GetCurSel();
+ if (i > 0) {
+ g_splineList->setActiveTarget(i-1);
+ g_qeglobals.selectObject = g_splineList->getActiveTarget(i-1);
+ g_splineList->startEdit(false);
+ } else {
+ g_splineList->startEdit(true);
+ g_qeglobals.selectObject = g_splineList->getPositionObj();
+ }
+
+ // * 4.0 to set increments in quarter seconds
+ m_wndSegments.SetScrollRange(0, g_splineList->getTotalTime() * 4.0);
+
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CDlgCamera::OnSelchangeListEvents()
+{
+ int sel = m_wndEvents.GetCurSel();
+ //g_splineList->setActiveSegment(sel >= 0 ? sel : 0);
+}
+
+void CDlgCamera::OnDblclkListEvents()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::setupFromCamera()
+{
+ if (m_wndSplines.GetSafeHwnd()) {
+ int i;
+ idStr str;
+ m_strName = g_splineList->getName();
+ m_strType = g_splineList->getPositionObj()->typeStr();
+ m_wndSplines.ResetContent();
+ m_wndSplines.AddString("Path");
+ for (i = 0; i < g_splineList->numTargets(); i++) {
+ m_wndSplines.AddString(g_splineList->getActiveTarget(i)->getName());
+ }
+ m_wndSplines.SetCurSel(0);
+ m_fSeconds = g_splineList->getBaseTime();
+ m_wndSegments.SetScrollRange(0, g_splineList->getTotalTime() * 4.0);
+
+ m_wndEvents.ResetContent();
+ for (i = 0; i < g_splineList->numEvents(); i++) {
+ str = va("%s\t%s", g_splineList->getEvent(i)->typeStr(), g_splineList->getEvent(i)->getParam());
+ m_wndEvents.AddString(str);
+ }
+ //m_currentSegment = g_splineList->getActiveSegment();
+ //m_numSegments = g_splineList->numSegments();
+ }
+ g_splineList->startEdit(true);
+ UpdateData(FALSE);
+}
+
+BOOL CDlgCamera::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ setupFromCamera();
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CDlgCamera::OnOK()
+{
+ g_dlgCamera.ShowWindow(SW_HIDE);
+ clearSelection();
+ g_splineList->stopEdit();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CDlgCamera::OnDestroy()
+{
+ if (GetSafeHwnd()) {
+ CRect rct;
+ GetWindowRect(rct);
+ SaveRegistryInfo("Radiant::CameraInspector", &rct, sizeof(rct));
+ }
+ CDialog::OnDestroy();
+ Sys_UpdateWindows(W_ALL);
+}
+
+
+void CDlgCamera::OnApply()
+{
+ UpdateData(TRUE);
+ g_splineList->setBaseTime(m_fSeconds);
+ g_splineList->setName(m_strName);
+ g_splineList->buildCamera();
+ m_wndSegments.SetScrollRange(0, g_splineList->getTotalTime() * 4.0);
+}
+
+void CDlgCamera::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
+{
+ CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
+ int max = g_splineList->getTotalTime() * 4;
+ if (max == 0) {
+ max = 1;
+ }
+ int n = pScrollBar->GetScrollPos();
+ switch (nSBCode) {
+ case SB_LINEUP : {
+ n--;
+ }
+ break;
+ case SB_LINEDOWN : {
+ n++;
+ }
+ break;
+ case SB_PAGEUP : {
+ n -= (float)max * 0.10;
+ }
+ break;
+ case SB_PAGEDOWN : {
+ n += (float)max * 0.10;
+ }
+ break;
+ case SB_THUMBPOSITION : {
+ n = nPos;
+ }
+ break;
+ case SB_THUMBTRACK : {
+ n = nPos;
+ }
+ }
+// if (n < 0) {
+// n = 0;
+// } else if (n >= g_splineList->numSegments()) {
+// if (g_splineList->numSegments() == 0) {
+// g_splineList->buildCamera();
+// }
+// n = g_splineList->numSegments() - 1;
+// }
+ pScrollBar->SetScrollPos(n);
+ if (m_trackCamera) {
+ float p = (float)n / max;
+ p *= g_splineList->getTotalTime() * 1000;
+ g_splineList->startCamera(0);
+ g_splineList->buildCamera();
+ vec3_t dir;
+ float fov;
+ g_splineList->getCameraInfo(p, g_pParentWnd->GetCamera()->Camera().origin, dir, &fov);
+ g_pParentWnd->GetCamera()->Camera().angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
+ g_pParentWnd->GetCamera()->Camera().angles[0] = asin (dir[2])*180/3.14159;
+
+ }
+ UpdateData(FALSE);
+ Sys_UpdateWindows(W_XY | W_CAMERA);
+}
+
+void CDlgCamera::OnFileNew()
+{
+ g_splineList->clear();
+ g_qeglobals.selectObject = g_splineList->getPositionObj();
+ setupFromCamera();
+ Sys_UpdateWindows(W_ALL);
+}
+
+void CDlgCamera::OnFileOpen()
+{
+ CNameDlg dlg("Open Camera File");
+ if (dlg.DoModal() == IDOK) {
+ g_splineList->clear();
+ g_qeglobals.selectObject = g_splineList->getPositionObj();
+ g_splineList->load(va("%s.camera", dlg.m_strName));
+ setupFromCamera();
+ Sys_UpdateWindows(W_ALL);
+ }
+}
+
+void CDlgCamera::OnFileSave()
+{
+ CNameDlg dlg("Save Camera File");
+ if (dlg.DoModal() == IDOK) {
+ g_splineList->save(va("%s.camera", dlg.m_strName));
+ }
+}
+
+void CDlgCamera::OnTestcamera()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::OnBtnDeletepoints()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::OnBtnSelectall()
+{
+ // TODO: Add your control notification handler code here
+
+}
+
+void CDlgCamera::OnRadioEditpoints()
+{
+ UpdateData(TRUE);
+ g_qeglobals.d_select_mode = sel_editpoint;
+}
+
+void CDlgCamera::OnRadioAddPoints()
+{
+ UpdateData(TRUE);
+ g_qeglobals.d_select_mode = sel_addpoint;
+}
diff --git a/q3radiant/dlgcamera.h b/q3radiant/dlgcamera.h
new file mode 100755
index 0000000..6c54007
--- /dev/null
+++ b/q3radiant/dlgcamera.h
@@ -0,0 +1,98 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#if !defined(AFX_DLGCAMERA_H__59C12359_E3EB_4081_9F28_01793D75CF20__INCLUDED_)
+#define AFX_DLGCAMERA_H__59C12359_E3EB_4081_9F28_01793D75CF20__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// DlgCamera.h : header file
+//
+
+extern void showCameraInspector();
+
+/////////////////////////////////////////////////////////////////////////////
+// CDlgCamera dialog
+
+class CDlgCamera : public CDialog
+{
+// Construction
+public:
+ CDlgCamera(CWnd* pParent = NULL); // standard constructor
+ void setupFromCamera();
+
+// Dialog Data
+ //{{AFX_DATA(CDlgCamera)
+ enum { IDD = IDD_DLG_CAMERA };
+ CScrollBar m_wndSegments;
+ CListBox m_wndEvents;
+ CComboBox m_wndSplines;
+ CString m_strName;
+ float m_fSeconds;
+ BOOL m_trackCamera;
+ int m_numSegments;
+ int m_currentSegment;
+ CString m_strType;
+ int m_editPoints;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDlgCamera)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CDlgCamera)
+ afx_msg void OnBtnAddevent();
+ afx_msg void OnBtnAddtarget();
+ afx_msg void OnBtnDelevent();
+ afx_msg void OnBtnDeltarget();
+ afx_msg void OnDblclkComboSplines();
+ afx_msg void OnSelchangeComboSplines();
+ afx_msg void OnSelchangeListEvents();
+ afx_msg void OnDblclkListEvents();
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ afx_msg void OnDestroy();
+ afx_msg void OnApply();
+ afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+ afx_msg void OnFileNew();
+ afx_msg void OnFileOpen();
+ afx_msg void OnFileSave();
+ afx_msg void OnTestcamera();
+ afx_msg void OnBtnDeletepoints();
+ afx_msg void OnBtnSelectall();
+ afx_msg void OnRadioEditpoints();
+ afx_msg void OnRadioAddPoints();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DLGCAMERA_H__59C12359_E3EB_4081_9F28_01793D75CF20__INCLUDED_)
diff --git a/q3radiant/igl.h b/q3radiant/igl.h
new file mode 100755
index 0000000..035cb77
--- /dev/null
+++ b/q3radiant/igl.h
@@ -0,0 +1,261 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.7.2.3 $
+// $Author: ttimo $
+// $Date: 2000/02/16 15:43:14 $
+// $Log: igl.h,v $
+// Revision 1.7.2.3 2000/02/16 15:43:14 ttimo
+// Curry bug #101996: added glTexParameterf and glNormal3f
+//
+// Revision 1.7.2.2 2000/02/13 17:48:07 ttimo
+// Curry bug #101874 - added glTexGenf to GL interface
+//
+// Revision 1.7.2.1 2000/02/04 22:59:34 ttimo
+// messaging API preview
+//
+// Revision 1.7 2000/01/18 00:43:59 ttimo
+// RC
+//
+// Revision 1.6 2000/01/13 00:46:41 ttimo
+// Merged in patches in / out
+// Revision 1.1.1.4 2000/01/18 00:17:12 ttimo
+// merging in for RC
+//
+// Revision 1.5 2000/01/11 22:14:48 ttimo
+// cleaning up after merging and thinks badly fucked up
+//
+// Revision 1.2 2000/01/09 04:39:14 ttimo
+// added some bindings to the GL table
+//
+// Revision 1.1.1.3 2000/01/11 16:43:15 ttimo
+// merged version from old reposit and Robert update
+//
+// Revision 1.1.1.1 2000/01/07 17:17:30 ttimo
+// initial import of Q3Radiant module
+//
+// Revision 1.1.1.1 2000/01/07 17:17:30 ttimo
+// initial import of Q3Radiant module
+//
+// Revision 1.3 2000/01/17 23:53:44 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:13 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:45 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:48 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.2 1999/11/03 20:38:04 Timo & Christine
+// MEAN plugin for Q3Radiant, alpha version
+//
+// Revision 1.1.2.1.2.1 1999/10/27 08:34:29 Timo & Christine
+// preview version of the texture tools plugin is ready
+// ( TexTool.dll plugin is in Q3Plugin module )
+// plugins can draw in their own window using Radiant's qgl bindings
+//
+// Revision 1.1.2.1 1999/10/08 16:28:14 Timo & Christine
+// started plugin extensions for EA features support in Q3Radiant
+// MEAN files plugin, and Surface Properties plugin
+//
+//
+// DESCRIPTION:
+// all purpose OpenGL interface for Q3Radiant plugins
+//
+
+#ifndef __IGL_H__
+#define __IGL_H__
+
+// we use this class to let plugins draw inside the Radiant windows
+class IGLWindow
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ virtual void Draw( VIEWTYPE vt ) = 0;
+};
+
+// define a GUID for this interface so plugins can access and reference it
+// {0F237620-854B-11d3-8EF3-A2DFBD53251B}
+static const GUID QERQglTable_GUID =
+{ 0xf237620, 0x854b, 0x11d3, { 0x8e, 0xf3, 0xa2, 0xdf, 0xbd, 0x53, 0x25, 0x1b } };
+
+#include <gl/gl.h>
+#include <gl/glu.h>
+
+typedef void (APIENTRY* PFN_QGLALPHAFUNC) (GLenum func, GLclampf ref);
+typedef void (APIENTRY* PFN_QGLBEGIN) (GLenum);
+typedef void (APIENTRY* PFN_QGLBINDTEXTURE) (GLenum target, GLuint texture);
+typedef void (APIENTRY* PFN_QGLBLENDFUNC) (GLenum sfactor, GLenum dfactor);
+typedef void (APIENTRY* PFN_QGLCALLLIST) (GLuint list);
+typedef void (APIENTRY* PFN_QGLCALLLISTS) (GLsizei n, GLenum type, const GLvoid *lists);
+typedef void (APIENTRY* PFN_QGLCLEAR) (GLbitfield mask);
+typedef void (APIENTRY* PFN_QGLCLEARCOLOR) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRY* PFN_QGLCLEARDEPTH) (GLclampd depth);
+typedef void (APIENTRY* PFN_QGLCOLOR3F) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRY* PFN_QGLCOLOR4F) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRY* PFN_QGLCULLFACE) (GLenum mode);
+typedef void (APIENTRY* PFN_QGLDELETELISTS) (GLuint list, GLsizei range);
+typedef void (APIENTRY* PFN_QGLDISABLE) (GLenum cap);
+typedef void (APIENTRY* PFN_QGLENABLE) (GLenum cap);
+typedef void (APIENTRY* PFN_QGLEND) ();
+typedef void (APIENTRY* PFN_QGLENDLIST) (void);
+typedef GLuint (APIENTRY* PFN_QGLGENLISTS) (GLsizei range);
+typedef void (APIENTRY* PFN_QGLLISTBASE) (GLuint base);
+typedef void (APIENTRY* PFN_QGLLOADIDENTITY) ();
+typedef void (APIENTRY* PFN_QGLMATRIXMODE) (GLenum mode);
+typedef void (APIENTRY* PFN_QGLNEWLIST) (GLuint list, GLenum mode);
+typedef void (APIENTRY* PFN_QGLNORMAL3F) (GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRY* PFN_QGLORTHO) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRY* PFN_QGLPOINTSIZE) (GLfloat size);
+typedef void (APIENTRY* PFN_QGLPOLYGONMODE) (GLenum face, GLenum mode);
+typedef void (APIENTRY* PFN_QGLPOPMATRIX) ();
+typedef void (APIENTRY* PFN_QGLPUSHMATRIX) ();
+typedef void (APIENTRY* PFN_QGLROTATED) (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY* PFN_QGLROTATEF) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLSCALEF) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLTEXCOORD2F) (GLfloat s, GLfloat t);
+typedef void (APIENTRY* PFN_QGLTEXENVF) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLTEXGENF) (GLenum coord, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLTEXPARAMETERF) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLTRANSLATED) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY* PFN_QGLTRANSLATEF) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLVERTEX2F) (GLfloat x, GLfloat y);
+typedef void (APIENTRY* PFN_QGLVERTEX3F) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLVIEWPORT) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+typedef void (WINAPI* PFN_QE_CHECKOPENGLFORERRORS) ();
+typedef int (WINAPI* PFN_QEW_SETUPPIXELFORMAT) (HDC hDC, qboolean zbuffer );
+typedef HGLRC (WINAPI* PFN_QWGL_CREATECONTEXT) (HDC);
+typedef BOOL (WINAPI* PFN_QWGL_DELETECONTEXT) (HGLRC);
+typedef BOOL (WINAPI* PFN_QWGL_MAKECURRENT) (HDC, HGLRC);
+typedef BOOL (WINAPI* PFN_QWGL_SHARELISTS) (HGLRC, HGLRC);
+typedef BOOL (WINAPI* PFN_QWGL_SWAPBUFFERS) (HDC);
+typedef BOOL (WINAPI* PFN_QWGL_USEFONTBITMAPS) (HDC, DWORD, DWORD, DWORD);
+
+// glu stuff
+typedef void (APIENTRY * PFN_QGLUPERSPECTIVE) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRY * PFN_QGLULOOKAT)(
+ GLdouble eyex,
+ GLdouble eyey,
+ GLdouble eyez,
+ GLdouble centerx,
+ GLdouble centery,
+ GLdouble centerz,
+ GLdouble upx,
+ GLdouble upy,
+ GLdouble upz);
+
+
+// specially provided by the editor for plugins
+typedef HGLRC (WINAPI* PFN_QERAPP_GETQEGLOBALSHGLRC) ();
+
+// plugins drawing inside the GL windows
+//++timo TODO: add hooking into other windows
+//+timo NOTE: this could be moved to the messaging system instead of having a dedicated interface
+typedef void (WINAPI* PFN_QERAPP_HOOKXYGLWINDOW) (IGLWindow *);
+typedef void (WINAPI* PFN_QERAPP_UNHOOKGLWINDOW) (IGLWindow *);
+
+struct _QERQglTable
+{
+ //++timo do we really wanna play with versions ?
+// float m_fVersion;
+ int m_nSize;
+ PFN_QGLALPHAFUNC m_pfn_qglAlphaFunc;
+ PFN_QGLBEGIN m_pfn_qglBegin;
+ PFN_QGLBINDTEXTURE m_pfn_qglBindTexture;
+ PFN_QGLBLENDFUNC m_pfn_qglBlendFunc;
+ PFN_QGLCALLLIST m_pfn_qglCallList;
+ PFN_QGLCLEAR m_pfn_qglClear;
+ PFN_QGLCLEARCOLOR m_pfn_qglClearColor;
+ PFN_QGLCALLLISTS m_pfn_qglCallLists;
+ PFN_QGLCLEARDEPTH m_pfn_qglClearDepth;
+ PFN_QGLCOLOR3F m_pfn_qglColor3f;
+ PFN_QGLCOLOR4F m_pfn_qglColor4f;
+ PFN_QGLCULLFACE m_pfn_qglCullFace;
+ PFN_QGLDELETELISTS m_pfn_qglDeleteLists;
+ PFN_QGLDISABLE m_pfn_qglDisable;
+ PFN_QGLENABLE m_pfn_qglEnable;
+ PFN_QGLEND m_pfn_qglEnd;
+ PFN_QGLENDLIST m_pfn_qglEndList;
+ PFN_QGLGENLISTS m_pfn_qglGenLists;
+ PFN_QGLLISTBASE m_pfn_qglListBase;
+ PFN_QGLLOADIDENTITY m_pfn_qglLoadIdentity;
+ PFN_QGLMATRIXMODE m_pfn_qglMatrixMode;
+ PFN_QGLNEWLIST m_pfn_qglNewList;
+ PFN_QGLNORMAL3F m_pfn_qglNormal3f;
+ PFN_QGLORTHO m_pfn_qglOrtho;
+ PFN_QGLPOINTSIZE m_pfn_qglPointSize;
+ PFN_QGLPOLYGONMODE m_pfn_qglPolygonMode;
+ PFN_QGLPOPMATRIX m_pfn_qglPopMatrix;
+ PFN_QGLPUSHMATRIX m_pfn_qglPushMatrix;
+ PFN_QGLROTATED m_pfn_qglRotated;
+ PFN_QGLROTATEF m_pfn_qglRotatef;
+ PFN_QGLSCALEF m_pfn_qglScalef;
+ PFN_QGLTEXCOORD2F m_pfn_qglTexCoord2f;
+ PFN_QGLTEXENVF m_pfn_qglTexEnvf;
+ PFN_QGLTEXGENF m_pfn_qglTexGenf;
+ PFN_QGLTEXPARAMETERF m_pfn_qglTexParameterf;
+ PFN_QGLTRANSLATED m_pfn_qglTranslated;
+ PFN_QGLTRANSLATEF m_pfn_qglTranslatef;
+ PFN_QGLVERTEX2F m_pfn_qglVertex2f;
+ PFN_QGLVERTEX3F m_pfn_qglVertex3f;
+ PFN_QGLVIEWPORT m_pfn_qglViewport;
+
+ PFN_QE_CHECKOPENGLFORERRORS m_pfn_QE_CheckOpenGLForErrors;
+ PFN_QEW_SETUPPIXELFORMAT m_pfn_QEW_SetupPixelFormat;
+ PFN_QWGL_CREATECONTEXT m_pfn_qwglCreateContext;
+ PFN_QWGL_DELETECONTEXT m_pfn_qwglDeleteContext;
+ PFN_QWGL_MAKECURRENT m_pfn_qwglMakeCurrent;
+ PFN_QWGL_SHARELISTS m_pfn_qwglShareLists;
+ PFN_QWGL_SWAPBUFFERS m_pfn_qwglSwapBuffers;
+ PFN_QWGL_USEFONTBITMAPS m_pfn_qwglUseFontBitmaps;
+
+ PFN_QERAPP_GETQEGLOBALSHGLRC m_pfnGetQeglobalsHGLRC;
+
+ // glu stuff
+ PFN_QGLUPERSPECTIVE m_pfn_qgluPerspective;
+ PFN_QGLULOOKAT m_pfn_qgluLookAt;
+
+ // plugin entities drawing inside Radiant windows
+ PFN_QERAPP_HOOKXYGLWINDOW m_pfnHookXYGLWindow;
+ PFN_QERAPP_UNHOOKGLWINDOW m_pfnUnHookGLWindow;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/iscriplib.h b/q3radiant/iscriplib.h
new file mode 100755
index 0000000..05b75a3
--- /dev/null
+++ b/q3radiant/iscriplib.h
@@ -0,0 +1,87 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4 $
+// $Author: ttimo $
+// $Date: 2000/01/18 00:17:12 $
+// $Log: iscriplib.h,v $
+// Revision 1.1.1.4 2000/01/18 00:17:12 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:44 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:13 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:45 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:27 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:48 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.2 1999/11/14 16:26:14 Timo & Christine
+// first beta of the ritualmap surface plugin
+//
+// Revision 1.1.2.1 1999/10/08 16:28:15 Timo & Christine
+// started plugin extensions for EA features support in Q3Radiant
+// MEAN files plugin, and Surface Properties plugin
+//
+//
+// DESCRIPTION:
+// all purpose scriplib interface for Q3Radiant plugins (cf. parse.h)
+//
+
+#ifndef __ISCRIPLIB_H_
+#define __ISCRIPLIB_H_
+
+// {4B115280-95FC-11d3-8EF3-0000E8E8657B}
+static const GUID QERScripLibTable_GUID =
+{ 0x4b115280, 0x95fc, 0x11d3, { 0x8e, 0xf3, 0x0, 0x0, 0xe8, 0xe8, 0x65, 0x7b } };
+
+typedef qboolean (WINAPI* PFN_GETTOKEN) (qboolean crossline);
+typedef void (WINAPI* PFN_UNGETTOKEN) ();
+// only used to retrieve &token
+typedef char* (WINAPI* PFN_TOKEN) ();
+
+struct _QERScripLibTable
+{
+ float m_fVersion;
+ int m_nSize;
+ PFN_GETTOKEN m_pfnGetToken;
+ PFN_UNGETTOKEN m_pfnUnGetToken;
+ PFN_TOKEN m_pfnToken;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/isurfaceplugin.h b/q3radiant/isurfaceplugin.h
new file mode 100755
index 0000000..14c55b6
--- /dev/null
+++ b/q3radiant/isurfaceplugin.h
@@ -0,0 +1,216 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//-----------------------------------------------------------------------------
+//
+// $LogFile$
+// $Revision: 1.1.1.4.2.1 $
+// $Author: ttimo $
+// $Date: 2000/02/13 17:25:04 $
+// $Log: isurfaceplugin.h,v $
+// Revision 1.1.1.4.2.1 2000/02/13 17:25:04 ttimo
+// started cleanup
+//
+// Revision 1.1.1.4 2000/01/18 00:17:13 ttimo
+// merging in for RC
+//
+// Revision 1.3 2000/01/17 23:53:44 TBesset
+// ready for merge in sourceforge (RC candidate)
+//
+// Revision 1.2 2000/01/07 16:40:13 TBesset
+// merged from BSP frontend
+//
+// Revision 1.1.1.3 1999/12/29 18:31:28 TBesset
+// Q3Radiant public version
+//
+// Revision 1.1.1.1.2.1 1999/12/29 21:39:45 TBesset
+// updated to update3 from Robert
+//
+// Revision 1.1.1.3 1999/12/29 18:31:28 TBesset
+// Q3Radiant public version
+// Revision 1.1.1.3 1999/12/29 18:31:28 TBesset
+// Q3Radiant public version
+//
+// Revision 1.2 1999/11/22 17:46:48 Timo & Christine
+// merged EARadiant into the main tree
+// bug fixes for Q3Plugin / EAPlugin
+// export for Robert
+//
+// Revision 1.1.2.4 1999/11/20 12:13:02 Timo & Christine
+// first release to Wolfen and Spog
+// with TexTool and DeQbsp3 plugin
+//
+// Revision 1.1.2.3 1999/11/16 14:23:13 Timo & Christine
+// merged 173 into Q3Radiant, EARadiant branch
+// see Timo\changelog.txt for merge log
+//
+// Revision 1.1.2.2 1999/11/14 16:26:15 Timo & Christine
+// first beta of the ritualmap surface plugin
+//
+// Revision 1.1.2.1 1999/10/08 16:28:15 Timo & Christine
+// started plugin extensions for EA features support in Q3Radiant
+// MEAN files plugin, and Surface Properties plugin
+//
+//
+// DESCRIPTION:
+//
+//
+
+#ifndef __ISURFACEPLUGIN_H_
+#define __ISURFACEPLUGIN_H_
+
+#ifndef Q3RADIANT
+
+// this is plugin included, define miptex_t
+//++timo FIXME: move definition into qertypes.h ? or assume plugin knows ?
+#define MIPLEVELS 4
+typedef struct miptex_s
+{
+ char name[32];
+ unsigned width, height;
+ unsigned offsets[MIPLEVELS]; // four mip maps stored
+ char animname[32]; // next frame in animation chain
+ int flags;
+ int contents;
+ int value;
+} miptex_t;
+
+#endif
+
+/*
+// there's a void* in each qtexture_t, must be casted to a IPluginQTexture*
+class IPluginQTexture
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ // Init for a miptex_t
+ virtual void InitForMiptex( miptex_t* ) = 0;
+ // set default texdef
+ virtual void SetDefaultTexdef() = 0;
+};
+
+// use this macro
+#define GETPLUGINQTEXTURE(pQTexture) (static_cast<IPluginQTexture *>(pQTexture->pData))
+*/
+
+// there's a void* in each qtexture_t, must be casted to a IPluginTexdef*
+// there's a void* in each face_t, must be casted to a IPluginTexdef*
+// NOTE: IPluginTexdef stores a pointer to the qtexture_t or face_t it's stored in
+// members of IPluginTexdef often access the qtexture_t or face_t they are connected to
+
+// Write texdef needs a function pointer, because Radiant either writes into a FILE or a CMemFile
+typedef void (WINAPI* PFN_QERAPP_MAPPRINTF) ( char *text, ... );
+
+class IPluginTexdef
+{
+public:
+ // Increment the number of references to this object
+ virtual void IncRef () = 0;
+ // Decrement the reference count
+ virtual void DecRef () = 0;
+ // Build a copy of this one, sets refCount to 1
+ virtual IPluginTexdef* Copy() = 0;
+ // refers to a face_t -----------------------
+ // Parse texdef
+ virtual void ParseTexdef () = 0;
+ // Write texdef
+ virtual void WriteTexdef (PFN_QERAPP_MAPPRINTF MapPrintf) = 0;
+ // hook to a face
+ virtual void Hook( face_t* ) = 0;
+ // ------------------------------------------
+ // refers to a qtexture_t -------------------
+ // Init for a miptex_t
+ //++timo NOTE: miptex_t is used only for .WAL format .. a bit outdated
+ virtual void InitForMiptex( miptex_t* ) = 0;
+ // set default texdef
+ virtual void SetDefaultTexdef() = 0;
+ // ------------------------------------------
+ // refers to a patchMesh_t ------------------
+ virtual void ParsePatchTexdef () = 0;
+ // write texdef for a patch
+ virtual void WritePatchTexdef (PFN_QERAPP_MAPPRINTF MapPrintf) = 0;
+ // hook to a patch
+ virtual void Hook( patchMesh_t* ) = 0;
+ // ------------------------------------------
+};
+
+// use this macro
+#define GETPLUGINTEXDEF(pFace) (static_cast<IPluginTexdef *>(pFace->pData))
+
+// this one is used by Radiant to access the surface plugin
+
+// {7DA59920-93D8-11d3-8EF3-0000E8E8657B}
+static const GUID QERPlugSurfaceTable_GUID =
+{ 0x7da59920, 0x93d8, 0x11d3, { 0x8e, 0xf3, 0x0, 0x0, 0xe8, 0xe8, 0x65, 0x7b } };
+
+typedef void (WINAPI* PFN_QERPLUG_DOSURFACE) ();
+typedef bool (WINAPI* PFN_QERPLUG_BYEBYESURFACEDIALOG) ();
+typedef void (WINAPI* PFN_QERPLUG_UPDATESURFACEDIALOG) ();
+// allocates a new IPluginTexdef, linked to a face_t, refCount is set to 1
+typedef IPluginTexdef* (WINAPI* PFN_QERPLUG_TEXDEFALLOC) ( face_t* );
+// allocates a new IPluginTexdef, linked to a qtexture_t, refCount is set to 1
+typedef IPluginTexdef* (WINAPI* PFN_QERPLUG_QTEXTUREALLOC) ( qtexture_t* );
+// allocates a new IPluginTexdef, linked to a patchMesh_t, refCount is set to 1
+typedef IPluginTexdef* (WINAPI* PFN_QERPLUG_PATCHALLOC) ( patchMesh_t* );
+
+struct _QERPlugSurfaceTable
+{
+ int m_nSize;
+ PFN_QERPLUG_BYEBYESURFACEDIALOG m_pfnByeByeSurfaceDialog;
+ PFN_QERPLUG_DOSURFACE m_pfnDoSurface;
+ PFN_QERPLUG_UPDATESURFACEDIALOG m_pfnUpdateSurfaceDialog;
+ PFN_QERPLUG_TEXDEFALLOC m_pfnTexdefAlloc;
+ PFN_QERPLUG_QTEXTUREALLOC m_pfnQTextureAlloc;
+ PFN_QERPLUG_PATCHALLOC m_pfnPatchAlloc;
+};
+
+// this one is used by the plugin to access some Radiant stuff
+
+// {42BAE4C0-9787-11d3-8EF3-0000E8E8657B}
+static const GUID QERAppSurfaceTable_GUID =
+{ 0x42bae4c0, 0x9787, 0x11d3, { 0x8e, 0xf3, 0x0, 0x0, 0xe8, 0xe8, 0x65, 0x7b } };
+
+typedef bool (WINAPI* PFN_PATCHESSELECTED) ();
+// retrieve g_qeglobals.texturewin_t
+//++timo FIXME: this should move in a dedicated table for all g_qeglobals stuff
+typedef texturewin_t* (WINAPI* PFN_QEGLOBALSTEXTUREWIN) ();
+// look for the first selected patch mesh
+//++timo FIXME: this is a convenient func since there's no way to scan patches ( yet )
+typedef patchMesh_t* (WINAPI* PFN_GETSELECTEDPATCH) ();
+typedef void (WINAPI* PFN_PATCHREBUILD) (patchMesh_t *p);
+//++timo FIXME: this one in particular is a hack
+typedef void (WINAPI* PFN_GETTWOSELECTEDPATCH) (patchMesh_t **p1, patchMesh_t **p2);
+
+struct _QERAppSurfaceTable
+{
+ int m_nSize;
+ PFN_PATCHESSELECTED m_pfnOnlyPatchesSelected;
+ PFN_PATCHESSELECTED m_pfnAnyPatchesSelected;
+ PFN_QEGLOBALSTEXTUREWIN m_pfnQeglobalsTexturewin;
+ PFN_GETSELECTEDPATCH m_pfnGetSelectedPatch;
+ PFN_PATCHREBUILD m_pfnPatchRebuild;
+ PFN_GETTWOSELECTEDPATCH m_pfnGetTwoSelectedPatch;
+};
+
+#endif \ No newline at end of file
diff --git a/q3radiant/qerplugin.h b/q3radiant/qerplugin.h
new file mode 100755
index 0000000..97d55d9
--- /dev/null
+++ b/q3radiant/qerplugin.h
@@ -0,0 +1,566 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// QERadiant PlugIns
+//
+//
+
+#ifndef __QERPLUGIN_H__
+#define __QERPLUGIN_H__
+
+#include <windows.h>
+#include "qertypes.h"
+
+#define QER_PLUG_VERSION_1 1.00
+#define QER_PLUG_VERSION 1.70f
+
+#define QER_MAX_NAMELEN 1024
+
+// the editor will look for plugins in two places, the plugins path
+// under the application path, and the path under the basepath as defined
+// in the project (.qe4) file.
+//
+// you can drop any number of new texture, model format DLL's in the standard plugin path
+// but only one plugin that overrides map loading/saving, surface dialog, surface flags, etc..
+// should be used at one time.. if multiples are loaded then the last one loaded will be the
+// active one
+//
+// type of services the plugin supplies, pass any combo of these flags
+// it is assumed the plugin will have a matching function as defined below
+// to correlate to the implied functionality
+//
+// FIXME: after specing this crap i went to a simpler model so this may disappear
+#define QER_PLUG_GAME_TEXTURE 0x0001 // defines new texture format
+#define QER_PLUG_GAME_MODEL 0x0002 // defines new model format
+#define QER_PLUG_GAME_MAP 0x0004 // handles map load/save
+#define QER_PLUG_GAME_SURFACEDLG 0x0008 // handles surface dialog
+#define QER_PLUG_GAME_SURFACEFLAGS 0x0010 // renames surface/content names
+
+// basics
+#define QERPLUG_INIT "QERPlug_Init"
+#define QERPLUG_GETNAME "QERPlug_GetName"
+#define QERPLUG_GETCOMMANDLIST "QERPlug_GetCommandList"
+#define QERPLUG_DISPATCH "QERPlug_Dispatch"
+#define QERPLUG_GETFUNCTABLE "QERPlug_GetFuncTable"
+
+// FIXME: not used, probably should remove
+#define QERPLUG_GETSERVICETPE "QERPlug_GetServiceType"
+
+// game stuff
+#define QERPLUG_GETTEXTUREINFO "QERPlug_GetTextureInfo" // gets a texture info structure
+#define QERPLUG_LOADTEXTURE "QERPlug_LoadTexture" // loads a texture, will return an RGBA structure
+ // and any surface flags/contents for it
+#define QERPLUG_GETTMODELINFO "QERPlug_GetModelInfo" // gets a model info structure
+#define QERPLUG_LOADMODEL "QERPlug_LoadModel" // loads model data from a plugin
+#define QERPLUG_DOSURFACEDLG "QERPlug_DoSurfaceDlg" // runs the surface dialog in a plugin
+ // this is going to get icky
+#define QERPLUG_GETSURFACEFLAGS "QERPlug_GetSurfaceFlags" // gets a list of surface/content flag names from a plugin
+
+struct _QERTextureInfo
+{
+ char m_TextureExtension[QER_MAX_NAMELEN]; // the extension these textures have
+ qboolean m_bHiColor; // if textures are NOT high color, the default
+ // palette (as described inthe qe4 file will be used for gamma correction)
+ // if they are high color, gamma and shading are computed on the fly
+ // based on the rgba data
+ //--bool m_bIsShader; // will probably do q3 shaders this way when i merge
+ qboolean m_bWadStyle; // if this is true, the plugin will be presented with the texture path
+ // defined in the .qe4 file and is expected to preload all the textures
+ qboolean m_bHalfLife; // causes brushes to be saved/parsed without the surface contents/flags/value
+};
+
+struct _QERTextureLoad // returned by a plugin
+{
+ _QERTextureLoad()
+ {
+ memset(reinterpret_cast<void*>(this), 0, sizeof(_QERTextureLoad));
+ };
+
+ ~_QERTextureLoad()
+ {
+ delete []m_pRGBA;
+ delete []m_pName;
+ };
+
+ void makeSpace(int nSize)
+ {
+ m_pRGBA = new unsigned char[nSize+1];
+ };
+
+ void setName(const char* p)
+ {
+ m_pName = new char[strlen(p)+1];
+ strcpy(m_pName, p);
+ };
+
+
+ unsigned char *m_pRGBA; // rgba data (alpha channel is supported and drawn appropriately)
+ int m_nWidth; // width
+ int m_nHeight; // height
+ int m_nContents; // default contents
+ int m_nFlags; // "" flags
+ int m_nValue; // "" value
+ char *m_pName; // name to be referenced in map, build tools, etc.
+};
+
+struct _QERModelInfo
+{
+ char m_ModelExtension[QER_MAX_NAMELEN];
+ bool m_bSkinned;
+ bool m_bMultipart;
+};
+
+struct _QERModelLoad
+{
+ // vertex and skin data
+};
+
+
+// hook functions
+// FIXME: none of the hook stuff works for v1.00
+#define QERPLUG_MAPLOAD "QERPlug_MapLoad"
+#define QERPLUG_MAPSAVE "QERPlug_MapSave"
+
+//=========================================
+// plugin functions version 1.0
+typedef LPCSTR (WINAPI* PFN_QERPLUG_INIT)(HMODULE hApp, HWND hwndMain);
+typedef LPCSTR (WINAPI* PFN_QERPLUG_GETNAME)();
+typedef LPCSTR (WINAPI* PFN_QERPLUG_GETCOMMANDLIST)();
+typedef void (WINAPI* PFN_QERPLUG_DISPATCH)(LPCSTR p, vec3_t vMin, vec3_t vMax, BOOL bSingleBrush);
+typedef LPVOID (WINAPI* PFN_QERPLUG_GETFUNCTABLE)();
+typedef void (WINAPI* PFN_QERPLUG_MAPLOAD)();
+typedef void (WINAPI* PFN_QERPLUG_MAPSAVE)();
+
+// editor defined plugin dispatches
+// these are used to signal the completion after a 'Get' function is called in the editor
+#define QERPLUG_DISPATCH_POINTDONE "PointDone"
+#define QERPLUG_DISPATCH_BRUSHDONE "BrushDone"
+
+// v1.5
+//
+// Texture loading
+// returns a ptr to _QERTextureInfo
+typedef LPVOID (WINAPI* PFN_QERPLUG_GETTEXTUREINFO)();
+//
+// loads a texture by calling the texture load func in the editor (defined below)
+// transparency (for water, fog, lava, etc.. ) can be emulated in the editor
+// by passing in appropriate alpha data or by setting the appropriate surface flags
+// expected by q2 (which the editor will use.. )
+typedef void (WINAPI* PFN_QERPLUG_LOADTEXTURE)(LPCSTR pFilename);
+
+// v1.6
+typedef LPVOID (WINAPI* PFN_QERPLUG_GETSURFACEFLAGS)();
+
+// v1.7
+// if exists in plugin, gets called between INIT and GETCOMMANDLIST
+// the plugin can register the EClasses he wants to handle
+//++timo TODO: this has got to move into the table, and be requested by QERPlug_RequestInterface
+//++timo FIXME: the LPVOID parameter must be casted to an IEpair interface
+#define QERPLUG_REGISTERPLUGINENTITIES "QERPlug_RegisterPluginEntities"
+typedef void (WINAPI* PFN_QERPLUG_REGISTERPLUGINENTITIES)( LPVOID );
+// if exists in plugin, gets called between INIT and GETCOMMANDLIST
+// the plugin can Init all it needs for surface properties
+#define QERPLUG_INITSURFACEPROPERTIES "QERPlug_InitSurfaceProperties"
+typedef void (WINAPI* PFN_QERPLUG_INITSURFACEPROPERTIES)();
+// if Radiant needs to use a particular set of commands, it can request the plugin to fill a func table
+// this is similar to PFN_QERAPP_REQUESTINTERFACE
+#define QERPLUG_REQUESTINTERFACE "QERPlug_RequestInterface"
+typedef int (WINAPI* PFN_QERPLUG_REQUESTINTERFACE)( REFGUID, LPVOID );
+
+//=========================================
+// editor functions
+
+// There are 3 potential brush handle lists
+// 1. the list that contains brushes a plugin creates using CreateBrushHandle
+// 2. the selected brush list (brushes the user has selected)
+// 3. the active brush list (brushes in the map that are not selected)
+//
+// In general, the same things can be done to brush handles (face manip, delete brushhandle, etc.. ) in each
+// list. There are a few exceptions.
+// 1. You cannot commit a selected or active brush handle to the map. This is because it is already in the map.
+// 2. You cannot bind brush handles from the selected or active brush list to an entity. As of v1.0 of the plugins
+// the only way for a plugin to create entities is to create a brush handles (or a list of handles) and then bind
+// them to an entity. This will commit the brush(s) and/or the entities to the map as well.
+//
+// To use the active or selected brush lists, you must first allocate them (which returns a count) and then
+// release them when you are finish manipulating brushes in one of those lists.
+
+//++timo NOTE : the #defines here are never used, but can help finding where things are done in the editor
+
+// brush manipulation routines
+#define QERAPP_CREATEBRUSH "QERApp_CreateBrush"
+#define QERAPP_CREATEBRUSHHANDLE "QERApp_CreateBrushHandle"
+#define QERAPP_DELETEBRUSHHANDLE "QERApp_DeleteBrushHandle"
+#define QERAPP_COMMITBRUSHHANDLETOMAP "QERApp_CommitBrushHandleToMap"
+//++timo not implemented .. remove
+// #define QERAPP_BINDHANDLESTOENTITY "QERApp_BindHandlesToEntity"
+#define QERAPP_ADDFACE "QERApp_AddFace"
+#define QERAPP_ADDFACEDATA "QERApp_AddFaceData"
+#define QERAPP_GETFACECOUNT "QERApp_GetFaceCount"
+#define QERAPP_GETFACEDATA "QERApp_GetFaceData"
+#define QERAPP_SETFACEDATA "QERApp_SetFaceData"
+#define QERAPP_DELETEFACE "QERApp_DeleteFace"
+#define QERAPP_TEXTUREBRUSH "QERApp_TextureBrush"
+#define QERAPP_BUILDBRUSH "QERApp_BuildBrush" // PGM
+#define QERAPP_SELECTEDBRUSHCOUNT "QERApp_SelectedBrushCount"
+#define QERAPP_ALLOCATESELECTEDBRUSHHANDLES "QERApp_AllocateSelectedBrushHandles"
+#define QERAPP_RELEASESELECTEDBRUSHHANDLES "QERApp_ReleaseSelectedBrushHandles"
+#define QERAPP_GETSELECTEDBRUSHHANDLE "QERApp_GetSelectedBrushHandle"
+#define QERAPP_ACTIVEBRUSHCOUNT "QERApp_ActiveBrushCount"
+#define QERAPP_ALLOCATEACTIVEBRUSHHANDLES "QERApp_AllocateActiveBrushHandles"
+#define QERAPP_RELEASEACTIVEBRUSHHANDLES "QERApp_ReleaseActiveBrushHandles"
+#define QERAPP_GETACTIVEBRUSHHANDLE "QERApp_GetActiveBrushHandle"
+
+// texture stuff
+#define QERAPP_TEXTURECOUNT "QERApp_TextureCount"
+#define QERAPP_GETTEXTURE "QERApp_GetTexture"
+#define QERAPP_GETCURRENTTEXTURE "QERApp_GetCurrentTexture"
+#define QERAPP_SETCURRENTTEXTURE "QERApp_SetCurrentTexture"
+
+// selection
+#define QERAPP_DELETESELECTION "QERApp_DeleteSelection"
+#define QERAPP_SELECTBRUSH "QERApp_SelectBrush" // PGM
+#define QERAPP_DESELECTBRUSH "QERApp_DeselectBrush" // PGM
+#define QERAPP_DESELECTALLBRUSHES "QERApp_DeselectAllBrushes" // PGM
+
+// data gathering
+#define QERAPP_GETPOINTS "QERApp_GetPoints"
+#define QERAPP_SELECTBRUSHES "QERApp_GetBrushes"
+
+// entity class stuff
+// the entity handling is very basic for 1.0
+#define QERAPP_GETECLASSCOUNT "QERApp_GetEClassCount"
+#define QERAPP_GETECLASS "QERApp_GetEClass"
+
+// misc
+#define QERAPP_SYSMSG "QERApp_SysMsg"
+#define QERAPP_INFOMSG "QERApp_InfoMsg"
+#define QERAPP_HIDEINFOMSG "QERApp_HideInfoMsg"
+#define QERAPP_POSITIONVIEW "QERApp_PositionView" // PGM
+#define QERAPP_RESET_PLUGINS "QERApp_ResetPlugins"
+
+// texture loading
+#define QERAPP_LOADTEXTURERGBA "QERApp_LoadTextureRGBA"
+
+// FIXME: the following are not implemented yet
+// hook registrations
+#define QERAPP_REGISTER_MAPLOADFUNC "QERApp_Register_MapLoadFunc"
+#define QERAPP_REGISTER_MAPSAVEFUNC "QERApp_Register_MapSaveFunc"
+
+// FIXME: the following are not implemented yet
+#define QERAPP_REGISTER_PROJECTLOADFUNC "QERApp_Register_ProjectLoadFunc"
+#define QERAPP_REGISTER_MOUSEHANDLER "QERApp_Register_MouseHandler"
+#define QERAPP_REGISTER_KEYHANDLER "QERApp_Register_KeyHandler"
+
+// FIXME: new primtives do not work in v1.00
+// primitives are new types of things in the map
+// for instance, the Q3 curves could have been done as
+// primitives instead of being built in
+// it will be a plugins responsibility to hook the map load and save funcs to load
+// and/or save any additional data (like new primitives of some type)
+// the editor will call each registered renderer during the rendering process to repaint
+// any primitives the plugin owns
+// each primitive object has a temporary sibling brush that lives in the map
+// FIXME: go backwards on this a bit.. orient it more towards the temp brush mode as it will be cleaner
+// basically a plugin will hook the map load and save and will add the primitives to the map.. this will
+// produce a temporary 'primitive' brush and the appropriate renderer will be called as well as the
+// edit handler (for edge drags, sizes, rotates, etc.. ) and the vertex maker will be called when vertex
+// mode is attemped on the brush.. there will need to be a GetPrimitiveBounds callback in the edit handler
+// so the brush can resize appropriately as needed.. this might be the plugins responsibility to set the
+// sibling brushes size.. it will then be the plugins responsibility to hook map save to save the primitives
+// as the editor will discard any temp primitive brushes.. (there probably needs to be some kind of sanity check
+// here as far as keeping the brushes and the plugin in sync.. i suppose the edit handler can deal with all of that
+// crap but it looks like a nice place for a mess)
+#define QERAPP_REGISTER_PRIMITIVE "QERApp_Register_Primitive"
+#define QERAPP_REGISTER_RENDERER "QERApp_Register_Renderer"
+#define QERAPP_REGISTER_EDITHANDLER "QERApp_Register_EditHandler"
+#define QERAPP_REGISTER_VERTEXMAKER "QERApp_Register_VertexMaker"
+#define QERAPP_ADDPRIMITIVE "QERApp_AddPrimitive"
+
+// v1.70
+#define QERAPP_GETENTITYCOUNT "QERApp_GetEntityCount"
+#define QERAPP_GETENTITYHANDLE "QERApp_GetEntityHandle"
+//++timo not implemented for the moment
+// #define QERAPP_GETENTITYINFO "QERApp_GetEntityInfo"
+//++timo does the keyval need some more funcs to add/remove ?
+// get the pointer and do the changes yourself
+#define QERAPP_GETENTITYKEYVALLIST "QERApp_GetKeyValList"
+#define QERAPP_ALLOCATEEPAIR "QERApp_AllocateEpair"
+// will check current KeyVal list is NULL, otherwise use GetKeyValList
+#define QERAPP_SETENTITYKEYVALLIST "QERApp_SetKeyValList"
+#define QERAPP_ALLOCATEENTITYBRUSHHANDLES "QERApp_AllocateEntityBrushHandles"
+#define QERAPP_RELEASEENTITYBRUSHHANDLES "QERApp_ReleaseEntityBrushHandles"
+#define QERAPP_GETENTITYBRUSHHANDLE "QERApp_GetEntityBrushHandle"
+#define QERAPP_CREATEENTITYHANDLE "QERApp_CreateEntityHandle"
+#define QERAPP_COMMITBRUSHHANDLETOENTITY "QERApp_CommitBrushHandleToEntity"
+#define QERAPP_COMMITENTITYHANDLETOMAP "QERApp_CommitEntityHandleToMap"
+#define QERAPP_SETSCREENUPDATE "QERApp_SetScreenUpdate"
+#define QERAPP_BUILDBRUSH2 "QERApp_BuildBrush2"
+
+struct _QERPointData
+{
+ int m_nCount;
+ vec3_t *m_pVectors;
+};
+
+struct _QERFaceData
+{
+ char m_TextureName[QER_MAX_NAMELEN];
+ int m_nContents;
+ int m_nFlags;
+ int m_nValue;
+ float m_fShift[2];
+ float m_fRotate;
+ float m_fScale[2];
+ vec3_t m_v1, m_v2, m_v3;
+ // brush primitive additions
+ qboolean m_bBPrimit;
+ brushprimit_texdef_t brushprimit_texdef;
+};
+
+typedef void (WINAPI* PFN_QERAPP_CREATEBRUSH)(vec3_t vMin, vec3_t vMax);
+
+typedef LPVOID (WINAPI* PFN_QERAPP_CREATEBRUSHHANDLE)();
+typedef void (WINAPI* PFN_QERAPP_DELETEBRUSHHANDLE)(LPVOID pv);
+typedef void (WINAPI* PFN_QERAPP_COMMITBRUSHHANDLETOMAP)(LPVOID pv);
+typedef void (WINAPI* PFN_QERAPP_ADDFACE)(LPVOID pv, vec3_t v1, vec3_t v2, vec3_t v3);
+
+typedef void (WINAPI* PFN_QERAPP_ADDFACEDATA)(LPVOID pv, _QERFaceData *pData);
+typedef int (WINAPI* PFN_QERAPP_GETFACECOUNT)(LPVOID pv);
+typedef _QERFaceData* (WINAPI* PFN_QERAPP_GETFACEDATA)(LPVOID pv, int nFaceIndex);
+typedef void (WINAPI* PFN_QERAPP_SETFACEDATA)(LPVOID pv, int nFaceIndex, _QERFaceData *pData);
+typedef void (WINAPI* PFN_QERAPP_DELETEFACE)(LPVOID pv, int nFaceIndex);
+typedef void (WINAPI* PFN_QERAPP_TEXTUREBRUSH)(LPVOID pv, LPCSTR pName);
+typedef void (WINAPI* PFN_QERAPP_BUILDBRUSH)(LPVOID pv); // PGM
+typedef void (WINAPI* PFN_QERAPP_SELECTBRUSH)(LPVOID pv); // PGM
+typedef void (WINAPI* PFN_QERAPP_DESELECTBRUSH)(LPVOID pv); // PGM
+typedef void (WINAPI* PFN_QERAPP_DESELECTALLBRUSHES)(); // PGM
+
+typedef void (WINAPI* PFN_QERAPP_DELETESELECTION)();
+typedef void (WINAPI* PFN_QERAPP_GETPOINTS)(int nMax, _QERPointData *pData, LPCSTR pMsg);
+typedef void (WINAPI* PFN_QERAPP_SYSMSG)(LPCSTR pMsg);
+typedef void (WINAPI* PFN_QERAPP_INFOMSG)(LPCSTR pMsg);
+typedef void (WINAPI* PFN_QERAPP_HIDEINFOMSG)();
+typedef void (WINAPI* PFN_QERAPP_POSITIONVIEW)(vec3_t v1, vec3_t v2); //PGM
+
+typedef int (WINAPI* PFN_QERAPP_SELECTEDBRUSHCOUNT)();
+typedef int (WINAPI* PFN_QERAPP_ALLOCATESELECTEDBRUSHHANDLES)();
+typedef void (WINAPI* PFN_QERAPP_RELEASESELECTEDBRUSHHANDLES)();
+typedef LPVOID (WINAPI* PFN_QERAPP_GETSELECTEDBRUSHHANDLE)(int nIndex);
+
+typedef int (WINAPI* PFN_QERAPP_ACTIVEBRUSHCOUNT)();
+typedef int (WINAPI* PFN_QERAPP_ALLOCATEACTIVEBRUSHHANDLES)();
+typedef void (WINAPI* PFN_QERAPP_RELEASEACTIVEBRUSHHANDLES)();
+typedef LPVOID (WINAPI* PFN_QERAPP_GETACTIVEBRUSHHANDLE)(int nIndex);
+
+typedef int (WINAPI* PFN_QERAPP_TEXTURECOUNT)();
+typedef LPCSTR (WINAPI* PFN_QERAPP_GETTEXTURE)(int nIndex);
+typedef LPCSTR (WINAPI* PFN_QERAPP_GETCURRENTTEXTURE)();
+typedef void (WINAPI* PFN_QERAPP_SETCURRENTTEXTURE)(LPCSTR pName);
+
+typedef void (WINAPI* PFN_QERAPP_REGISTERMAPLOAD)(LPVOID vp);
+typedef void (WINAPI* PFN_QERAPP_REGISTERMAPSAVE)(LPVOID vp);
+
+typedef int (WINAPI* PFN_QERAPP_GETECLASSCOUNT)();
+typedef LPCSTR (WINAPI* PFN_QERAPP_GETECLASS)(int nIndex);
+
+typedef void (WINAPI* PFN_QERAPP_RESETPLUGINS)();
+//--typedef int (WINAPI* PFN_QERAPP_GETENTITYCOUNT)();
+
+
+// called by texture loaders for each texture loaded
+typedef void (WINAPI* PFN_QERAPP_LOADTEXTURERGBA)(LPVOID vp);
+
+//--typedef LPCSTR (WINAPI* PFN_QERAPP_GETENTITY)(int nIndex);
+
+// v1.70
+typedef int (WINAPI* PFN_QERAPP_GETENTITYCOUNT)();
+typedef LPVOID (WINAPI* PFN_QERAPP_GETENTITYHANDLE)(int nIndex);
+typedef epair_t** (WINAPI* PFN_QERAPP_GETENTITYKEYVALLIST)(LPVOID vp);
+typedef epair_t* (WINAPI* PFN_QERAPP_ALLOCATEEPAIR)( char*, char* );
+typedef void (WINAPI* PFN_QERAPP_SETENTITYKEYVALLIST)(LPVOID vp, epair_t* ep);
+typedef int (WINAPI* PFN_QERAPP_ALLOCATEENTITYBRUSHHANDLES)(LPVOID vp);
+typedef void (WINAPI* PFN_QERAPP_RELEASEENTITYBRUSHHANDLES)();
+typedef LPVOID (WINAPI* PFN_QERAPP_GETENTITYBRUSHHANDLE)(int nIndex);
+typedef LPVOID (WINAPI* PFN_QERAPP_CREATEENTITYHANDLE)();
+typedef void (WINAPI* PFN_QERAPP_COMMITBRUSHHANDLETOENTITY)( LPVOID vpBrush, LPVOID vpEntity);
+typedef void (WINAPI* PFN_QERAPP_COMMITENTITYHANDLETOMAP)(LPVOID vp);
+typedef void (WINAPI* PFN_QERAPP_SETSCREENUPDATE)(int bScreenUpdate);
+// this one uses window flags defined in qertypes.h
+typedef void (WINAPI* PFN_QERAPP_SYSUPDATEWINDOWS)(int bits);
+//++timo remove this one
+typedef void (WINAPI* PFN_QERAPP_BUILDBRUSH2)(LPVOID vp, int bConvert);
+// Radiant functions for Plugin Entities
+// will look for the value of the correponding key in the project epairs
+typedef char* (WINAPI* PFN_QERAPP_READPROJECTKEY)(char* );
+// will scan the file, parse the first EClass found, and associate it to the caller plugin
+// will only read first EClass in the file, and return true/false
+typedef int (WINAPI* PFN_QERAPP_SCANFILEFORECLASS)(char* );
+// plugins can request additional interfaces from the editor when they need specific services
+typedef int (WINAPI* PFN_QERAPP_REQUESTINTERFACE)( REFGUID, LPVOID );
+// use this one for errors, Radiant will stop after the "edit preferences" dialog
+typedef void (WINAPI* PFN_QERAPP_ERRORMSG)(LPCSTR pMsg);
+// use to gain read access to the project epairs
+// FIXME: removed, accessed through QERPlug_RegisterPluginEntities with the IEpair interface
+// typedef void (WINAPI* PFN_QERAPP_GETPROJECTEPAIR)(epair_t **);
+// used to allocate and read a buffer
+//++timo NOTE: perhaps this would need moving to some kind of dedicated interface
+typedef int (WINAPI* PFN_QERAPP_LOADFILE)(const char *pLocation, void ** buffer);
+typedef char* (WINAPI* PFN_QERAPP_EXPANDRELETIVEPATH)(char *);
+typedef void (WINAPI* PFN_QERAPP_QECONVERTDOSTOUNIXNAME)( char *dst, const char *src );
+typedef int (WINAPI* PFN_QERAPP_HASSHADER)(const char *);
+typedef int (WINAPI* PFN_QERAPP_TEXTURELOADSKIN)(char *pName, int *pnWidth, int *pnHeight);
+// free memory previously allocated by Radiant
+// NOTE: this is dirty
+typedef void (WINAPI* PFN_QERAPP_RADIANTFREE)( void * );
+// retrieves the path to the engine from the preferences dialog box
+typedef char* (WINAPI* PFN_QERAPP_GETGAMEPATH)();
+// retrieves full Radiant path
+typedef char* (WINAPI* PFN_QERAPP_GETQERPATH)();
+
+// patches in/out
+// NOTE: this is a bit different from the brushes in/out, no LPVOID handles this time
+// use int indexes instead
+// if you call AllocateActivePatchHandles, you'll be playing with active patches
+// AllocateSelectedPatcheHandles for selected stuff
+// a call to CreatePatchHandle will move you to a seperate index table
+typedef int (WINAPI* PFN_QERAPP_ALLOCATEACTIVEPATCHHANDLES) ();
+typedef int (WINAPI* PFN_QERAPP_ALLOCATESELECTEDPATCHHANDLES) ();
+typedef void (WINAPI* PFN_QERAPP_RELEASEPATCHHANDLES) ();
+typedef patchMesh_t* (WINAPI* PFN_QERAPP_GETPATCHDATA) (int);
+typedef void (WINAPI* PFN_QERAPP_DELETEPATCH) (int);
+typedef int (WINAPI* PFN_QERAPP_CREATEPATCHHANDLE) ();
+// when commiting, only a few patchMesh_t members are relevant:
+// int width, height; // in control points, not patches
+// int contents, flags, value, type;
+// drawVert_t ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
+// once you have commited the index is still available, if the patch handle was allocated by you
+// then you can re-use the index to commit other patches .. otherwise you can change existing patches
+// NOTE: the handle thing for plugin-allocated patches is a bit silly (nobody's perfect)
+// TODO: change current behaviour to an index = 0 to tell Radiant to allocate, other indexes to existing patches
+// patch is selected after a commit
+// you can add an optional texture / shader name .. if NULL will use the current texture
+typedef void (WINAPI* PFN_QERAPP_COMMITPATCHHANDLETOMAP) (int, patchMesh_t* pMesh, char *texName);
+
+// FIXME:
+// add map format extensions
+// add texture format handlers
+// add surface dialog handler
+// add model handler/displayer
+
+// v1 func table
+// Plugins need to declare one of these and implement the getfunctable as described above
+struct _QERFuncTable_1
+{
+ float m_fVersion;
+ int m_nSize;
+ PFN_QERAPP_CREATEBRUSH m_pfnCreateBrush;
+ PFN_QERAPP_CREATEBRUSHHANDLE m_pfnCreateBrushHandle;
+ PFN_QERAPP_DELETEBRUSHHANDLE m_pfnDeleteBrushHandle;
+ PFN_QERAPP_COMMITBRUSHHANDLETOMAP m_pfnCommitBrushHandle;
+ PFN_QERAPP_ADDFACE m_pfnAddFace;
+ PFN_QERAPP_ADDFACEDATA m_pfnAddFaceData;
+ PFN_QERAPP_GETFACEDATA m_pfnGetFaceData;
+ PFN_QERAPP_GETFACECOUNT m_pfnGetFaceCount;
+ PFN_QERAPP_SETFACEDATA m_pfnSetFaceData;
+ PFN_QERAPP_DELETEFACE m_pfnDeleteFace;
+ PFN_QERAPP_TEXTUREBRUSH m_pfnTextureBrush;
+ PFN_QERAPP_BUILDBRUSH m_pfnBuildBrush; // PGM
+ PFN_QERAPP_SELECTBRUSH m_pfnSelectBrush; // PGM
+ PFN_QERAPP_DESELECTBRUSH m_pfnDeselectBrush; // PGM
+ PFN_QERAPP_DESELECTALLBRUSHES m_pfnDeselectAllBrushes; // PGM
+
+ PFN_QERAPP_DELETESELECTION m_pfnDeleteSelection;
+ PFN_QERAPP_GETPOINTS m_pfnGetPoints;
+ PFN_QERAPP_SYSMSG m_pfnSysMsg;
+ PFN_QERAPP_INFOMSG m_pfnInfoMsg;
+ PFN_QERAPP_HIDEINFOMSG m_pfnHideInfoMsg;
+ PFN_QERAPP_POSITIONVIEW m_pfnPositionView; // PGM
+
+ PFN_QERAPP_SELECTEDBRUSHCOUNT m_pfnSelectedBrushCount;
+ PFN_QERAPP_ALLOCATESELECTEDBRUSHHANDLES m_pfnAllocateSelectedBrushHandles;
+ PFN_QERAPP_RELEASESELECTEDBRUSHHANDLES m_pfnReleaseSelectedBrushHandles;
+ PFN_QERAPP_GETSELECTEDBRUSHHANDLE m_pfnGetSelectedBrushHandle;
+
+ PFN_QERAPP_ACTIVEBRUSHCOUNT m_pfnActiveBrushCount;
+ PFN_QERAPP_ALLOCATEACTIVEBRUSHHANDLES m_pfnAllocateActiveBrushHandles;
+ PFN_QERAPP_RELEASEACTIVEBRUSHHANDLES m_pfnReleaseActiveBrushHandles;
+ PFN_QERAPP_GETACTIVEBRUSHHANDLE m_pfnGetActiveBrushHandle;
+
+ //++timo this would need to be removed and replaced by the IShaders interface
+ PFN_QERAPP_TEXTURECOUNT m_pfnTextureCount;
+ PFN_QERAPP_GETTEXTURE m_pfnGetTexture;
+ PFN_QERAPP_GETCURRENTTEXTURE m_pfnGetCurrentTexture;
+ PFN_QERAPP_SETCURRENTTEXTURE m_pfnSetCurrentTexture;
+
+ PFN_QERAPP_GETECLASSCOUNT m_pfnGetEClassCount;
+ PFN_QERAPP_GETECLASS m_pfnGetEClass;
+ PFN_QERAPP_RESETPLUGINS m_pfnResetPlugins;
+ // v1.00 ends here
+ // v1.50 starts here
+ PFN_QERAPP_LOADTEXTURERGBA m_pfnLoadTextureRGBA;
+ // v1.50 ends here
+ // v1.70 starts here
+ PFN_QERAPP_GETENTITYCOUNT m_pfnGetEntityCount;
+ PFN_QERAPP_GETENTITYHANDLE m_pfnGetEntityHandle;
+ PFN_QERAPP_GETENTITYKEYVALLIST m_pfnGetEntityKeyValList;
+ PFN_QERAPP_SETENTITYKEYVALLIST m_pfnSetEntityKeyValList;
+ PFN_QERAPP_ALLOCATEENTITYBRUSHHANDLES m_pfnAllocateEntityBrushHandles;
+ PFN_QERAPP_RELEASEENTITYBRUSHHANDLES m_pfnReleaseEntityBrushHandles;
+ PFN_QERAPP_GETENTITYBRUSHHANDLE m_pfnGetEntityBrushHandle;
+ PFN_QERAPP_CREATEENTITYHANDLE m_pfnCreateEntityHandle;
+ PFN_QERAPP_COMMITBRUSHHANDLETOENTITY m_pfnCommitBrushHandleToEntity;
+ PFN_QERAPP_COMMITENTITYHANDLETOMAP m_pfnCommitEntityHandleToMap;
+ PFN_QERAPP_ALLOCATEEPAIR m_pfnAllocateEpair;
+ PFN_QERAPP_SETSCREENUPDATE m_pfnSetScreenUpdate;
+ PFN_QERAPP_SYSUPDATEWINDOWS m_pfnSysUpdateWindows;
+ PFN_QERAPP_BUILDBRUSH2 m_pfnBuildBrush2;
+ // Radiant functions for Plugin Entities
+ PFN_QERAPP_READPROJECTKEY m_pfnReadProjectKey;
+ PFN_QERAPP_SCANFILEFORECLASS m_pfnScanFileForEClass;
+ // plugins can request additional interfaces
+ PFN_QERAPP_REQUESTINTERFACE m_pfnRequestInterface;
+ PFN_QERAPP_ERRORMSG m_pfnErrorMsg;
+ // loading a file into a buffer
+ PFN_QERAPP_LOADFILE m_pfnLoadFile;
+ PFN_QERAPP_EXPANDRELETIVEPATH m_pfnExpandReletivePath;
+ PFN_QERAPP_QECONVERTDOSTOUNIXNAME m_pfnQE_ConvertDOSToUnixName;
+ PFN_QERAPP_HASSHADER m_pfnHasShader;
+ PFN_QERAPP_TEXTURELOADSKIN m_pfnTexture_LoadSkin;
+ PFN_QERAPP_RADIANTFREE m_pfnRadiantFree;
+ PFN_QERAPP_GETGAMEPATH m_pfnGetGamePath;
+ PFN_QERAPP_GETQERPATH m_pfnGetQERPath;
+ // patches in / out
+ PFN_QERAPP_ALLOCATEACTIVEPATCHHANDLES m_pfnAllocateActivePatchHandles;
+ PFN_QERAPP_ALLOCATESELECTEDPATCHHANDLES m_pfnAllocateSelectedPatchHandles;
+ PFN_QERAPP_RELEASEPATCHHANDLES m_pfnReleasePatchHandles;
+ PFN_QERAPP_GETPATCHDATA m_pfnGetPatchData;
+ PFN_QERAPP_DELETEPATCH m_pfnDeletePatch;
+ PFN_QERAPP_CREATEPATCHHANDLE m_pfnCreatePatchHandle;
+ PFN_QERAPP_COMMITPATCHHANDLETOMAP m_pfnCommitPatchHandleToMap;
+};
+
+
+//--typedef int (WINAPI* PFN_QERAPP_BRUSHCOUNT )();
+//--typedef brush_t* (WINAPI* PFN_QERAPP_GETBRUSH )();
+//--typedef void (WINAPI* PFN_QERAPP_DELETEBRUSH )();
+
+#endif \ No newline at end of file
diff --git a/q3radiant/res/BEVEL.BMP b/q3radiant/res/BEVEL.BMP
new file mode 100755
index 0000000..5c2dcd6
--- /dev/null
+++ b/q3radiant/res/BEVEL.BMP
Binary files differ
diff --git a/q3radiant/res/BITMAP2.BMP b/q3radiant/res/BITMAP2.BMP
new file mode 100755
index 0000000..7982fa2
--- /dev/null
+++ b/q3radiant/res/BITMAP2.BMP
Binary files differ
diff --git a/q3radiant/res/BMP00001.BMP b/q3radiant/res/BMP00001.BMP
new file mode 100755
index 0000000..bc656df
--- /dev/null
+++ b/q3radiant/res/BMP00001.BMP
Binary files differ
diff --git a/q3radiant/res/BMP00002.BMP b/q3radiant/res/BMP00002.BMP
new file mode 100755
index 0000000..7233996
--- /dev/null
+++ b/q3radiant/res/BMP00002.BMP
Binary files differ
diff --git a/q3radiant/res/BMP0002.BMP b/q3radiant/res/BMP0002.BMP
new file mode 100755
index 0000000..50ab191
--- /dev/null
+++ b/q3radiant/res/BMP0002.BMP
Binary files differ
diff --git a/q3radiant/res/DEFTEX.WAL b/q3radiant/res/DEFTEX.WAL
new file mode 100755
index 0000000..498b56a
--- /dev/null
+++ b/q3radiant/res/DEFTEX.WAL
Binary files differ
diff --git a/q3radiant/res/ENDCAP.BMP b/q3radiant/res/ENDCAP.BMP
new file mode 100755
index 0000000..cb25691
--- /dev/null
+++ b/q3radiant/res/ENDCAP.BMP
Binary files differ
diff --git a/q3radiant/res/IBEVEL.BMP b/q3radiant/res/IBEVEL.BMP
new file mode 100755
index 0000000..4624f5d
--- /dev/null
+++ b/q3radiant/res/IBEVEL.BMP
Binary files differ
diff --git a/q3radiant/res/IENDCAP.BMP b/q3radiant/res/IENDCAP.BMP
new file mode 100755
index 0000000..892bbde
--- /dev/null
+++ b/q3radiant/res/IENDCAP.BMP
Binary files differ
diff --git a/q3radiant/res/Q.BMP b/q3radiant/res/Q.BMP
new file mode 100755
index 0000000..759b87c
--- /dev/null
+++ b/q3radiant/res/Q.BMP
Binary files differ
diff --git a/q3radiant/res/RADIANT3.GIF b/q3radiant/res/RADIANT3.GIF
new file mode 100755
index 0000000..adbe1f5
--- /dev/null
+++ b/q3radiant/res/RADIANT3.GIF
Binary files differ
diff --git a/q3radiant/res/Radiant.ico b/q3radiant/res/Radiant.ico
new file mode 100755
index 0000000..f644e9a
--- /dev/null
+++ b/q3radiant/res/Radiant.ico
Binary files differ
diff --git a/q3radiant/res/Radiant.rc2 b/q3radiant/res/Radiant.rc2
new file mode 100755
index 0000000..84a0b5d
--- /dev/null
+++ b/q3radiant/res/Radiant.rc2
@@ -0,0 +1,13 @@
+//
+// RADIANT.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/q3radiant/res/RadiantDoc.ico b/q3radiant/res/RadiantDoc.ico
new file mode 100755
index 0000000..3288c6f
--- /dev/null
+++ b/q3radiant/res/RadiantDoc.ico
Binary files differ
diff --git a/q3radiant/res/TOOLBAR1.BMP b/q3radiant/res/TOOLBAR1.BMP
new file mode 100755
index 0000000..55e05ec
--- /dev/null
+++ b/q3radiant/res/TOOLBAR1.BMP
Binary files differ
diff --git a/q3radiant/res/TOOLBAR2.BMP b/q3radiant/res/TOOLBAR2.BMP
new file mode 100755
index 0000000..dfa5dd1
--- /dev/null
+++ b/q3radiant/res/TOOLBAR2.BMP
Binary files differ
diff --git a/q3radiant/res/Toolbar.bmp b/q3radiant/res/Toolbar.bmp
new file mode 100755
index 0000000..1956dd5
--- /dev/null
+++ b/q3radiant/res/Toolbar.bmp
Binary files differ
diff --git a/q3radiant/res/VIEWDEFA.BMP b/q3radiant/res/VIEWDEFA.BMP
new file mode 100755
index 0000000..30233a8
--- /dev/null
+++ b/q3radiant/res/VIEWDEFA.BMP
Binary files differ
diff --git a/q3radiant/res/VIEWOPPO.BMP b/q3radiant/res/VIEWOPPO.BMP
new file mode 100755
index 0000000..afa4270
--- /dev/null
+++ b/q3radiant/res/VIEWOPPO.BMP
Binary files differ
diff --git a/q3radiant/res/bmp00003.bmp b/q3radiant/res/bmp00003.bmp
new file mode 100755
index 0000000..c7270fd
--- /dev/null
+++ b/q3radiant/res/bmp00003.bmp
Binary files differ
diff --git a/q3radiant/res/icon2.ico b/q3radiant/res/icon2.ico
new file mode 100755
index 0000000..47e4d87
--- /dev/null
+++ b/q3radiant/res/icon2.ico
Binary files differ
diff --git a/q3radiant/res/logo_sm3dfx.bmp b/q3radiant/res/logo_sm3dfx.bmp
new file mode 100755
index 0000000..9a1e106
--- /dev/null
+++ b/q3radiant/res/logo_sm3dfx.bmp
Binary files differ
diff --git a/q3radiant/res/shaderbar.bmp b/q3radiant/res/shaderbar.bmp
new file mode 100755
index 0000000..913de51
--- /dev/null
+++ b/q3radiant/res/shaderbar.bmp
Binary files differ
diff --git a/q3radiant/res/shaderdoc.ico b/q3radiant/res/shaderdoc.ico
new file mode 100755
index 0000000..3288c6f
--- /dev/null
+++ b/q3radiant/res/shaderdoc.ico
Binary files differ
diff --git a/q3radiant/res/shaderframe.ico b/q3radiant/res/shaderframe.ico
new file mode 100755
index 0000000..f644e9a
--- /dev/null
+++ b/q3radiant/res/shaderframe.ico
Binary files differ
diff --git a/q3radiant/resource.h b/q3radiant/resource.h
new file mode 100755
index 0000000..87789cb
--- /dev/null
+++ b/q3radiant/resource.h
@@ -0,0 +1,840 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Radiant.rc
+//
+#define IDSELECT 2
+#define IDOK2 2
+#define ID_APPLY 3
+#define IDD_ABOUTBOX 100
+#define IDR_ACCELERATOR1 104
+#define IDD_CREATE_ENTITY 107
+#define IDD_EDIT_ENTITY 108
+#define IDR_TOOLBAR1 109
+#define IDD_FINDTEXTURE 111
+#define IDD_ENTITY 115
+#define IDR_E_MENU 116
+#define IDD_EDITPROP 117
+#define IDD_GAMMA 118
+#define IDD_FINDBRUSH 119
+#define IDI_ICON1 120
+#define IDD_ROTATE 121
+#define IDD_SIDES 122
+#define IDD_ABOUT 123
+#define IDB_BITMAP1 127
+#define IDD_SURFACE 129
+#define IDR_MAINFRAME 130
+#define IDR_RADIANTYPE 131
+#define IDAPPLY 132
+#define IDS_STRING1 132
+#define ID_BTN_APPLY 133
+#define ID_TESTCAMERA 133
+#define IDC_CHECK_LIVE 134
+#define IDR_POPUP_TEXTURE 135
+#define IDR_POPUP_SELECTION 136
+#define IDR_POPUP_VIEW 137
+#define IDD_DLG_PREFS 139
+#define IDD_DLG_MAPINFO 141
+#define IDD_DLG_ENTITYLIST 142
+#define IDD_DLG_SCRIPTS 143
+#define IDD_DLG_NEWPROJECT 144
+#define IDD_DLG_COMMANDLIST 145
+#define IDR_MENU_DROP 146
+#define IDB_VIEWDEFAULT 147
+#define IDR_MENU_DAIKATANA 147
+#define IDB_VIEWQE4 148
+#define IDB_VIEWDEFAULT2 148
+#define IDR_MENU11 148
+#define IDR_MENU_QUAKE3 148
+#define IDB_VIEW4WAY 149
+#define IDB_VIEWDEFAULT3 149
+#define IDB_VIEWDEFAULT_Z 150
+#define IDB_3DFX 154
+#define IDR_ACCEL_SURFACE 155
+#define IDD_DIALOG_SCALE 156
+#define IDR_MINIACCEL 156
+#define IDD_DIALOG_FINDREPLACE 159
+#define IDD_DIALOG_STAIRS 160
+#define IDD_DIALOG_INPUT 161
+#define IDD_DLG_INFORMATION 162
+#define IDR_TOOLBAR_SCALELOCK 163
+#define IDR_TOOLBAR_ADVANCED 164
+#define IDD_PROJECT 165
+#define IDD_TEXTUREBAR 166
+#define IDD_ADDCMD 167
+#define IDD_DIALOG_TEXTURELIST 168
+#define IDD_DIALOG_NEWPATCH 169
+#define IDR_MENU1 170
+#define IDD_DIALOG_TEXTURELAYOUT 171
+#define IDR_POPUP_ENTITY 171
+#define IDD_DIALOG_CAP 173
+#define IDB_IENDCAP 175
+#define IDB_ENDCAP 176
+#define IDD_DIALOG_THICKEN 176
+#define IDB_BEVEL 177
+#define IDB_IBEVEL 178
+#define IDR_SHADERFRAME 179
+#define IDR_SHADERTYPE 180
+#define IDR_POPUP_GROUP 180
+#define IDR_POPUP_SPLINE 181
+#define IDD_DIALOG1 182
+#define IDD_DIALOG_PATCH 182
+#define IDD_PLAYWAVE 183
+#define IDD_TEXLIST 184
+#define IDD_DIALOG2 186
+#define IDD_DLG_GROUPS 186
+#define IDD_DLG_GROUP 188
+#define IDD_NEWNAME 189
+#define IDB_BITMAP_GROUPS 190
+#define IDD_DLG_CAMERA 194
+#define IDD_DLG_CAMERAEVENT 195
+#define IDD_DLG_CAMERATARGET 196
+#define IDC_BTN_HIDE 1000
+#define IDC_SPIN1 1001
+#define IDC_SPIN2 1002
+#define IDC_RADIO_MOUSE 1002
+#define IDC_SPIN3 1003
+#define IDC_RADIO2 1003
+#define IDC_RADIO_VIEWTYPE 1004
+#define IDC_RADIO3 1004
+#define IDC_RADIO_FALLOFF2 1004
+#define IDC_RADIO_VIEWTYPE2 1005
+#define IDC_BTN_BROWSE 1006
+#define IDC_EDIT_QUAKE2 1007
+#define IDC_RADIO_VIEWTYPE3 1008
+#define IDC_LIST_ENTITIES 1009
+#define IDC_RADIO_VIEWTYPE4 1009
+#define IDC_EDIT_TOTALBRUSHES 1010
+#define IDC_EDIT_PAKFILE 1010
+#define IDC_RADIO_RUNQUAKE 1011
+#define IDC_BTN_BROWSEPAK 1011
+#define IDC_RADIO_RUNQUAKE2 1012
+#define IDC_EDIT_PREFABPATH 1012
+#define IDC_RADIO_RUNQUAKE3 1013
+#define IDC_BTN_BROWSEPREFAB 1013
+#define IDC_CHECK_LOADLAST 1014
+#define IDC_TREE_ENTITY 1015
+#define IDC_CHECK_AUTOSAVE 1015
+#define IDC_CHECK_LOADLASTMAP 1016
+#define IDC_LIST_ENTITY 1017
+#define IDC_EDIT_USERPATH 1017
+#define IDC_ENTITY_COMMENT 1018
+#define IDC_LIST_SCRIPTS 1018
+#define IDC_BTN_BROWSEUSERINI 1018
+#define ID_NEW 1019
+#define IDC_CHECK_USESHADERS 1019
+#define ID_EDIT 1020
+#define IDC_EDIT_NAME 1020
+#define IDC_VALUE 1021
+#define ID_RUN 1021
+#define IDC_LIST_COMMANDS 1021
+#define IDC_KEY 1022
+#define IDC_EDIT_COLOR 1022
+#define IDC_ENTITY_LIST 1023
+#define IDC_CHECK_FACE 1023
+#define IDC_PAIRS 1024
+#define IDC_CHECK_RIGHTCLICK 1024
+#define IDC_CHECK_VERTEX 1025
+#define IDC_CHECK1 1026
+#define IDC_CHECK_TEXTUREWINDOW 1026
+#define IDC_CHECK2 1027
+#define IDC_CHECK_TEXTURETOOLBAR 1027
+#define IDC_CHECK3 1028
+#define IDC_CHECK_LIGHTDRAW 1028
+#define IDC_CHECK4 1029
+#define IDC_CHECK_SNAPT 1029
+#define IDC_CHECK5 1030
+#define IDC_CHECK_3DFX 1030
+#define IDC_CHECK_TEXTURESCROLLBAR 1030
+#define IDC_CHECK6 1031
+#define IDC_CHECK_INTERNALBSP 1031
+#define IDC_CHECK7 1032
+#define IDC_CHECK_RUNQUAKE 1032
+#define IDC_CHECK8 1033
+#define IDC_CHECK_SETGAME 1033
+#define IDC_CHECK9 1034
+#define IDC_CHECK_3DFX2 1034
+#define IDC_CHECK_DISPLAYLISTS 1034
+#define IDC_CHECK10 1035
+#define IDC_EDIT_AUTOSAVE 1035
+#define IDC_CHECK11 1036
+#define IDC_CHECK_PAK 1036
+#define IDC_CHECK12 1037
+#define IDC_BUTTON1 1037
+#define IDC_BTN_APPLYTEXTURESTUFF 1037
+#define IDC_CHECK_QE4PAINTING 1037
+#define IDC_BTN_PLAY 1037
+#define IDC_BTN_ADD 1037
+#define IDC_BTN_TEXTURE 1037
+#define IDC_BTN_PREVIEW 1037
+#define IDC_BTN_ADDTARGET 1037
+#define IDC_ANGLE90 1038
+#define IDC_CHECK13 1038
+#define IDC_SPIN_AUTOSAVE 1038
+#define IDC_BTN_DEL 1038
+#define IDC_ANGLE45 1039
+#define IDC_CHECK14 1039
+#define IDC_BUTTON_CREDITS 1039
+#define IDC_CHECK_SIZEPAINT 1039
+#define IDC_BTN_ADD3 1039
+#define IDC_BTN_EDIT 1039
+#define IDC_ANGLE135 1040
+#define IDC_CHECK15 1040
+#define IDC_EDIT_X 1040
+#define IDC_CHECK_TEXTURELOCALAXIS 1040
+#define IDC_SPIN_UNDO 1040
+#define IDC_ANGLE225 1041
+#define IDC_CHECK16 1041
+#define IDC_CHECK_SNAPSHOTS 1041
+#define IDC_ANGLEUP 1042
+#define IDC_CHECK17 1042
+#define IDC_EDIT_FIND 1042
+#define IDC_SPIN_POINTSIZE 1042
+#define IDC_ANGLE180 1043
+#define IDC_CHECK18 1043
+#define IDC_EDIT_REPLACE 1043
+#define IDC_EDIT_S 1043
+#define IDC_ANGLE315 1044
+#define IDC_CHECK19 1044
+#define IDC_CHECK_SELECTED 1044
+#define IDC_EDIT_T 1044
+#define IDC_ANGLE0 1045
+#define IDC_CHECK20 1045
+#define IDC_CHECK_FORCE 1045
+#define IDC_ANGLE270 1046
+#define IDC_CHECK21 1046
+#define IDC_ANGLEDOWN 1047
+#define IDC_CHECK22 1047
+#define IDC_DELETEKEY 1048
+#define IDC_ADDPAIR 1048
+#define IDC_CHECK23 1048
+#define IDC_DELETEPAIR 1049
+#define IDC_CHECK24 1049
+#define IDC_CHECK25 1050
+#define IDC_SPAWN1 1051
+#define IDC_CHECK26 1051
+#define IDC_SPAWN2 1052
+#define IDC_CHECK27 1052
+#define IDC_SPAWN3 1053
+#define IDC_CHECK28 1053
+#define IDC_SPAWN4 1054
+#define IDC_CHECK29 1054
+#define IDC_SPAWN5 1055
+#define IDC_CHECK30 1055
+#define IDC_SPAWN6 1056
+#define IDC_CHECK31 1056
+#define IDC_SPAWN7 1057
+#define IDC_CHECK32 1057
+#define IDC_SPAWN8 1058
+#define IDC_CHECK33 1058
+#define IDC_EDIT1 1059
+#define IDC_CHECK34 1059
+#define IDC_ROTATE_BOX 1060
+#define IDC_ROTZ 1060
+#define IDC_CHECK35 1060
+#define IDC_EDIT_TOTALENTITIES 1060
+#define IDC_EDIT_Y 1060
+#define IDC_SCALE_BOX 1061
+#define IDC_ROTY 1061
+#define IDC_CHECK36 1061
+#define IDC_EDIT_NET 1061
+#define IDC_EDIT_Z 1061
+#define IDC_E_VALUE_FIELD 1062
+#define IDC_CHECK37 1062
+#define IDC_CHECK38 1063
+#define IDC_E_LIST 1064
+#define IDC_CHECK39 1064
+#define IDC_E_COMMENT 1065
+#define IDC_CHECK40 1065
+#define IDC_CHECK41 1066
+#define IDC_E_PROPS 1067
+#define IDC_CHECK42 1067
+#define IDC_E_135 1068
+#define IDC_CHECK43 1068
+#define IDC_E_180 1069
+#define IDC_CHECK44 1069
+#define IDC_E_225 1070
+#define IDC_CHECK45 1070
+#define IDC_E_270 1071
+#define IDC_CHECK46 1071
+#define IDC_E_90 1072
+#define IDC_CHECK47 1072
+#define IDC_E_45 1073
+#define IDC_CHECK48 1073
+#define IDC_E_0 1074
+#define IDC_CHECK49 1074
+#define IDC_E_315 1075
+#define IDC_CHECK50 1075
+#define IDC_E_UP 1076
+#define IDC_CHECK51 1076
+#define IDC_E_DOWN 1077
+#define IDC_CHECK52 1077
+#define IDC_CHECK53 1078
+#define IDC_CHECK54 1079
+#define IDC_E_ADDPROP 1080
+#define IDC_CHECK55 1080
+#define IDC_E_DELPROP 1081
+#define IDC_CHECK56 1081
+#define IDC_E_CREATE 1082
+#define IDC_CHECK57 1082
+#define IDC_E_STATUS 1083
+#define IDC_CHECK58 1083
+#define IDC_CHECK59 1084
+#define IDC_CHECK60 1085
+#define IDC_CHECK61 1086
+#define IDC_CHECK62 1087
+#define IDC_CHECK63 1088
+#define IDC_CHECK64 1089
+#define IDC_SHIFT_BOX 1090
+#define IDC_HSHIFT 1090
+#define IDC_VSHIFT 1091
+#define IDC_ROTATEV 1092
+#define ID_BTN_CANCEL 1092
+#define IDC_HSTRETCH 1092
+#define IDC_SCALEV 1093
+#define IDC_EDIT_STATUSPOINTSIZE 1093
+#define IDC_VSTRETCH 1093
+#define IDC_SCALEH 1094
+#define IDC_EDIT_ROTATION 1094
+#define IDC_SHIFTV 1095
+#define IDC_HSHIFTA 1095
+#define IDC_STATIC_FIELD1 1095
+#define IDC_EDIT_UNDOLEVELS 1095
+#define IDC_SHIFTH 1096
+#define IDC_VSHIFTA 1097
+#define IDC_HSCALE 1098
+#define IDC_HSCALEA 1099
+#define IDC_VSCALE 1100
+#define IDC_EDIT_FIELD1 1100
+#define IDC_VSCALEA 1101
+#define IDC_STATIC_FIELD2 1101
+#define IDC_ROTATE 1102
+#define IDC_EDIT_FIELD2 1102
+#define IDC_SLIDER_CAMSPEED 1102
+#define IDC_G_EDIT 1103
+#define IDC_ROTATEA 1103
+#define IDC_STATIC_FIELD3 1103
+#define IDC_CHECK_CAMXYUPDATE 1103
+#define IDC_STATIC_KEY 1104
+#define IDC_FIND_BRUSH 1104
+#define IDC_EDIT_FIELD3 1104
+#define IDC_STATIC_VALUE 1105
+#define IDC_STATIC_FIELD4 1105
+#define IDC_E_KEY_FIELD 1106
+#define IDC_EDIT_FIELD4 1106
+#define IDC_FIND_ENTITY 1107
+#define IDC_STATIC_FIELD5 1107
+#define IDC_SIDES 1108
+#define IDC_EDIT_FIELD5 1108
+#define IDC_COMBO_WHATGAME 1108
+#define IDC_ROTX 1109
+#define IDC_BTN_COLOR 1109
+#define IDC_STATIC_COLOR 1110
+#define IDC_E_COLOR 1111
+#define IDC_ABOUT_GLVENDOR 1112
+#define IDC_ABOUT_GLVERSION 1113
+#define IDC_BTN_THECOLOR 1113
+#define IDC_ABOUT_GLRENDERER 1114
+#define IDC_STATIC_STUFF 1115
+#define IDC_TEXTURE 1116
+#define IDC_CHECK_ALTDRAG 1116
+#define IDC_PRJRSHCMD 1117
+#define IDC_SPIN_HSHIFT 1117
+#define IDC_CHECK_MOUSECHASE 1117
+#define IDC_PRJREMOTEBASE 1118
+#define IDC_SPIN_VSHIFT 1118
+#define IDC_CHECK_FACECOLOR 1118
+#define IDC_PRJENTITYPATH 1119
+#define IDC_SPIN_VSCALE 1119
+#define IDC_CHECK_NOCLAMP 1119
+#define IDC_PRJTEXPATH 1120
+#define IDC_SPIN_HSCALE 1120
+#define IDC_PRJAUTOSAVE 1121
+#define IDC_SPIN_ROTATE 1121
+#define IDC_ADDCMD 1122
+#define IDC_EDIT_ROTATEAMT 1122
+#define IDC_CMD_LIST 1123
+#define IDC_CHECK_DLLENTITIES 1123
+#define IDC_PRJBASEPATH 1124
+#define IDC_CHECK_WIDETOOLBAR 1124
+#define IDC_CMDCOMMAND 1125
+#define IDC_CHECK_BUGGYICD 1125
+#define IDC_CMDMENUTEXT 1126
+#define IDC_CHECK_SGIOPENGL 1126
+#define IDC_REMCMD 1127
+#define IDC_PRJINTERVAL 1128
+#define IDC_CHECK_HICOLOR 1128
+#define IDC_PRJMAPSPATH 1129
+#define IDC_CHECK_SHADERTEST 1129
+#define IDC_EDITCMD 1130
+#define IDC_CHECK_SHOWSHADERS 1130
+#define IDC_ABOUT_GLEXTENSIONS 1131
+#define IDC_LIST_TEXTURES 1132
+#define IDC_COMBO_WIDTH 1136
+#define IDC_COMBO_HEIGHT 1137
+#define IDC_BTN_PATCHDETAILS 1137
+#define IDC_BTN_PATCHRESET 1138
+#define IDC_BTN_PATCHNATURAL 1139
+#define IDC_RADIO_CAP 1139
+#define IDC_BTN_PATCHFIT 1140
+#define IDC_RADIO_CAP2 1140
+#define IDC_CHECK_SEAMS 1140
+#define IDC_RADIO_CAP3 1141
+#define IDC_EDIT_AMOUNT 1141
+#define IDC_RADIO_CAP4 1142
+#define IDC_BTN_ASSIGNSOUND 1142
+#define IDC_BTN_AXIAL 1142
+#define IDC_BTN_ASSIGNMODEL 1143
+#define IDC_BTN_FACEFIT 1143
+#define IDC_SLIDER_TEXTUREQUALITY 1144
+#define IDC_LIST1 1144
+#define IDC_BTN_BRUSHFIT 1144
+#define IDC_LIST_EVENTS 1144
+#define IDC_TREE1 1145
+#define IDC_COMBO_ROW 1147
+#define IDC_COMBO_COL 1148
+#define IDC_COMBO_TYPE 1149
+#define IDC_EDIT_WIDTH 1151
+#define IDC_CHECK_BPRIMIT 1151
+#define IDC_EDIT_HEIGHT 1152
+#define IDC_SPIN_WIDTH 1154
+#define IDC_SPIN_HEIGHT 1155
+#define IDC_COMBO_SHADERS 1157
+#define IDC_TREE_GROUP 1158
+#define IDC_CHECK_NOSTIPPLE 1159
+#define IDC_TAB_MODE 1159
+#define IDC_SLIDER_FALLOFF 1161
+#define IDC_CHECK_POINT 1162
+#define IDC_CHECK_EQUALRADIUS 1163
+#define IDC_RADIO_FALLOFF 1164
+#define IDC_CHECK_PROJECTED 1165
+#define IDC_CHECK_EXPLICITFALLOFF 1166
+#define IDC_EDIT_FALLOFF 1167
+#define IDC_STATIC_TEXTURE 1168
+#define IDC_CHECK_STROBE 1169
+#define IDC_EDIT_STROBE 1170
+#define IDC_CHECK_ROTATE 1171
+#define IDC_EDIT_ROTATE 1172
+#define IDC_BTN_FOG 1174
+#define IDC_CHECK_FOG 1175
+#define IDC_EDIT_ALPHA 1176
+#define IDC_CHECK_SHADOWS 1178
+#define IDC_CHECK_DIFFUSE 1179
+#define IDC_CHECK_SPECULAR 1180
+#define IDC_EDIT_RADIUSY 1184
+#define IDC_EDIT_RADIUSZ 1185
+#define IDC_EDIT_RADIUSX 1186
+#define IDC_EDIT_TARGETX 1187
+#define IDC_EDIT_TARGETY 1188
+#define IDC_EDIT_TARGETZ 1189
+#define IDC_EDIT_RIGHTX 1190
+#define IDC_EDIT_RIGHTY 1191
+#define IDC_EDIT_RIGHTZ 1192
+#define IDC_EDIT_UPX 1193
+#define IDC_EDIT_UPY 1194
+#define IDC_EDIT_UPZ 1195
+#define IDC_EDIT_STARTX 1196
+#define IDC_EDIT_STARTY 1197
+#define IDC_EDIT_STARTZ 1198
+#define IDC_EDIT_ENDX 1199
+#define IDC_EDIT_ENDY 1200
+#define IDC_EDIT_ENDZ 1201
+#define IDC_COMBO_TEXTURE 1203
+#define IDC_EDIT_MAPS 1205
+#define IDC_EDIT_CAM_NAME 1208
+#define IDC_COMBO_SPLINES 1209
+#define IDC_SCROLLBAR_SEGMENT 1210
+#define IDC_EDIT_LENGTH 1212
+#define IDC_EDIT_SEGMENT 1213
+#define IDC_BTN_ADDEVENT 1214
+#define IDC_BTN_DELEVENT 1215
+#define IDC_CHECK_TRACKCAMERA 1216
+#define IDC_RADIO_EVENT 1217
+#define IDC_EDIT_TOTALSEGMENTS 1217
+#define IDC_RADIO5 1218
+#define IDC_RADIO6 1219
+#define IDC_RADIO7 1220
+#define IDC_RADIO8 1221
+#define IDC_EDIT_PARAM 1222
+#define IDC_RADIO9 1223
+#define IDC_RADIO_FIXED 1223
+#define IDC_RADIO10 1224
+#define IDC_RADIO11 1225
+#define IDC_RADIO_EDITPOINTS 1225
+#define IDC_RADIO12 1226
+#define IDC_RADIO_EDITPOINTS2 1226
+#define IDC_BTN_DELETEPOINTS 1227
+#define IDC_EDIT_TYPE 1228
+#define IDC_BTN_SELECTALL 1229
+#define ID_ENTITY_START 22800
+#define ID_FILE_IMPORT 32771
+#define ID_VIEW_XY 32772
+#define ID_VIEW_SIDE 32773
+#define ID_VIEW_FRONT 32774
+#define ID_CAMERATOGGLE 32775
+#define ID_VIEW_CAMERATOGGLE 32776
+#define ID_BUTTON32777 32777
+#define ID_BUTTON32778 32778
+#define ID_TEXTURES_POPUP 32780
+#define ID_POPUP_SELECTION 32782
+#define ID_VIEW_CHANGE 32783
+#define ID_VIEW_CAMERAUPDATE 32784
+#define ID_VIEW_CLIPPER 32785
+#define ID_PREFS 32786
+#define ID_TOGGLE_LOCK 32787
+#define ID_EDIT_MAPINFO 32788
+#define ID_EDIT_ENTITYINFO 32789
+#define ID_BRUSH_SCRIPTS 32790
+#define ID_VIEW_NEXTVIEW 32791
+#define ID_HELP_COMMANDLIST 32792
+#define ID_FILE_NEWPROJECT 32793
+#define ID_MENUITEM32795 32795
+#define ID_SNAPTOGRID 32795
+#define ID_SPLIT_SELECTED 32823
+#define ID_CLIP_SELECTED 32824
+#define ID_FLIP_CLIP 32825
+#define ID_TOGGLEVIEW_YZ 32831
+#define ID_TOGGLEVIEW_XZ 32832
+#define ID_COLORS_GRIDTEXT 32833
+#define ID_COLORS_BRUSH 32834
+#define ID_COLORS_SELECTEDBRUSH 32835
+#define ID_COLORS_CLIPPER 32836
+#define ID_COLORS_GRIDBLOCK 32837
+#define ID_COLORS_VIEWNAME 32838
+#define ID_COLOR_SETORIGINAL 32839
+#define ID_COLOR_SETQER 32840
+#define ID_COLOR_SETBLACK 32841
+#define ID_BYEBYE 32842
+#define ID_SELECT_SCALE 32843
+#define ID_SELECT_MOUSEROTATE 32844
+#define ID_TEXTURE_REPLACESELECTED 32859
+#define ID_TEXTURE_REPLACEALL 32860
+#define ID_SELECT_MOUSESCALE 32866
+#define ID_SCALELOCKX 32867
+#define ID_SCALELOCKY 32868
+#define ID_SCALELOCKZ 32869
+#define ID_VIEW_CUBICCLIPPING 32870
+#define ID_FILE_PROJECTSETTINGS 32875
+#define ID_VIEW_CUBEOUT 32876
+#define ID_VIEW_CUBEIN 32877
+#define ID_NODES_LOADNODES 32878
+#define ID_NODES_SHOWNODES 32879
+#define ID_NODES_SHOWLINKS 32880
+#define ID_NODES_REMOVEALLNODES 32881
+#define ID_NODES_COUNTNODES 32882
+#define ID_NODES_GIVEMONEYTONELNO 32883
+#define ID_FILE_SAVEREGION 32887
+#define ID_FILE_LOADREGION 32888
+#define ID_SELECTION_MOVEDOWN 32890
+#define ID_TOOLBAR_MAIN 32891
+#define ID_SELECTION_MOVEUP 32892
+#define ID_TOOLBAR_TEXTURE 32892
+#define ID_BRUSH_MAKECONE 32896
+#define ID_TEXTURES_LOAD 32897
+#define ID_TOGGLE_ROTATELOCK 32898
+#define ID_CURVE_CYLINDER 32903
+#define ID_CURVE_ENDCAP 32904
+#define ID_CURVE_BEVEL 32905
+#define ID_CURVE_SPHERE 32906
+#define ID_CURVE_HEMISPHERE 32907
+#define ID_CURVE_QUARTER 32908
+#define ID_CURVE_EIGHTHSPHERE 32909
+#define ID_CURVE_INVERTCURVE 32910
+#define ID_FILE_IMPORTMAP 32911
+#define ID_FILE_EXPORTMAP 32912
+#define ID_EDIT_LOADPREFAB 32913
+#define ID_VIEW_SHOWCURVES 32914
+#define ID_SELECTION_SELECT_NUDGELEFT 32916
+#define ID_SELECTION_SELECT_NUDGERIGHT 32917
+#define ID_SELECTION_SELECT_NUDGEUP 32918
+#define ID_SELECTION_SELECT_NUDGEDOWN 32919
+#define ID_TEXTURES_LOADLIST 32920
+#define ID_DONTSELECTCURVE 32923
+#define ID_CONVERTCURVES 32924
+#define ID_DYNAMIC_LIGHTING 32925
+#define ID_PATCH_SHOWBOUNDINGBOX 32926
+#define ID_CURVE_SIMPLEPATCHMESH 32927
+#define ID_PATCH_WIREFRAME 32928
+#define ID_PATCH_WELD 32929
+#define ID_CURVE_PATCHTUBE 32930
+#define ID_CURVE_PATCHCONE 32931
+#define ID_CURVE_PATCHENDCAP 32932
+#define ID_CURVE_PATCHBEVEL 32933
+#define ID_CURVE_PATCHINVERTEDENDCAP 32934
+#define ID_CURVE_PATCHINVERTEDBEVEL 32935
+#define ID_PATCH_DRILLDOWN 32936
+#define ID_CURVE_LOADPATCHFILE 32937
+#define ID_CURVE_INSERTROW 32938
+#define ID_CURVE_INSERTCOLUMN 32939
+#define ID_CURVE_DELETEROW 32940
+#define ID_CURVE_DELETECOLUMN 32941
+#define ID_BUTTON32942 32942
+#define ID_PATCH_INSDEL 32942
+#define ID_CURVE_INSERT_ADDCOLUMN 32943
+#define ID_CURVE_INSERT_INSERTCOLUMN 32944
+#define ID_CURVE_INSERT_ADDROW 32945
+#define ID_CURVE_INSERT_INSERTROW 32946
+#define ID_CURVE_DELETE_FIRSTCOLUMN 32947
+#define ID_CURVE_DELETE_LASTCOLUMN 32948
+#define ID_CURVE_DELETE_FIRSTROW 32949
+#define ID_CURVE_DELETE_LASTROW 32950
+#define ID_CURVE_NEGATIVE 32951
+#define ID_PATCH_BEND 32952
+#define ID_CURVE_PATCHDENSETUBE 32955
+#define ID_CURVE_PATCHVERYDENSETUBE 32956
+#define ID_CURVE_CAP 32957
+#define ID_CURVE_CAP_INVERTEDBEVEL 32959
+#define ID_CURVE_CAP_INVERTEDENDCAP 32960
+#define ID_CURVE_REDISPERSE_ROWS 32961
+#define ID_CURVE_REDISPERSE_COLS 32962
+#define ID_PATCH_NATURALIZE 32963
+#define ID_CURVE_PATCHSQUARE 32964
+#define ID_BRUSH_PRIMITIVES_SPHERE 32965
+#define ID_BRUSH_PRIMITIVES_TORUS 32966
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_200 32967
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_100 32968
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_50 32969
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_25 32970
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_10 32971
+#define ID_CURVE_NEGATIVETEXTUREX 32972
+#define ID_TEXTURES_FLUSH 32973
+#define ID_CURVE_OVERLAY_SET 32974
+#define ID_CURVE_OVERLAY_CLEAR 32975
+#define ID_CURVE_NEGATIVETEXTUREY 32976
+#define ID_CURVE_THICKEN 32977
+#define ID_CURVE_CYCLECAP 32978
+#define ID_CURVE_MATRIX_TRANSPOSE 32981
+#define ID_PLUGINS_REFRESH 32982
+#define ID_TEXTURES_RELOADSHADERS 32983
+#define ID_VIEW_ENTITIESAS_BOUNDINGBOX 32984
+#define ID_VIEW_ENTITIESAS_WRITEFRAME 32985
+#define ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME 32986
+#define ID_VIEW_ENTITIESAS_SELECTEDSKINNED 32987
+#define ID_VIEW_ENTITIESAS_SKINNED 32988
+#define ID_VIEW_ENTITIESAS_SKINNEDANDBOXED 32989
+#define ID_SHOW_ENTITIES 32990
+#define ID_VIEW_ENTITIESAS_WIREFRAME 32991
+#define ID_VIEW_SHOWHINT 32993
+#define ID_VIEW_OPENGLLIGHTING 32998
+#define ID_VIEW_SHOWCAULK 32999
+#define ID_VIEW_SHOWANGLES 33000
+#define ID_EDIT_SAVEPREFAB 33001
+#define ID_CURVE_MOREENDCAPSBEVELS_SQUAREENDCAP 33002
+#define ID_CURVE_MOREENDCAPSBEVELS_SQUAREBEVEL 33003
+#define ID_CURVE_PRIMITIVES_SPHERE 33005
+#define ID_VIEW_HIDESHOW_HIDESELECTED 33006
+#define ID_VIEW_HIDESHOW_SHOWHIDDEN 33007
+#define ID_TEXTURES_SHADERS_SHOW 33008
+#define ID_SELECTION_CSGADD 33009
+#define ID_SELECTION_CSGMERGE 33011
+#define ID_TEXTURES_FLUSH_UNUSED 33014
+#define ID_DROP_GROUP_REMOVE 33016
+#define ID_DROP_GROUP_ADDTO_WORLD 33017
+#define ID_DROP_GROUP_NEWGROUP 33018
+#define ID_DROP_GROUP_NAME 33019
+#define ID_DROP_GROUP_ADDTO 33020
+#define ID_TERRAIN_CREATETERRAINFROMBRUSH 33022
+#define ID_TERRAIN_RAISELOWERTERRAIN 33023
+#define ID_SPLINES_MODE 33027
+#define ID_SPLINES_LOAD 33028
+#define ID_SPLINES_SAVE 33029
+#define ID_SPLINES_EDIT 33030
+#define ID_SPLINE_TEST 33031
+#define ID_POPUP_NEWCAMERA_INTERPOLATED 33034
+#define ID_POPUP_NEWCAMERA_SPLINE 33035
+#define ID_POPUP_NEWCAMERA_FIXED 33036
+#define ID_ENTITY_END 33500
+#define ID_PLUGIN_START 33800
+#define ID_PLUGIN_END 33999
+#define ID_FILE_EXIT 40002
+#define ID_FILE_SAVEAS 40004
+#define ID_VIEW_CENTER 40005
+#define ID_VIEW_UPFLOOR 40006
+#define ID_VIEW_DOWNFLOOR 40007
+#define ID_BRUSH_FLIPX 40008
+#define ID_BRUSH_FLIPY 40009
+#define ID_BRUSH_FLIPZ 40010
+#define ID_BRUSH_ROTATEX 40011
+#define ID_BRUSH_ROTATEY 40012
+#define ID_BRUSH_ROTATEZ 40013
+#define ID_BSP_FULLVIS 40016
+#define ID_BSP_FASTVIS 40017
+#define ID_BSP_NOVIS 40018
+#define ID_BSP_RELIGHT 40019
+#define ID_BSP_ENTITIES 40020
+#define ID_FILE_POINTFILE 40021
+#define ID_VIEW_100 40022
+#define ID_VIEW_75 40023
+#define ID_VIEW_50 40024
+#define ID_VIEW_25 40025
+#define ID_VIEW_12 40026
+#define ID_TEXTURES_SHOWALL 40033
+#define ID_TEXTURES_SHOWINUSE 40034
+#define ID_TEXTURES_TOGGLEVIEW 40037
+#define ID_SELECTION_CREATEENTITY 40039
+#define ID_SELECTION_EDITENTITY 40040
+#define ID_MISC_BENCHMARK 40041
+#define ID_REGION_OFF 40043
+#define ID_REGION_SETXY 40044
+#define ID_REGION_SETBRUSH 40045
+#define ID_SELECTION_MAKEHOLLOW 40046
+#define ID_SELECTION_SELECTPARTIALTALL 40047
+#define ID_SELECTION_SELECTCOMPLETETALL 40048
+#define ID_SELECTION_CSGSUBTRACT 40049
+#define ID_SELECTION_SELECTTOUCHING 40050
+#define ID_VIEW_NEAREST 40052
+#define ID_VIEW_NEARESTMIPMAP 40053
+#define ID_VIEW_LINEAR 40054
+#define ID_VIEW_BILINEAR 40055
+#define ID_VIEW_BILINEARMIPMAP 40056
+#define ID_VIEW_TRILINEAR 40057
+#define ID_TEXTURES_WIREFRAME 40058
+#define ID_TEXTURES_FLATSHADE 40059
+#define ID_VIEW_SHOWNAMES 40060
+#define ID_VIEW_ZOOMIN 40061
+#define ID_VIEW_ZOOMOUT 40062
+#define ID_VIEW_SHOWCOORDINATES 40063
+#define ID_VIEW_Z100 40064
+#define ID_VIEW_ZZOOMIN 40065
+#define ID_VIEW_ZZOOMOUT 40066
+#define ID_SELECTION_CLONE 40067
+#define ID_SELECTION_DESELECT 40068
+#define ID_SELECTION_DELETE 40069
+#define ID_BUTTON40068 40070
+#define ID_SELECTION_DRAGVERTECIES 40074
+#define ID_SELECTION_DRAGEDGES 40075
+#define ID_REGION_SETTALLBRUSH 40076
+#define ID_SELECTION_SELECTINSIDE 40092
+#define ID_PROJECT_RELEAD 40094
+#define ID_PROJECT_CHANGE 40095
+#define ID_MISC_GAMMA 40097
+#define ID_VIEW_SHOWENT 40098
+#define ID_VIEW_SHOWPATH 40099
+#define ID_VIEW_SHOWLIGHTS 40100
+#define ID_VIEW_SHOWCLIP 40101
+#define ID_VIEW_SHOWWATER 40102
+#define ID_VIEW_SHOWWORLD 40103
+#define ID_MISC_TEXTUREBACKGROUN 40104
+#define ID_TEXTUREBK 40105
+#define ID_COLORS_XYBK 40106
+#define ID_FILE_ABOUT 40107
+#define ID_VIEW_CONSOLE 40108
+#define ID_VIEW_ENTITY 40109
+#define ID_VIEW_TEXTURE 40110
+#define ID_COLORS_MAJOR 40111
+#define ID_COLORS_MINOR 40113
+#define ID_SELECTION_CONNECT 40114
+#define ID_FILE_LOADPROJECT 40115
+#define ID_MISC_FINDBRUSH 40116
+#define ID_MISC_NEXTLEAKSPOT 40117
+#define ID_MISC_PREVIOUSLEAKSPOT 40118
+#define ID_BRUSH_3SIDED 40119
+#define ID_BRUSH_4SIDED 40120
+#define ID_BRUSH_5SIDED 40121
+#define ID_BRUSH_6SIDED 40122
+#define ID_BRUSH_7SIDED 40123
+#define ID_BRUSH_8SIDED 40124
+#define ID_BRUSH_9SIDED 40125
+#define ID_SELECTION_ARBITRARYROTATION 40126
+#define ID_BRUSH_ARBITRARYSIDED 40127
+#define ID_SELECTION_UNGROUPENTITY 40130
+#define ID_MISC_SELECTENTITYCOLOR 40131
+#define ID_MISC_PRINTXY 40132
+#define ID_HELP_ABOUT 40134
+#define ID_EDIT_COPYBRUSH 40135
+#define ID_EDIT_PASTEBRUSH 40136
+#define ID_TEXTURES_INSPECTOR 40137
+#define ID_VIEW_SHOWDETAIL 40138
+#define ID_SELECTION_MAKE_DETAIL 40139
+#define ID_SELECTION_MAKE_STRUCTURAL 40140
+#define ID_REGION_SETSELECTION 40142
+#define ID_VIEW_SHOWBLOCKS 40143
+#define ID_GRID_1 40144
+#define ID_GRID_2 40145
+#define ID_GRID_4 40146
+#define ID_GRID_8 40147
+#define ID_GRID_16 40148
+#define ID_GRID_32 40149
+#define ID_GRID_64 40150
+#define ID_CAMERA_UP 40151
+#define ID_CAMERA_DOWN 40152
+#define ID_CAMERA_LEFT 40153
+#define ID_CAMERA_RIGHT 40155
+#define ID_CAMERA_FORWARD 40156
+#define ID_CAMERA_BACK 40157
+#define ID_CAMERA_ANGLEUP 40158
+#define ID_CAMERA_ANGLEDOWN 40159
+#define ID_CAMERA_STRAFELEFT 40160
+#define ID_CAMERA_STRAFERIGHT 40161
+#define ID_GRID_TOGGLE 40162
+#define ID_ENTITYLIST 40163
+#define ID_MAPINFO 40164
+#define ID_TOGGLECONSOLE 40165
+#define ID_TOGGLECAMERA 40166
+#define ID_TOGGLEZ 40167
+#define ID_TOGGLEVIEW 40168
+#define ID_SELECTION_TEXTURE_DEC 40169
+#define ID_SELECTION_TEXTURE_INC 40170
+#define ID_SELECTION_TEXTURE_FIT 40171
+#define ID_SELECTION_TEXTURE_ROTATECLOCK 40172
+#define ID_SELECTION_TEXTURE_ROTATECOUNTER 40173
+#define ID_SELECTION_TEXTURE_SCALEUP 40174
+#define ID_SELECTION_TEXTURE_SCALEDOWN 40175
+#define ID_SELECTION_TEXTURE_SHIFTLEFT 40176
+#define ID_SELECTION_TEXTURE_SHIFTRIGHT 40177
+#define ID_SELECTION_TEXTURE_SHIFTUP 40178
+#define ID_SELECTION_TEXTURE_SHIFTDOWN 40179
+#define ID_GRID_NEXT 40180
+#define ID_GRID_PREV 40181
+#define ID_SELECTION_TEXTURE_SCALELEFT 40182
+#define ID_SELECTION_TEXTURE_SCALERIGHT 40183
+#define ID_SELECTION_PRINT 40184
+#define ID_SELECTION_TOGGLESIZEPAINT 40185
+#define ID_PATCH_TAB 40186
+#define ID_PATCH_ENTER 40187
+#define ID_SELECT_SNAPTOGRID 40188
+#define ID_PATCH_INSPECTOR 40189
+#define ID_SELECT_ALL 40190
+#define ID_CURVE_FREEZE 40191
+#define ID_CURVE_UNFREEZE 40192
+#define ID_CURVE_UNFREEZEALL 40193
+#define ID_SELECT_RESELECT 40194
+#define ID_FITBRUSH 40195
+#define ID_FITFACE 40196
+#define ID_VIEW_CROSSHAIR 40197
+#define ID_SELECTION_INVERT 40198
+#define ID_VIEW_GROUPS 40199
+#define ID_SELECTION_NOOUTLINE 40200
+#define ID_SPLINES_POPUP 40201
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 192
+#define _APS_NEXT_COMMAND_VALUE 33024
+#define _APS_NEXT_CONTROL_VALUE 1160
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/q3radiant/splines/Splines.vcproj b/q3radiant/splines/Splines.vcproj
new file mode 100755
index 0000000..be579ae
--- /dev/null
+++ b/q3radiant/splines/Splines.vcproj
@@ -0,0 +1,296 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="Splines"
+ SccProjectName="&quot;$/source/q3radiant/splines&quot;, XINAAAAA"
+ SccLocalPath=".">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;Q3RADIANT"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/Splines.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\Splines.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;Q3RADIANT"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/Splines.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\Splines.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="math_angles.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="math_matrix.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="math_quaternion.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="math_vector.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="q_parse.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="q_shared.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="splines.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="util_str.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="math_angles.h">
+ </File>
+ <File
+ RelativePath="math_matrix.h">
+ </File>
+ <File
+ RelativePath="math_quaternion.h">
+ </File>
+ <File
+ RelativePath="math_vector.h">
+ </File>
+ <File
+ RelativePath="q_shared.h">
+ </File>
+ <File
+ RelativePath="splines.h">
+ </File>
+ <File
+ RelativePath="util_list.h">
+ </File>
+ <File
+ RelativePath="util_str.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/q3radiant/splines/math_angles.cpp b/q3radiant/splines/math_angles.cpp
new file mode 100755
index 0000000..0142d3d
--- /dev/null
+++ b/q3radiant/splines/math_angles.cpp
@@ -0,0 +1,150 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "q_shared.h"
+#include <float.h>
+
+angles_t ang_zero( 0.0f, 0.0f, 0.0f );
+
+void toAngles( mat3_t &src, angles_t &dst ) {
+ double theta;
+ double cp;
+ double sp;
+
+ sp = src[ 0 ][ 2 ];
+
+ // cap off our sin value so that we don't get any NANs
+ if ( sp > 1.0 ) {
+ sp = 1.0;
+ } else if ( sp < -1.0 ) {
+ sp = -1.0;
+ }
+
+ theta = -asin( sp );
+ cp = cos( theta );
+
+ if ( cp > 8192 * FLT_EPSILON ) {
+ dst.pitch = theta * 180 / M_PI;
+ dst.yaw = atan2( src[ 0 ][ 1 ], src[ 0 ][ 0 ] ) * 180 / M_PI;
+ dst.roll = atan2( src[ 1 ][ 2 ], src[ 2 ][ 2 ] ) * 180 / M_PI;
+ } else {
+ dst.pitch = theta * 180 / M_PI;
+ dst.yaw = -atan2( src[ 1 ][ 0 ], src[ 1 ][ 1 ] ) * 180 / M_PI;
+ dst.roll = 0;
+ }
+}
+
+void toAngles( quat_t &src, angles_t &dst ) {
+ mat3_t temp;
+
+ toMatrix( src, temp );
+ toAngles( temp, dst );
+}
+
+void toAngles( idVec3_t &src, angles_t &dst ) {
+ dst.pitch = src[ 0 ];
+ dst.yaw = src[ 1 ];
+ dst.roll = src[ 2 ];
+}
+
+void angles_t::toVectors( idVec3_t *forward, idVec3_t *right, idVec3_t *up ) {
+ float angle;
+ static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
+
+ angle = yaw * ( M_PI * 2 / 360 );
+ sy = sin( angle );
+ cy = cos( angle );
+
+ angle = pitch * ( M_PI * 2 / 360 );
+ sp = sin( angle );
+ cp = cos( angle );
+
+ angle = roll * ( M_PI * 2 / 360 );
+ sr = sin( angle );
+ cr = cos( angle );
+
+ if ( forward ) {
+ forward->set( cp * cy, cp * sy, -sp );
+ }
+
+ if ( right ) {
+ right->set( -sr * sp * cy + cr * sy, -sr * sp * sy + -cr * cy, -sr * cp );
+ }
+
+ if ( up ) {
+ up->set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
+ }
+}
+
+idVec3_t angles_t::toForward( void ) {
+ float angle;
+ static float sp, sy, cp, cy; // static to help MS compiler fp bugs
+
+ angle = yaw * ( M_PI * 2 / 360 );
+ sy = sin( angle );
+ cy = cos( angle );
+
+ angle = pitch * ( M_PI * 2 / 360 );
+ sp = sin( angle );
+ cp = cos( angle );
+
+ return idVec3_t( cp * cy, cp * sy, -sp );
+}
+
+/*
+=================
+Normalize360
+
+returns angles normalized to the range [0 <= angle < 360]
+=================
+*/
+angles_t& angles_t::Normalize360( void ) {
+ pitch = (360.0 / 65536) * ( ( int )( pitch * ( 65536 / 360.0 ) ) & 65535 );
+ yaw = (360.0 / 65536) * ( ( int )( yaw * ( 65536 / 360.0 ) ) & 65535 );
+ roll = (360.0 / 65536) * ( ( int )( roll * ( 65536 / 360.0 ) ) & 65535 );
+
+ return *this;
+}
+
+
+/*
+=================
+Normalize180
+
+returns angles normalized to the range [-180 < angle <= 180]
+=================
+*/
+angles_t& angles_t::Normalize180( void ) {
+ Normalize360();
+
+ if ( pitch > 180.0 ) {
+ pitch -= 360.0;
+ }
+
+ if ( yaw > 180.0 ) {
+ yaw -= 360.0;
+ }
+
+ if ( roll > 180.0 ) {
+ roll -= 360.0;
+ }
+ return *this;
+}
diff --git a/q3radiant/splines/math_angles.h b/q3radiant/splines/math_angles.h
new file mode 100755
index 0000000..7156e46
--- /dev/null
+++ b/q3radiant/splines/math_angles.h
@@ -0,0 +1,195 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __MATH_ANGLES_H__
+#define __MATH_ANGLES_H__
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "math_vector.h"
+
+class mat3_t;
+class quat_t;
+class idVec3_t;
+typedef idVec3_t &vec3_p;
+
+class angles_t {
+public:
+ float pitch;
+ float yaw;
+ float roll;
+
+ angles_t();
+ angles_t( float pitch, float yaw, float roll );
+ angles_t( const idVec3_t &vec );
+
+ friend void toAngles( idVec3_t &src, angles_t &dst );
+ friend void toAngles( quat_t &src, angles_t &dst );
+ friend void toAngles( mat3_t &src, angles_t &dst );
+
+ operator vec3_p();
+
+ float operator[]( int index ) const;
+ float& operator[]( int index );
+
+ void set( float pitch, float yaw, float roll );
+
+ void operator=( angles_t const &a );
+ void operator=( idVec3_t const &a );
+
+ friend angles_t operator+( const angles_t &a, const angles_t &b );
+ angles_t &operator+=( angles_t const &a );
+ angles_t &operator+=( idVec3_t const &a );
+
+ friend angles_t operator-( angles_t &a, angles_t &b );
+ angles_t &operator-=( angles_t &a );
+
+ friend angles_t operator*( const angles_t &a, float b );
+ friend angles_t operator*( float a, const angles_t &b );
+ angles_t &operator*=( float a );
+
+ friend int operator==( angles_t &a, angles_t &b );
+
+ friend int operator!=( angles_t &a, angles_t &b );
+
+ void toVectors( idVec3_t *forward, idVec3_t *right = NULL, idVec3_t *up = NULL );
+ idVec3_t toForward( void );
+
+ angles_t &Zero( void );
+
+ angles_t &Normalize360( void );
+ angles_t &Normalize180( void );
+};
+
+extern angles_t ang_zero;
+
+inline angles_t::angles_t() {}
+
+inline angles_t::angles_t( float pitch, float yaw, float roll ) {
+ this->pitch = pitch;
+ this->yaw = yaw;
+ this->roll = roll;
+}
+
+inline angles_t::angles_t( const idVec3_t &vec ) {
+ this->pitch = vec.x;
+ this->yaw = vec.y;
+ this->roll = vec.z;
+}
+
+inline float angles_t::operator[]( int index ) const {
+ assert( ( index >= 0 ) && ( index < 3 ) );
+ return ( &pitch )[ index ];
+}
+
+inline float& angles_t::operator[]( int index ) {
+ assert( ( index >= 0 ) && ( index < 3 ) );
+ return ( &pitch )[ index ];
+}
+
+inline angles_t::operator vec3_p( void ) {
+ return *( idVec3_t * )&pitch;
+}
+
+inline void angles_t::set( float pitch, float yaw, float roll ) {
+ this->pitch = pitch;
+ this->yaw = yaw;
+ this->roll = roll;
+}
+
+inline void angles_t::operator=( angles_t const &a ) {
+ pitch = a.pitch;
+ yaw = a.yaw;
+ roll = a.roll;
+}
+
+inline void angles_t::operator=( idVec3_t const &a ) {
+ pitch = a[ 0 ];
+ yaw = a[ 1 ];
+ roll = a[ 2 ];
+}
+
+inline angles_t operator+( const angles_t &a, const angles_t &b ) {
+ return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll );
+}
+
+inline angles_t& angles_t::operator+=( angles_t const &a ) {
+ pitch += a.pitch;
+ yaw += a.yaw;
+ roll += a.roll;
+
+ return *this;
+}
+
+inline angles_t& angles_t::operator+=( idVec3_t const &a ) {
+ pitch += a.x;
+ yaw += a.y;
+ roll += a.z;
+
+ return *this;
+}
+
+inline angles_t operator-( angles_t &a, angles_t &b ) {
+ return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll );
+}
+
+inline angles_t& angles_t::operator-=( angles_t &a ) {
+ pitch -= a.pitch;
+ yaw -= a.yaw;
+ roll -= a.roll;
+
+ return *this;
+}
+
+inline angles_t operator*( const angles_t &a, float b ) {
+ return angles_t( a.pitch * b, a.yaw * b, a.roll * b );
+}
+
+inline angles_t operator*( float a, const angles_t &b ) {
+ return angles_t( a * b.pitch, a * b.yaw, a * b.roll );
+}
+
+inline angles_t& angles_t::operator*=( float a ) {
+ pitch *= a;
+ yaw *= a;
+ roll *= a;
+
+ return *this;
+}
+
+inline int operator==( angles_t &a, angles_t &b ) {
+ return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) );
+}
+
+inline int operator!=( angles_t &a, angles_t &b ) {
+ return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) );
+}
+
+inline angles_t& angles_t::Zero( void ) {
+ pitch = 0.0f;
+ yaw = 0.0f;
+ roll = 0.0f;
+
+ return *this;
+}
+
+#endif /* !__MATH_ANGLES_H__ */
diff --git a/q3radiant/splines/math_matrix.cpp b/q3radiant/splines/math_matrix.cpp
new file mode 100755
index 0000000..24ae914
--- /dev/null
+++ b/q3radiant/splines/math_matrix.cpp
@@ -0,0 +1,134 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "q_shared.h"
+
+mat3_t mat3_default( idVec3_t( 1, 0, 0 ), idVec3_t( 0, 1, 0 ), idVec3_t( 0, 0, 1 ) );
+
+void toMatrix( quat_t const &src, mat3_t &dst ) {
+ float wx, wy, wz;
+ float xx, yy, yz;
+ float xy, xz, zz;
+ float x2, y2, z2;
+
+ x2 = src.x + src.x;
+ y2 = src.y + src.y;
+ z2 = src.z + src.z;
+
+ xx = src.x * x2;
+ xy = src.x * y2;
+ xz = src.x * z2;
+
+ yy = src.y * y2;
+ yz = src.y * z2;
+ zz = src.z * z2;
+
+ wx = src.w * x2;
+ wy = src.w * y2;
+ wz = src.w * z2;
+
+ dst[ 0 ][ 0 ] = 1.0f - ( yy + zz );
+ dst[ 0 ][ 1 ] = xy - wz;
+ dst[ 0 ][ 2 ] = xz + wy;
+
+ dst[ 1 ][ 0 ] = xy + wz;
+ dst[ 1 ][ 1 ] = 1.0f - ( xx + zz );
+ dst[ 1 ][ 2 ] = yz - wx;
+
+ dst[ 2 ][ 0 ] = xz - wy;
+ dst[ 2 ][ 1 ] = yz + wx;
+ dst[ 2 ][ 2 ] = 1.0f - ( xx + yy );
+}
+
+void toMatrix( angles_t const &src, mat3_t &dst ) {
+ float angle;
+ static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
+
+ angle = src.yaw * ( M_PI * 2.0f / 360.0f );
+ sy = sin( angle );
+ cy = cos( angle );
+
+ angle = src.pitch * ( M_PI * 2.0f / 360.0f );
+ sp = sin( angle );
+ cp = cos( angle );
+
+ angle = src.roll * ( M_PI * 2.0f / 360.0f );
+ sr = sin( angle );
+ cr = cos( angle );
+
+ dst[ 0 ].set( cp * cy, cp * sy, -sp );
+ dst[ 1 ].set( sr * sp * cy + cr * -sy, sr * sp * sy + cr * cy, sr * cp );
+ dst[ 2 ].set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
+}
+
+void toMatrix( idVec3_t const &src, mat3_t &dst ) {
+ angles_t sup = src;
+ toMatrix(sup, dst);
+}
+
+void mat3_t::ProjectVector( const idVec3_t &src, idVec3_t &dst ) const {
+ dst.x = src * mat[ 0 ];
+ dst.y = src * mat[ 1 ];
+ dst.z = src * mat[ 2 ];
+}
+
+void mat3_t::UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const {
+ dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z;
+}
+
+void mat3_t::Transpose( mat3_t &matrix ) {
+ int i;
+ int j;
+
+ for( i = 0; i < 3; i++ ) {
+ for( j = 0; j < 3; j++ ) {
+ matrix[ i ][ j ] = mat[ j ][ i ];
+ }
+ }
+}
+
+void mat3_t::Transpose( void ) {
+ float temp;
+ int i;
+ int j;
+
+ for( i = 0; i < 3; i++ ) {
+ for( j = i + 1; j < 3; j++ ) {
+ temp = mat[ i ][ j ];
+ mat[ i ][ j ] = mat[ j ][ i ];
+ mat[ j ][ i ] = temp;
+ }
+ }
+}
+
+mat3_t mat3_t::Inverse( void ) const {
+ mat3_t inv( *this );
+
+ inv.Transpose();
+
+ return inv;
+}
+
+void mat3_t::Clear( void ) {
+ mat[0].set( 1, 0, 0 );
+ mat[1].set( 0, 1, 0 );
+ mat[2].set( 0, 0, 1 );
+}
diff --git a/q3radiant/splines/math_matrix.h b/q3radiant/splines/math_matrix.h
new file mode 100755
index 0000000..ed1da0d
--- /dev/null
+++ b/q3radiant/splines/math_matrix.h
@@ -0,0 +1,223 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __MATH_MATRIX_H__
+#define __MATH_MATRIX_H__
+
+#include <string.h>
+#include "math_vector.h"
+
+#ifndef ID_INLINE
+#ifdef _WIN32
+#define ID_INLINE __inline
+#else
+#define ID_INLINE inline
+#endif
+#endif
+
+class quat_t;
+class angles_t;
+
+class mat3_t {
+public:
+ idVec3_t mat[ 3 ];
+
+ mat3_t();
+ mat3_t( float src[ 3 ][ 3 ] );
+ mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z );
+ mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz );
+
+ friend void toMatrix( quat_t const &src, mat3_t &dst );
+ friend void toMatrix( angles_t const &src, mat3_t &dst );
+ friend void toMatrix( idVec3_t const &src, mat3_t &dst );
+
+ idVec3_t operator[]( int index ) const;
+ idVec3_t &operator[]( int index );
+
+ idVec3_t operator*( const idVec3_t &vec ) const;
+ mat3_t operator*( const mat3_t &a ) const;
+ mat3_t operator*( float a ) const;
+ mat3_t operator+( mat3_t const &a ) const;
+ mat3_t operator-( mat3_t const &a ) const;
+
+ friend idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat );
+ friend mat3_t operator*( float a, mat3_t const &b );
+
+ mat3_t &operator*=( float a );
+ mat3_t &operator+=( mat3_t const &a );
+ mat3_t &operator-=( mat3_t const &a );
+
+ void Clear( void );
+
+ void ProjectVector( const idVec3_t &src, idVec3_t &dst ) const;
+ void UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const;
+
+ void OrthoNormalize( void );
+ void Transpose( mat3_t &matrix );
+ void Transpose( void );
+ mat3_t Inverse( void ) const;
+ void Identity( void );
+
+ friend void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst );
+ friend mat3_t SkewSymmetric( idVec3_t const &src );
+};
+
+ID_INLINE mat3_t::mat3_t() {
+}
+
+ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
+ memcpy( mat, src, sizeof( src ) );
+}
+
+ID_INLINE mat3_t::mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z ) {
+ mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z;
+ mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z;
+ mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z;
+}
+
+ID_INLINE mat3_t::mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) {
+ mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz;
+ mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz;
+ mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz;
+}
+
+ID_INLINE idVec3_t mat3_t::operator[]( int index ) const {
+ assert( ( index >= 0 ) && ( index < 3 ) );
+ return mat[ index ];
+}
+
+ID_INLINE idVec3_t& mat3_t::operator[]( int index ) {
+ assert( ( index >= 0 ) && ( index < 3 ) );
+ return mat[ index ];
+}
+
+ID_INLINE idVec3_t mat3_t::operator*( const idVec3_t &vec ) const {
+ return idVec3_t(
+ mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
+ mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
+ mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
+}
+
+ID_INLINE mat3_t mat3_t::operator*( const mat3_t &a ) const {
+ return mat3_t(
+ mat[0].x * a[0].x + mat[0].y * a[1].x + mat[0].z * a[2].x,
+ mat[0].x * a[0].y + mat[0].y * a[1].y + mat[0].z * a[2].y,
+ mat[0].x * a[0].z + mat[0].y * a[1].z + mat[0].z * a[2].z,
+ mat[1].x * a[0].x + mat[1].y * a[1].x + mat[1].z * a[2].x,
+ mat[1].x * a[0].y + mat[1].y * a[1].y + mat[1].z * a[2].y,
+ mat[1].x * a[0].z + mat[1].y * a[1].z + mat[1].z * a[2].z,
+ mat[2].x * a[0].x + mat[2].y * a[1].x + mat[2].z * a[2].x,
+ mat[2].x * a[0].y + mat[2].y * a[1].y + mat[2].z * a[2].y,
+ mat[2].x * a[0].z + mat[2].y * a[1].z + mat[2].z * a[2].z );
+}
+
+ID_INLINE mat3_t mat3_t::operator*( float a ) const {
+ return mat3_t(
+ mat[0].x * a, mat[0].y * a, mat[0].z * a,
+ mat[1].x * a, mat[1].y * a, mat[1].z * a,
+ mat[2].x * a, mat[2].y * a, mat[2].z * a );
+}
+
+ID_INLINE mat3_t mat3_t::operator+( mat3_t const &a ) const {
+ return mat3_t(
+ mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z,
+ mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z,
+ mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z );
+}
+
+ID_INLINE mat3_t mat3_t::operator-( mat3_t const &a ) const {
+ return mat3_t(
+ mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z,
+ mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z,
+ mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z );
+}
+
+ID_INLINE idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat ) {
+ return idVec3_t(
+ mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
+ mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
+ mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
+}
+
+ID_INLINE mat3_t operator*( float a, mat3_t const &b ) {
+ return mat3_t(
+ b[0].x * a, b[0].y * a, b[0].z * a,
+ b[1].x * a, b[1].y * a, b[1].z * a,
+ b[2].x * a, b[2].y * a, b[2].z * a );
+}
+
+ID_INLINE mat3_t &mat3_t::operator*=( float a ) {
+ mat[0].x *= a; mat[0].y *= a; mat[0].z *= a;
+ mat[1].x *= a; mat[1].y *= a; mat[1].z *= a;
+ mat[2].x *= a; mat[2].y *= a; mat[2].z *= a;
+
+ return *this;
+}
+
+ID_INLINE mat3_t &mat3_t::operator+=( mat3_t const &a ) {
+ mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z;
+ mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z;
+ mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z;
+
+ return *this;
+}
+
+ID_INLINE mat3_t &mat3_t::operator-=( mat3_t const &a ) {
+ mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z;
+ mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z;
+ mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z;
+
+ return *this;
+}
+
+ID_INLINE void mat3_t::OrthoNormalize( void ) {
+ mat[ 0 ].Normalize();
+ mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
+ mat[ 2 ].Normalize();
+ mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
+ mat[ 1 ].Normalize();
+}
+
+ID_INLINE void mat3_t::Identity( void ) {
+ mat[ 0 ].x = 1.f; mat[ 0 ].y = 0.f; mat[ 0 ].z = 0.f;
+ mat[ 1 ].x = 0.f; mat[ 1 ].y = 1.f; mat[ 1 ].z = 0.f;
+ mat[ 2 ].x = 0.f; mat[ 2 ].y = 0.f; mat[ 2 ].z = 1.f;
+}
+
+ID_INLINE void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ) {
+ dst[0].x = inv[0].x * b[0].x + inv[1].x * b[1].x + inv[2].x * b[2].x;
+ dst[0].y = inv[0].x * b[0].y + inv[1].x * b[1].y + inv[2].x * b[2].y;
+ dst[0].z = inv[0].x * b[0].z + inv[1].x * b[1].z + inv[2].x * b[2].z;
+ dst[1].x = inv[0].y * b[0].x + inv[1].y * b[1].x + inv[2].y * b[2].x;
+ dst[1].y = inv[0].y * b[0].y + inv[1].y * b[1].y + inv[2].y * b[2].y;
+ dst[1].z = inv[0].y * b[0].z + inv[1].y * b[1].z + inv[2].y * b[2].z;
+ dst[2].x = inv[0].z * b[0].x + inv[1].z * b[1].x + inv[2].z * b[2].x;
+ dst[2].y = inv[0].z * b[0].y + inv[1].z * b[1].y + inv[2].z * b[2].y;
+ dst[2].z = inv[0].z * b[0].z + inv[1].z * b[1].z + inv[2].z * b[2].z;
+}
+
+ID_INLINE mat3_t SkewSymmetric( idVec3_t const &src ) {
+ return mat3_t( 0.0f, -src.z, src.y, src.z, 0.0f, -src.x, -src.y, src.x, 0.0f );
+}
+
+extern mat3_t mat3_default;
+
+#endif /* !__MATH_MATRIX_H__ */
diff --git a/q3radiant/splines/math_quaternion.cpp b/q3radiant/splines/math_quaternion.cpp
new file mode 100755
index 0000000..4ef670e
--- /dev/null
+++ b/q3radiant/splines/math_quaternion.cpp
@@ -0,0 +1,78 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#include "math_quaternion.h"
+#include "math_matrix.h"
+
+void toQuat( idVec3_t &src, quat_t &dst ) {
+ dst.x = src.x;
+ dst.y = src.y;
+ dst.z = src.z;
+ dst.w = 0.0f;
+}
+
+void toQuat( angles_t &src, quat_t &dst ) {
+ mat3_t temp;
+
+ toMatrix( src, temp );
+ toQuat( temp, dst );
+}
+
+void toQuat( mat3_t &src, quat_t &dst ) {
+ float trace;
+ float s;
+ int i;
+ int j;
+ int k;
+
+ static int next[ 3 ] = { 1, 2, 0 };
+
+ trace = src[ 0 ][ 0 ] + src[ 1 ][ 1 ] + src[ 2 ][ 2 ];
+ if ( trace > 0.0f ) {
+ s = ( float )sqrt( trace + 1.0f );
+ dst.w = s * 0.5f;
+ s = 0.5f / s;
+
+ dst.x = ( src[ 2 ][ 1 ] - src[ 1 ][ 2 ] ) * s;
+ dst.y = ( src[ 0 ][ 2 ] - src[ 2 ][ 0 ] ) * s;
+ dst.z = ( src[ 1 ][ 0 ] - src[ 0 ][ 1 ] ) * s;
+ } else {
+ i = 0;
+ if ( src[ 1 ][ 1 ] > src[ 0 ][ 0 ] ) {
+ i = 1;
+ }
+ if ( src[ 2 ][ 2 ] > src[ i ][ i ] ) {
+ i = 2;
+ }
+
+ j = next[ i ];
+ k = next[ j ];
+
+ s = ( float )sqrt( ( src[ i ][ i ] - ( src[ j ][ j ] + src[ k ][ k ] ) ) + 1.0f );
+ dst[ i ] = s * 0.5f;
+
+ s = 0.5f / s;
+
+ dst.w = ( src[ k ][ j ] - src[ j ][ k ] ) * s;
+ dst[ j ] = ( src[ j ][ i ] + src[ i ][ j ] ) * s;
+ dst[ k ] = ( src[ k ][ i ] + src[ i ][ k ] ) * s;
+ }
+}
diff --git a/q3radiant/splines/math_quaternion.h b/q3radiant/splines/math_quaternion.h
new file mode 100755
index 0000000..74ae2ac
--- /dev/null
+++ b/q3radiant/splines/math_quaternion.h
@@ -0,0 +1,190 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __MATH_QUATERNION_H__
+#define __MATH_QUATERNION_H__
+
+#include <assert.h>
+#include <math.h>
+
+class idVec3_t;
+class angles_t;
+class mat3_t;
+
+class quat_t {
+public:
+ float x;
+ float y;
+ float z;
+ float w;
+
+ quat_t();
+ quat_t( float x, float y, float z, float w );
+
+ friend void toQuat( idVec3_t &src, quat_t &dst );
+ friend void toQuat( angles_t &src, quat_t &dst );
+ friend void toQuat( mat3_t &src, quat_t &dst );
+
+ float *vec4( void );
+
+ float operator[]( int index ) const;
+ float &operator[]( int index );
+
+ void set( float x, float y, float z, float w );
+
+ void operator=( quat_t a );
+
+ friend quat_t operator+( quat_t a, quat_t b );
+ quat_t &operator+=( quat_t a );
+
+ friend quat_t operator-( quat_t a, quat_t b );
+ quat_t &operator-=( quat_t a );
+
+ friend quat_t operator*( quat_t a, float b );
+ friend quat_t operator*( float a, quat_t b );
+ quat_t &operator*=( float a );
+
+ friend int operator==( quat_t a, quat_t b );
+ friend int operator!=( quat_t a, quat_t b );
+
+ float Length( void );
+ quat_t &Normalize( void );
+
+ quat_t operator-();
+};
+
+inline quat_t::quat_t() {
+}
+
+inline quat_t::quat_t( float x, float y, float z, float w ) {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->w = w;
+}
+
+inline float *quat_t::vec4( void ) {
+ return &x;
+}
+
+inline float quat_t::operator[]( int index ) const {
+ assert( ( index >= 0 ) && ( index < 4 ) );
+ return ( &x )[ index ];
+}
+
+inline float& quat_t::operator[]( int index ) {
+ assert( ( index >= 0 ) && ( index < 4 ) );
+ return ( &x )[ index ];
+}
+
+inline void quat_t::set( float x, float y, float z, float w ) {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->w = w;
+}
+
+inline void quat_t::operator=( quat_t a ) {
+ x = a.x;
+ y = a.y;
+ z = a.z;
+ w = a.w;
+}
+
+inline quat_t operator+( quat_t a, quat_t b ) {
+ return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
+}
+
+inline quat_t& quat_t::operator+=( quat_t a ) {
+ x += a.x;
+ y += a.y;
+ z += a.z;
+ w += a.w;
+
+ return *this;
+}
+
+inline quat_t operator-( quat_t a, quat_t b ) {
+ return quat_t( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w );
+}
+
+inline quat_t& quat_t::operator-=( quat_t a ) {
+ x -= a.x;
+ y -= a.y;
+ z -= a.z;
+ w -= a.w;
+
+ return *this;
+}
+
+inline quat_t operator*( quat_t a, float b ) {
+ return quat_t( a.x * b, a.y * b, a.z * b, a.w * b );
+}
+
+inline quat_t operator*( float a, quat_t b ) {
+ return b * a;
+}
+
+inline quat_t& quat_t::operator*=( float a ) {
+ x *= a;
+ y *= a;
+ z *= a;
+ w *= a;
+
+ return *this;
+}
+
+inline int operator==( quat_t a, quat_t b ) {
+ return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) );
+}
+
+inline int operator!=( quat_t a, quat_t b ) {
+ return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) );
+}
+
+inline float quat_t::Length( void ) {
+ float length;
+
+ length = x * x + y * y + z * z + w * w;
+ return ( float )sqrt( length );
+}
+
+inline quat_t& quat_t::Normalize( void ) {
+ float length;
+ float ilength;
+
+ length = this->Length();
+ if ( length ) {
+ ilength = 1 / length;
+ x *= ilength;
+ y *= ilength;
+ z *= ilength;
+ w *= ilength;
+ }
+
+ return *this;
+}
+
+inline quat_t quat_t::operator-() {
+ return quat_t( -x, -y, -z, -w );
+}
+
+#endif /* !__MATH_QUATERNION_H__ */
diff --git a/q3radiant/splines/math_vector.cpp b/q3radiant/splines/math_vector.cpp
new file mode 100755
index 0000000..120258c
--- /dev/null
+++ b/q3radiant/splines/math_vector.cpp
@@ -0,0 +1,144 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//#include "../game/q_shared.h"
+#include "math_vector.h"
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+
+#define LERP_DELTA 1e-6
+
+idVec3_t vec_zero( 0.0f, 0.0f, 0.0f );
+
+Bounds boundsZero;
+
+float idVec3_t::toYaw( void ) {
+ float yaw;
+
+ if ( ( y == 0 ) && ( x == 0 ) ) {
+ yaw = 0;
+ } else {
+ yaw = atan2( y, x ) * 180 / M_PI;
+ if ( yaw < 0 ) {
+ yaw += 360;
+ }
+ }
+
+ return yaw;
+}
+
+float idVec3_t::toPitch( void ) {
+ float forward;
+ float pitch;
+
+ if ( ( x == 0 ) && ( y == 0 ) ) {
+ if ( z > 0 ) {
+ pitch = 90;
+ } else {
+ pitch = 270;
+ }
+ } else {
+ forward = ( float )idSqrt( x * x + y * y );
+ pitch = atan2( z, forward ) * 180 / M_PI;
+ if ( pitch < 0 ) {
+ pitch += 360;
+ }
+ }
+
+ return pitch;
+}
+
+/*
+angles_t idVec3_t::toAngles( void ) {
+ float forward;
+ float yaw;
+ float pitch;
+
+ if ( ( x == 0 ) && ( y == 0 ) ) {
+ yaw = 0;
+ if ( z > 0 ) {
+ pitch = 90;
+ } else {
+ pitch = 270;
+ }
+ } else {
+ yaw = atan2( y, x ) * 180 / M_PI;
+ if ( yaw < 0 ) {
+ yaw += 360;
+ }
+
+ forward = ( float )idSqrt( x * x + y * y );
+ pitch = atan2( z, forward ) * 180 / M_PI;
+ if ( pitch < 0 ) {
+ pitch += 360;
+ }
+ }
+
+ return angles_t( -pitch, yaw, 0 );
+}
+*/
+
+idVec3_t LerpVector( idVec3_t &w1, idVec3_t &w2, const float t ) {
+ float omega, cosom, sinom, scale0, scale1;
+
+ cosom = w1 * w2;
+ if ( ( 1.0 - cosom ) > LERP_DELTA ) {
+ omega = acos( cosom );
+ sinom = sin( omega );
+ scale0 = sin( ( 1.0 - t ) * omega ) / sinom;
+ scale1 = sin( t * omega ) / sinom;
+ } else {
+ scale0 = 1.0 - t;
+ scale1 = t;
+ }
+
+ return ( w1 * scale0 + w2 * scale1 );
+}
+
+/*
+=============
+idVec3_t::string
+
+This is just a convenience function
+for printing vectors
+=============
+*/
+char *idVec3_t::string( void ) {
+ static int index = 0;
+ static char str[ 8 ][ 36 ];
+ char *s;
+
+ // use an array so that multiple toString's won't collide
+ s = str[ index ];
+ index = (index + 1)&7;
+
+ sprintf( s, "%.2f %.2f %.2f", x, y, z );
+
+ return s;
+}
diff --git a/q3radiant/splines/math_vector.h b/q3radiant/splines/math_vector.h
new file mode 100755
index 0000000..8afc541
--- /dev/null
+++ b/q3radiant/splines/math_vector.h
@@ -0,0 +1,572 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __MATH_VECTOR_H__
+#define __MATH_VECTOR_H__
+
+#pragma warning(disable : 4244)
+
+#include <math.h>
+#include <assert.h>
+
+//#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+//#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+//#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+//#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
+
+//#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
+#define __VectorMA(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
+//#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+
+#define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
+#define VectorSubtract4(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
+#define VectorAdd4(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
+#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+#define VectorScale4(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
+#define VectorMA4(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
+
+
+//#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
+#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
+//#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
+#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+
+#define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
+
+
+//#include "util_heap.h"
+
+#ifndef EQUAL_EPSILON
+#define EQUAL_EPSILON 0.001
+#endif
+
+float Q_fabs( float f );
+
+#ifndef ID_INLINE
+#ifdef _WIN32
+#define ID_INLINE __inline
+#else
+#define ID_INLINE inline
+#endif
+#endif
+
+// if this is defined, vec3 will take four elements, which may allow
+// easier SIMD optimizations
+//#define FAT_VEC3
+//#ifdef __ppc__
+//#pragma align(16)
+//#endif
+
+class angles_t;
+#ifdef __ppc__
+// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
+// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson
+// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost.
+// We'll then multiply 1/sqrt times the original value to get the sqrt.
+// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive)
+// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments).
+
+static inline float idSqrt(float x) {
+ const float half = 0.5;
+ const float one = 1.0;
+ float B, y0, y1;
+
+ // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
+ if (fabs(x) == 0.0)
+ return x;
+ B = x;
+
+#ifdef __GNUC__
+ asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
+#else
+ y0 = __frsqrte(B);
+#endif
+ /* First refinement step */
+
+ y1 = y0 + half*y0*(one - B*y0*y0);
+
+ /* Second refinement step -- copy the output of the last step to the input of this step */
+
+ y0 = y1;
+ y1 = y0 + half*y0*(one - B*y0*y0);
+
+ /* Get sqrt(x) from x * 1/sqrt(x) */
+ return x * y1;
+}
+#else
+static inline double idSqrt(double x) {
+ return sqrt(x);
+}
+#endif
+
+
+//class idVec3_t : public idHeap<idVec3_t> {
+class idVec3_t {
+public:
+#ifndef FAT_VEC3
+ float x,y,z;
+#else
+ float x,y,z,dist;
+#endif
+
+#ifndef FAT_VEC3
+ idVec3_t() {};
+#else
+ idVec3_t() {dist = 0.0f;};
+#endif
+ idVec3_t( const float x, const float y, const float z );
+
+ operator float *();
+
+ float operator[]( const int index ) const;
+ float &operator[]( const int index );
+
+ void set( const float x, const float y, const float z );
+
+ idVec3_t operator-() const;
+
+ idVec3_t &operator=( const idVec3_t &a );
+
+ float operator*( const idVec3_t &a ) const;
+ idVec3_t operator*( const float a ) const;
+ friend idVec3_t operator*( float a, idVec3_t b );
+
+ idVec3_t operator+( const idVec3_t &a ) const;
+ idVec3_t operator-( const idVec3_t &a ) const;
+
+ idVec3_t &operator+=( const idVec3_t &a );
+ idVec3_t &operator-=( const idVec3_t &a );
+ idVec3_t &operator*=( const float a );
+
+ int operator==( const idVec3_t &a ) const;
+ int operator!=( const idVec3_t &a ) const;
+
+ idVec3_t Cross( const idVec3_t &a ) const;
+ idVec3_t &Cross( const idVec3_t &a, const idVec3_t &b );
+
+ float Length( void ) const;
+ float Normalize( void );
+
+ void Zero( void );
+ void Snap( void );
+ void SnapTowards( const idVec3_t &to );
+
+ float toYaw( void );
+ float toPitch( void );
+ angles_t toAngles( void );
+ friend idVec3_t LerpVector( const idVec3_t &w1, const idVec3_t &w2, const float t );
+
+ char *string( void );
+};
+
+extern idVec3_t vec_zero;
+
+ID_INLINE idVec3_t::idVec3_t( const float x, const float y, const float z ) {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+#ifdef FAT_VEC3
+ this->dist = 0.0f;
+#endif
+}
+
+ID_INLINE float idVec3_t::operator[]( const int index ) const {
+ return ( &x )[ index ];
+}
+
+ID_INLINE float &idVec3_t::operator[]( const int index ) {
+ return ( &x )[ index ];
+}
+
+ID_INLINE idVec3_t::operator float *( void ) {
+ return &x;
+}
+
+ID_INLINE idVec3_t idVec3_t::operator-() const {
+ return idVec3_t( -x, -y, -z );
+}
+
+ID_INLINE idVec3_t &idVec3_t::operator=( const idVec3_t &a ) {
+ x = a.x;
+ y = a.y;
+ z = a.z;
+
+ return *this;
+}
+
+ID_INLINE void idVec3_t::set( const float x, const float y, const float z ) {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+}
+
+ID_INLINE idVec3_t idVec3_t::operator-( const idVec3_t &a ) const {
+ return idVec3_t( x - a.x, y - a.y, z - a.z );
+}
+
+ID_INLINE float idVec3_t::operator*( const idVec3_t &a ) const {
+ return x * a.x + y * a.y + z * a.z;
+}
+
+ID_INLINE idVec3_t idVec3_t::operator*( const float a ) const {
+ return idVec3_t( x * a, y * a, z * a );
+}
+
+ID_INLINE idVec3_t operator*( const float a, const idVec3_t b ) {
+ return idVec3_t( b.x * a, b.y * a, b.z * a );
+}
+
+ID_INLINE idVec3_t idVec3_t::operator+( const idVec3_t &a ) const {
+ return idVec3_t( x + a.x, y + a.y, z + a.z );
+}
+
+ID_INLINE idVec3_t &idVec3_t::operator+=( const idVec3_t &a ) {
+ x += a.x;
+ y += a.y;
+ z += a.z;
+
+ return *this;
+}
+
+ID_INLINE idVec3_t &idVec3_t::operator-=( const idVec3_t &a ) {
+ x -= a.x;
+ y -= a.y;
+ z -= a.z;
+
+ return *this;
+}
+
+ID_INLINE idVec3_t &idVec3_t::operator*=( const float a ) {
+ x *= a;
+ y *= a;
+ z *= a;
+
+ return *this;
+}
+
+ID_INLINE int idVec3_t::operator==( const idVec3_t &a ) const {
+ if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
+ return false;
+ }
+
+ if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
+ return false;
+ }
+
+ if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
+ return false;
+ }
+
+ return true;
+}
+
+ID_INLINE int idVec3_t::operator!=( const idVec3_t &a ) const {
+ if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
+ return true;
+ }
+
+ if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
+ return true;
+ }
+
+ if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
+ return true;
+ }
+
+ return false;
+}
+
+ID_INLINE idVec3_t idVec3_t::Cross( const idVec3_t &a ) const {
+ return idVec3_t( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
+}
+
+ID_INLINE idVec3_t &idVec3_t::Cross( const idVec3_t &a, const idVec3_t &b ) {
+ x = a.y * b.z - a.z * b.y;
+ y = a.z * b.x - a.x * b.z;
+ z = a.x * b.y - a.y * b.x;
+
+ return *this;
+}
+
+ID_INLINE float idVec3_t::Length( void ) const {
+ float length;
+
+ length = x * x + y * y + z * z;
+ return ( float )idSqrt( length );
+}
+
+ID_INLINE float idVec3_t::Normalize( void ) {
+ float length;
+ float ilength;
+
+ length = this->Length();
+ if ( length ) {
+ ilength = 1.0f / length;
+ x *= ilength;
+ y *= ilength;
+ z *= ilength;
+ }
+
+ return length;
+}
+
+ID_INLINE void idVec3_t::Zero( void ) {
+ x = 0.0f;
+ y = 0.0f;
+ z = 0.0f;
+}
+
+ID_INLINE void idVec3_t::Snap( void ) {
+ x = float( int( x ) );
+ y = float( int( y ) );
+ z = float( int( z ) );
+}
+
+/*
+======================
+SnapTowards
+
+Round a vector to integers for more efficient network
+transmission, but make sure that it rounds towards a given point
+rather than blindly truncating. This prevents it from truncating
+into a wall.
+======================
+*/
+ID_INLINE void idVec3_t::SnapTowards( const idVec3_t &to ) {
+ if ( to.x <= x ) {
+ x = float( int( x ) );
+ } else {
+ x = float( int( x ) + 1 );
+ }
+
+ if ( to.y <= y ) {
+ y = float( int( y ) );
+ } else {
+ y = float( int( y ) + 1 );
+ }
+
+ if ( to.z <= z ) {
+ z = float( int( z ) );
+ } else {
+ z = float( int( z ) + 1 );
+ }
+}
+
+//===============================================================
+
+class Bounds {
+public:
+ idVec3_t b[2];
+
+ Bounds();
+ Bounds( const idVec3_t &mins, const idVec3_t &maxs );
+
+ void Clear();
+ void Zero();
+ float Radius(); // radius from origin, not from center
+ idVec3_t Center();
+ void AddPoint( const idVec3_t &v );
+ void AddBounds( const Bounds &bb );
+ bool IsCleared();
+ bool ContainsPoint( const idVec3_t &p );
+ bool IntersectsBounds( const Bounds &b2 ); // touching is NOT intersecting
+};
+
+extern Bounds boundsZero;
+
+ID_INLINE Bounds::Bounds(){
+}
+
+ID_INLINE bool Bounds::IsCleared() {
+ return b[0][0] > b[1][0];
+}
+
+ID_INLINE bool Bounds::ContainsPoint( const idVec3_t &p ) {
+ if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
+ || p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
+ return false;
+ }
+ return true;
+}
+
+ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
+ if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
+ || b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
+ return false;
+ }
+ return true;
+}
+
+ID_INLINE Bounds::Bounds( const idVec3_t &mins, const idVec3_t &maxs ) {
+ b[0] = mins;
+ b[1] = maxs;
+}
+
+ID_INLINE idVec3_t Bounds::Center() {
+ return idVec3_t( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
+}
+
+ID_INLINE void Bounds::Clear() {
+ b[0][0] = b[0][1] = b[0][2] = 99999;
+ b[1][0] = b[1][1] = b[1][2] = -99999;
+}
+
+ID_INLINE void Bounds::Zero() {
+ b[0][0] = b[0][1] = b[0][2] =
+ b[1][0] = b[1][1] = b[1][2] = 0;
+}
+
+ID_INLINE void Bounds::AddPoint( const idVec3_t &v ) {
+ if ( v[0] < b[0][0]) {
+ b[0][0] = v[0];
+ }
+ if ( v[0] > b[1][0]) {
+ b[1][0] = v[0];
+ }
+ if ( v[1] < b[0][1] ) {
+ b[0][1] = v[1];
+ }
+ if ( v[1] > b[1][1]) {
+ b[1][1] = v[1];
+ }
+ if ( v[2] < b[0][2] ) {
+ b[0][2] = v[2];
+ }
+ if ( v[2] > b[1][2]) {
+ b[1][2] = v[2];
+ }
+}
+
+
+ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
+ if ( bb.b[0][0] < b[0][0]) {
+ b[0][0] = bb.b[0][0];
+ }
+ if ( bb.b[0][1] < b[0][1]) {
+ b[0][1] = bb.b[0][1];
+ }
+ if ( bb.b[0][2] < b[0][2]) {
+ b[0][2] = bb.b[0][2];
+ }
+
+ if ( bb.b[1][0] > b[1][0]) {
+ b[1][0] = bb.b[1][0];
+ }
+ if ( bb.b[1][1] > b[1][1]) {
+ b[1][1] = bb.b[1][1];
+ }
+ if ( bb.b[1][2] > b[1][2]) {
+ b[1][2] = bb.b[1][2];
+ }
+}
+
+ID_INLINE float Bounds::Radius( ) {
+ int i;
+ float total;
+ float a, aa;
+
+ total = 0;
+ for (i=0 ; i<3 ; i++) {
+ a = (float)fabs( b[0][i] );
+ aa = (float)fabs( b[1][i] );
+ if ( aa > a ) {
+ a = aa;
+ }
+ total += a * a;
+ }
+
+ return (float)idSqrt( total );
+}
+
+//===============================================================
+
+
+class idVec2_t {
+public:
+ float x;
+ float y;
+
+ operator float *();
+ float operator[]( int index ) const;
+ float &operator[]( int index );
+};
+
+ID_INLINE float idVec2_t::operator[]( int index ) const {
+ return ( &x )[ index ];
+}
+
+ID_INLINE float& idVec2_t::operator[]( int index ) {
+ return ( &x )[ index ];
+}
+
+ID_INLINE idVec2_t::operator float *( void ) {
+ return &x;
+}
+
+class vec4_t : public idVec3_t {
+public:
+#ifndef FAT_VEC3
+ float dist;
+#endif
+ vec4_t();
+ ~vec4_t() {};
+
+ vec4_t( float x, float y, float z, float dist );
+ float operator[]( int index ) const;
+ float &operator[]( int index );
+};
+
+ID_INLINE vec4_t::vec4_t() {}
+ID_INLINE vec4_t::vec4_t( float x, float y, float z, float dist ) {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ this->dist = dist;
+}
+
+ID_INLINE float vec4_t::operator[]( int index ) const {
+ return ( &x )[ index ];
+}
+
+ID_INLINE float& vec4_t::operator[]( int index ) {
+ return ( &x )[ index ];
+}
+
+
+class idVec5_t : public idVec3_t {
+public:
+ float s;
+ float t;
+ float operator[]( int index ) const;
+ float &operator[]( int index );
+};
+
+
+ID_INLINE float idVec5_t::operator[]( int index ) const {
+ return ( &x )[ index ];
+}
+
+ID_INLINE float& idVec5_t::operator[]( int index ) {
+ return ( &x )[ index ];
+}
+
+#endif /* !__MATH_VECTOR_H__ */
diff --git a/q3radiant/splines/q_parse.cpp b/q3radiant/splines/q_parse.cpp
new file mode 100755
index 0000000..1f61ba4
--- /dev/null
+++ b/q3radiant/splines/q_parse.cpp
@@ -0,0 +1,535 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// q_parse.c -- support for parsing text files
+
+#include "q_shared.h"
+
+/*
+============================================================================
+
+PARSING
+
+============================================================================
+*/
+
+// multiple character punctuation tokens
+static const char *punctuation[] = {
+ "+=", "-=", "*=", "/=", "&=", "|=", "++", "--",
+ "&&", "||", "<=", ">=", "==", "!=",
+ NULL
+};
+
+typedef struct {
+ char token[MAX_TOKEN_CHARS];
+ int lines;
+ qboolean ungetToken;
+ char parseFile[MAX_QPATH];
+} parseInfo_t;
+
+#define MAX_PARSE_INFO 16
+static parseInfo_t parseInfo[MAX_PARSE_INFO];
+static int parseInfoNum;
+static parseInfo_t *pi = &parseInfo[0];
+
+/*
+===================
+Com_BeginParseSession
+===================
+*/
+void Com_BeginParseSession( const char *filename ) {
+ if ( parseInfoNum == MAX_PARSE_INFO - 1 ) {
+ Com_Error( ERR_FATAL, "Com_BeginParseSession: session overflow" );
+ }
+ parseInfoNum++;
+ pi = &parseInfo[parseInfoNum];
+
+ pi->lines = 1;
+ Q_strncpyz( pi->parseFile, filename, sizeof( pi->parseFile ) );
+}
+
+/*
+===================
+Com_EndParseSession
+===================
+*/
+void Com_EndParseSession( void ) {
+ if ( parseInfoNum == 0 ) {
+ Com_Error( ERR_FATAL, "Com_EndParseSession: session underflow" );
+ }
+ parseInfoNum--;
+ pi = &parseInfo[parseInfoNum];
+}
+
+/*
+===================
+Com_GetCurrentParseLine
+===================
+*/
+int Com_GetCurrentParseLine( void ) {
+ return pi->lines;
+}
+
+/*
+===================
+Com_ScriptError
+
+Prints the script name and line number in the message
+===================
+*/
+void Com_ScriptError( const char *msg, ... ) {
+ va_list argptr;
+ char string[32000];
+
+ va_start( argptr, msg );
+ vsprintf( string, msg,argptr );
+ va_end( argptr );
+
+ Com_Error( ERR_DROP, "File %s, line %i: %s", pi->parseFile, pi->lines, string );
+}
+
+void Com_ScriptWarning( const char *msg, ... ) {
+ va_list argptr;
+ char string[32000];
+
+ va_start( argptr, msg );
+ vsprintf( string, msg,argptr );
+ va_end( argptr );
+
+ Com_Printf( "File %s, line %i: %s", pi->parseFile, pi->lines, string );
+}
+
+
+/*
+===================
+Com_UngetToken
+
+Calling this will make the next Com_Parse return
+the current token instead of advancing the pointer
+===================
+*/
+void Com_UngetToken( void ) {
+ if ( pi->ungetToken ) {
+ Com_ScriptError( "UngetToken called twice" );
+ }
+ pi->ungetToken = qtrue;
+}
+
+
+static const char *SkipWhitespace( const char (*data), qboolean *hasNewLines ) {
+ int c;
+
+ while( (c = *data) <= ' ') {
+ if( !c ) {
+ return NULL;
+ }
+ if( c == '\n' ) {
+ pi->lines++;
+ *hasNewLines = qtrue;
+ }
+ data++;
+ }
+
+ return data;
+}
+
+/*
+==============
+Com_ParseExt
+
+Parse a token out of a string
+Will never return NULL, just empty strings.
+An empty string will only be returned at end of file.
+
+If "allowLineBreaks" is qtrue then an empty
+string will be returned if the next token is
+a newline.
+==============
+*/
+static char *Com_ParseExt( const char *(*data_p), qboolean allowLineBreaks ) {
+ int c = 0, len;
+ qboolean hasNewLines = qfalse;
+ const char *data;
+ const char **punc;
+
+ if ( !data_p ) {
+ Com_Error( ERR_FATAL, "Com_ParseExt: NULL data_p" );
+ }
+
+ data = *data_p;
+ len = 0;
+ pi->token[0] = 0;
+
+ // make sure incoming data is valid
+ if ( !data ) {
+ *data_p = NULL;
+ return pi->token;
+ }
+
+ // skip any leading whitespace
+ while ( 1 ) {
+ // skip whitespace
+ data = SkipWhitespace( data, &hasNewLines );
+ if ( !data ) {
+ *data_p = NULL;
+ return pi->token;
+ }
+ if ( hasNewLines && !allowLineBreaks ) {
+ *data_p = data;
+ return pi->token;
+ }
+
+ c = *data;
+
+ // skip double slash comments
+ if ( c == '/' && data[1] == '/' ) {
+ while (*data && *data != '\n') {
+ data++;
+ }
+ continue;
+ }
+
+ // skip /* */ comments
+ if ( c=='/' && data[1] == '*' ) {
+ while ( *data && ( *data != '*' || data[1] != '/' ) ) {
+ if( *data == '\n' ) {
+ pi->lines++;
+ }
+ data++;
+ }
+ if ( *data ) {
+ data += 2;
+ }
+ continue;
+ }
+
+ // a real token to parse
+ break;
+ }
+
+ // handle quoted strings
+ if ( c == '\"' ) {
+ data++;
+ while( 1 ) {
+ c = *data++;
+ if ( ( c=='\\' ) && ( *data == '\"' ) ) {
+ // allow quoted strings to use \" to indicate the " character
+ data++;
+ } else if ( c=='\"' || !c ) {
+ pi->token[len] = 0;
+ *data_p = ( char * ) data;
+ return pi->token;
+ } else if( *data == '\n' ) {
+ pi->lines++;
+ }
+ if ( len < MAX_TOKEN_CHARS - 1 ) {
+ pi->token[len] = c;
+ len++;
+ }
+ }
+ }
+
+ // check for a number
+ // is this parsing of negative numbers going to cause expression problems
+ if ( ( c >= '0' && c <= '9' ) || ( c == '-' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ||
+ ( c == '.' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ) {
+ do {
+
+ if (len < MAX_TOKEN_CHARS - 1) {
+ pi->token[len] = c;
+ len++;
+ }
+ data++;
+
+ c = *data;
+ } while ( ( c >= '0' && c <= '9' ) || c == '.' );
+
+ // parse the exponent
+ if ( c == 'e' || c == 'E' ) {
+ if (len < MAX_TOKEN_CHARS - 1) {
+ pi->token[len] = c;
+ len++;
+ }
+ data++;
+ c = *data;
+
+ if ( c == '-' || c == '+' ) {
+ if (len < MAX_TOKEN_CHARS - 1) {
+ pi->token[len] = c;
+ len++;
+ }
+ data++;
+ c = *data;
+ }
+
+ do {
+ if (len < MAX_TOKEN_CHARS - 1) {
+ pi->token[len] = c;
+ len++;
+ }
+ data++;
+
+ c = *data;
+ } while ( c >= '0' && c <= '9' );
+ }
+
+ if (len == MAX_TOKEN_CHARS) {
+ len = 0;
+ }
+ pi->token[len] = 0;
+
+ *data_p = ( char * ) data;
+ return pi->token;
+ }
+
+ // check for a regular word
+ // we still allow forward and back slashes in name tokens for pathnames
+ // and also colons for drive letters
+ if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' || c == '/' || c == '\\' ) {
+ do {
+ if (len < MAX_TOKEN_CHARS - 1) {
+ pi->token[len] = c;
+ len++;
+ }
+ data++;
+
+ c = *data;
+ } while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_'
+ || ( c >= '0' && c <= '9' ) || c == '/' || c == '\\' || c == ':' || c == '.' );
+
+ if (len == MAX_TOKEN_CHARS) {
+ len = 0;
+ }
+ pi->token[len] = 0;
+
+ *data_p = ( char * ) data;
+ return pi->token;
+ }
+
+ // check for multi-character punctuation token
+ for ( punc = punctuation ; *punc ; punc++ ) {
+ int l;
+ int j;
+
+ l = strlen( *punc );
+ for ( j = 0 ; j < l ; j++ ) {
+ if ( data[j] != (*punc)[j] ) {
+ break;
+ }
+ }
+ if ( j == l ) {
+ // a valid multi-character punctuation
+ memcpy( pi->token, *punc, l );
+ pi->token[l] = 0;
+ data += l;
+ *data_p = (char *)data;
+ return pi->token;
+ }
+ }
+
+ // single character punctuation
+ pi->token[0] = *data;
+ pi->token[1] = 0;
+ data++;
+ *data_p = (char *)data;
+
+ return pi->token;
+}
+
+/*
+===================
+Com_Parse
+===================
+*/
+const char *Com_Parse( const char *(*data_p) ) {
+ if ( pi->ungetToken ) {
+ pi->ungetToken = qfalse;
+ return pi->token;
+ }
+ return Com_ParseExt( data_p, qtrue );
+}
+
+/*
+===================
+Com_ParseOnLine
+===================
+*/
+const char *Com_ParseOnLine( const char *(*data_p) ) {
+ if ( pi->ungetToken ) {
+ pi->ungetToken = qfalse;
+ return pi->token;
+ }
+ return Com_ParseExt( data_p, qfalse );
+}
+
+
+
+/*
+==================
+Com_MatchToken
+==================
+*/
+void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ) {
+ const char *token;
+
+ token = Com_Parse( buf_p );
+ if ( strcmp( token, match ) ) {
+ if (warning) {
+ Com_ScriptWarning( "MatchToken: %s != %s", token, match );
+ } else {
+ Com_ScriptError( "MatchToken: %s != %s", token, match );
+ }
+ }
+}
+
+
+/*
+=================
+Com_SkipBracedSection
+
+The next token should be an open brace.
+Skips until a matching close brace is found.
+Internal brace depths are properly skipped.
+=================
+*/
+void Com_SkipBracedSection( const char *(*program) ) {
+ const char *token;
+ int depth;
+
+ depth = 0;
+ do {
+ token = Com_Parse( program );
+ if( token[1] == 0 ) {
+ if( token[0] == '{' ) {
+ depth++;
+ }
+ else if( token[0] == '}' ) {
+ depth--;
+ }
+ }
+ } while( depth && *program );
+}
+
+/*
+=================
+Com_SkipRestOfLine
+=================
+*/
+void Com_SkipRestOfLine ( const char *(*data) ) {
+ const char *p;
+ int c;
+
+ p = *data;
+ while ( (c = *p++) != 0 ) {
+ if ( c == '\n' ) {
+ pi->lines++;
+ break;
+ }
+ }
+
+ *data = p;
+}
+
+/*
+====================
+Com_ParseRestOfLine
+====================
+*/
+const char *Com_ParseRestOfLine( const char *(*data_p) ) {
+ static char line[MAX_TOKEN_CHARS];
+ const char *token;
+
+ line[0] = 0;
+ while( 1 ) {
+ token = Com_ParseOnLine( data_p );
+ if ( !token[0] ) {
+ break;
+ }
+ if ( line[0] ) {
+ Q_strcat( line, sizeof(line), " " );
+ }
+ Q_strcat( line, sizeof(line), token );
+ }
+
+ return line;
+}
+
+
+float Com_ParseFloat( const char *(*buf_p) ) {
+ const char *token;
+
+ token = Com_Parse( buf_p );
+ if ( !token[0] ) {
+ return 0;
+ }
+ return atof( token );
+}
+
+int Com_ParseInt( const char *(*buf_p) ) {
+ const char *token;
+
+ token = Com_Parse( buf_p );
+ if ( !token[0] ) {
+ return 0;
+ }
+ return atof( token );
+}
+
+
+
+void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) {
+ const char *token;
+ int i;
+
+ Com_MatchToken( buf_p, "(" );
+
+ for (i = 0 ; i < x ; i++) {
+ token = Com_Parse(buf_p);
+ m[i] = atof(token);
+ }
+
+ Com_MatchToken( buf_p, ")" );
+}
+
+void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) {
+ int i;
+
+ Com_MatchToken( buf_p, "(" );
+
+ for (i = 0 ; i < y ; i++) {
+ Com_Parse1DMatrix (buf_p, x, m + i * x);
+ }
+
+ Com_MatchToken( buf_p, ")" );
+}
+
+void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) {
+ int i;
+
+ Com_MatchToken( buf_p, "(" );
+
+ for (i = 0 ; i < z ; i++) {
+ Com_Parse2DMatrix (buf_p, y, x, m + i * x*y);
+ }
+
+ Com_MatchToken( buf_p, ")" );
+}
+
diff --git a/q3radiant/splines/q_shared.cpp b/q3radiant/splines/q_shared.cpp
new file mode 100755
index 0000000..56cbcf1
--- /dev/null
+++ b/q3radiant/splines/q_shared.cpp
@@ -0,0 +1,976 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+// q_shared.c -- stateless support routines that are included in each code dll
+#include "q_shared.h"
+
+/*
+============================================================================
+
+GROWLISTS
+
+============================================================================
+*/
+
+// malloc / free all in one place for debugging
+extern "C" void *Com_Allocate( int bytes );
+extern "C" void Com_Dealloc( void *ptr );
+
+void Com_InitGrowList( growList_t *list, int maxElements ) {
+ list->maxElements = maxElements;
+ list->currentElements = 0;
+ list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
+}
+
+int Com_AddToGrowList( growList_t *list, void *data ) {
+ void **old;
+
+ if ( list->currentElements != list->maxElements ) {
+ list->elements[list->currentElements] = data;
+ return list->currentElements++;
+ }
+
+ // grow, reallocate and move
+ old = list->elements;
+
+ if ( list->maxElements < 0 ) {
+ Com_Error( ERR_FATAL, "Com_AddToGrowList: maxElements = %i", list->maxElements );
+ }
+
+ if ( list->maxElements == 0 ) {
+ // initialize the list to hold 100 elements
+ Com_InitGrowList( list, 100 );
+ return Com_AddToGrowList( list, data );
+ }
+
+ list->maxElements *= 2;
+
+ Com_DPrintf( "Resizing growlist to %i maxElements\n", list->maxElements );
+
+ list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
+
+ if ( !list->elements ) {
+ Com_Error( ERR_DROP, "Growlist alloc failed" );
+ }
+
+ memcpy( list->elements, old, list->currentElements * sizeof( void * ) );
+
+ Com_Dealloc( old );
+
+ return Com_AddToGrowList( list, data );
+}
+
+void *Com_GrowListElement( const growList_t *list, int index ) {
+ if ( index < 0 || index >= list->currentElements ) {
+ Com_Error( ERR_DROP, "Com_GrowListElement: %i out of range of %i",
+ index, list->currentElements );
+ }
+ return list->elements[index];
+}
+
+int Com_IndexForGrowListElement( const growList_t *list, const void *element ) {
+ int i;
+
+ for ( i = 0 ; i < list->currentElements ; i++ ) {
+ if ( list->elements[i] == element ) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+//============================================================================
+
+
+float Com_Clamp( float min, float max, float value ) {
+ if ( value < min ) {
+ return min;
+ }
+ if ( value > max ) {
+ return max;
+ }
+ return value;
+}
+
+/*
+============
+Com_StringContains
+============
+*/
+const char *Com_StringContains( const char *str1, const char *str2, int casesensitive) {
+ int len, i, j;
+
+ len = strlen(str1) - strlen(str2);
+ for (i = 0; i <= len; i++, str1++) {
+ for (j = 0; str2[j]; j++) {
+ if (casesensitive) {
+ if (str1[j] != str2[j]) {
+ break;
+ }
+ }
+ else {
+ if (toupper(str1[j]) != toupper(str2[j])) {
+ break;
+ }
+ }
+ }
+ if (!str2[j]) {
+ return str1;
+ }
+ }
+ return NULL;
+}
+
+/*
+============
+Com_Filter
+============
+*/
+int Com_Filter( const char *filter, const char *name, int casesensitive)
+{
+ char buf[MAX_TOKEN_CHARS];
+ const char *ptr;
+ int i, found;
+
+ while(*filter) {
+ if (*filter == '*') {
+ filter++;
+ for (i = 0; *filter; i++) {
+ if (*filter == '*' || *filter == '?') break;
+ buf[i] = *filter;
+ filter++;
+ }
+ buf[i] = '\0';
+ if (strlen(buf)) {
+ ptr = Com_StringContains(name, buf, casesensitive);
+ if (!ptr) return qfalse;
+ name = ptr + strlen(buf);
+ }
+ }
+ else if (*filter == '?') {
+ filter++;
+ name++;
+ }
+ else if (*filter == '[' && *(filter+1) == '[') {
+ filter++;
+ }
+ else if (*filter == '[') {
+ filter++;
+ found = qfalse;
+ while(*filter && !found) {
+ if (*filter == ']' && *(filter+1) != ']') break;
+ if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']')) {
+ if (casesensitive) {
+ if (*name >= *filter && *name <= *(filter+2)) found = qtrue;
+ }
+ else {
+ if (toupper(*name) >= toupper(*filter) &&
+ toupper(*name) <= toupper(*(filter+2))) found = qtrue;
+ }
+ filter += 3;
+ }
+ else {
+ if (casesensitive) {
+ if (*filter == *name) found = qtrue;
+ }
+ else {
+ if (toupper(*filter) == toupper(*name)) found = qtrue;
+ }
+ filter++;
+ }
+ }
+ if (!found) return qfalse;
+ while(*filter) {
+ if (*filter == ']' && *(filter+1) != ']') break;
+ filter++;
+ }
+ filter++;
+ name++;
+ }
+ else {
+ if (casesensitive) {
+ if (*filter != *name) return qfalse;
+ }
+ else {
+ if (toupper(*filter) != toupper(*name)) return qfalse;
+ }
+ filter++;
+ name++;
+ }
+ }
+ return qtrue;
+}
+
+
+/*
+================
+Com_HashString
+
+================
+*/
+int Com_HashString( const char *fname ) {
+ int i;
+ long hash;
+ char letter;
+
+ hash = 0;
+ i = 0;
+ while (fname[i] != '\0') {
+ letter = tolower(fname[i]);
+ if (letter =='.') break; // don't include extension
+ if (letter =='\\') letter = '/'; // damn path names
+ hash+=(long)(letter)*(i+119);
+ i++;
+ }
+ hash &= (FILE_HASH_SIZE-1);
+ return hash;
+}
+
+
+/*
+============
+Com_SkipPath
+============
+*/
+char *Com_SkipPath (char *pathname)
+{
+ char *last;
+
+ last = pathname;
+ while (*pathname)
+ {
+ if (*pathname=='/')
+ last = pathname+1;
+ pathname++;
+ }
+ return last;
+}
+
+/*
+============
+Com_StripExtension
+============
+*/
+void Com_StripExtension( const char *in, char *out ) {
+ while ( *in && *in != '.' ) {
+ *out++ = *in++;
+ }
+ *out = 0;
+}
+
+
+/*
+==================
+Com_DefaultExtension
+==================
+*/
+void Com_DefaultExtension (char *path, int maxSize, const char *extension ) {
+ char oldPath[MAX_QPATH];
+ char *src;
+
+//
+// if path doesn't have a .EXT, append extension
+// (extension should include the .)
+//
+ src = path + strlen(path) - 1;
+
+ while (*src != '/' && src != path) {
+ if ( *src == '.' ) {
+ return; // it has an extension
+ }
+ src--;
+ }
+
+ Q_strncpyz( oldPath, path, sizeof( oldPath ) );
+ Com_sprintf( path, maxSize, "%s%s", oldPath, extension );
+}
+
+/*
+============================================================================
+
+ BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+// can't just use function pointers, or dll linkage can
+// mess up when qcommon is included in multiple places
+static short (*_BigShort) (short l);
+static short (*_LittleShort) (short l);
+static int (*_BigLong) (int l);
+static int (*_LittleLong) (int l);
+static float (*_BigFloat) (float l);
+static float (*_LittleFloat) (float l);
+
+short BigShort(short l){return _BigShort(l);}
+short LittleShort(short l) {return _LittleShort(l);}
+int BigLong (int l) {return _BigLong(l);}
+int LittleLong (int l) {return _LittleLong(l);}
+float BigFloat (float l) {return _BigFloat(l);}
+float LittleFloat (float l) {return _LittleFloat(l);}
+
+short ShortSwap (short l)
+{
+ byte b1,b2;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+
+ return (b1<<8) + b2;
+}
+
+short ShortNoSwap (short l)
+{
+ return l;
+}
+
+int LongSwap (int l)
+{
+ byte b1,b2,b3,b4;
+
+ b1 = l&255;
+ b2 = (l>>8)&255;
+ b3 = (l>>16)&255;
+ b4 = (l>>24)&255;
+
+ return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int LongNoSwap (int l)
+{
+ return l;
+}
+
+float FloatSwap (float f)
+{
+ union
+ {
+ float f;
+ byte b[4];
+ } dat1, dat2;
+
+
+ dat1.f = f;
+ dat2.b[0] = dat1.b[3];
+ dat2.b[1] = dat1.b[2];
+ dat2.b[2] = dat1.b[1];
+ dat2.b[3] = dat1.b[0];
+ return dat2.f;
+}
+
+float FloatNoSwap (float f)
+{
+ return f;
+}
+
+/*
+================
+Swap_Init
+================
+*/
+void Swap_Init (void)
+{
+ byte swaptest[2] = {1,0};
+
+// set the byte swapping variables in a portable manner
+ if ( *(short *)swaptest == 1)
+ {
+ _BigShort = ShortSwap;
+ _LittleShort = ShortNoSwap;
+ _BigLong = LongSwap;
+ _LittleLong = LongNoSwap;
+ _BigFloat = FloatSwap;
+ _LittleFloat = FloatNoSwap;
+ }
+ else
+ {
+ _BigShort = ShortNoSwap;
+ _LittleShort = ShortSwap;
+ _BigLong = LongNoSwap;
+ _LittleLong = LongSwap;
+ _BigFloat = FloatNoSwap;
+ _LittleFloat = FloatSwap;
+ }
+
+}
+
+/*
+===============
+Com_ParseInfos
+===============
+*/
+int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ) {
+ const char *token;
+ int count;
+ char key[MAX_TOKEN_CHARS];
+
+ count = 0;
+
+ while ( 1 ) {
+ token = Com_Parse( &buf );
+ if ( !token[0] ) {
+ break;
+ }
+ if ( strcmp( token, "{" ) ) {
+ Com_Printf( "Missing { in info file\n" );
+ break;
+ }
+
+ if ( count == max ) {
+ Com_Printf( "Max infos exceeded\n" );
+ break;
+ }
+
+ infos[count][0] = 0;
+ while ( 1 ) {
+ token = Com_Parse( &buf );
+ if ( !token[0] ) {
+ Com_Printf( "Unexpected end of info file\n" );
+ break;
+ }
+ if ( !strcmp( token, "}" ) ) {
+ break;
+ }
+ Q_strncpyz( key, token, sizeof( key ) );
+
+ token = Com_ParseOnLine( &buf );
+ if ( !token[0] ) {
+ token = "<NULL>";
+ }
+ Info_SetValueForKey( infos[count], key, token );
+ }
+ count++;
+ }
+
+ return count;
+}
+
+
+
+/*
+============================================================================
+
+ LIBRARY REPLACEMENT FUNCTIONS
+
+============================================================================
+*/
+
+int Q_isprint( int c )
+{
+ if ( c >= 0x20 && c <= 0x7E )
+ return ( 1 );
+ return ( 0 );
+}
+
+int Q_islower( int c )
+{
+ if (c >= 'a' && c <= 'z')
+ return ( 1 );
+ return ( 0 );
+}
+
+int Q_isupper( int c )
+{
+ if (c >= 'A' && c <= 'Z')
+ return ( 1 );
+ return ( 0 );
+}
+
+int Q_isalpha( int c )
+{
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+ return ( 1 );
+ return ( 0 );
+}
+
+char* Q_strrchr( const char* string, int c )
+{
+ char cc = c;
+ char *s;
+ char *sp=(char *)0;
+
+ s = (char*)string;
+
+ while (*s)
+ {
+ if (*s == cc)
+ sp = s;
+ s++;
+ }
+ if (cc == 0)
+ sp = s;
+
+ return sp;
+}
+
+/*
+=============
+Q_strncpyz
+
+Safe strncpy that ensures a trailing zero
+=============
+*/
+void Q_strncpyz( char *dest, const char *src, int destsize ) {
+ if ( !src ) {
+ Com_Error( ERR_FATAL, "Q_strncpyz: NULL src" );
+ }
+ if ( destsize < 1 ) {
+ Com_Error(ERR_FATAL,"Q_strncpyz: destsize < 1" );
+ }
+
+ strncpy( dest, src, destsize-1 );
+ dest[destsize-1] = 0;
+}
+
+int Q_stricmpn (const char *s1, const char *s2, int n) {
+ int c1, c2;
+
+ do {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if (!n--) {
+ return 0; // strings are equal until end point
+ }
+
+ if (c1 != c2) {
+ if (c1 >= 'a' && c1 <= 'z') {
+ c1 -= ('a' - 'A');
+ }
+ if (c2 >= 'a' && c2 <= 'z') {
+ c2 -= ('a' - 'A');
+ }
+ if (c1 != c2) {
+ return c1 < c2 ? -1 : 1;
+ }
+ }
+ } while (c1);
+
+ return 0; // strings are equal
+}
+
+int Q_strncmp (const char *s1, const char *s2, int n) {
+ int c1, c2;
+
+ do {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if (!n--) {
+ return 0; // strings are equal until end point
+ }
+
+ if (c1 != c2) {
+ return c1 < c2 ? -1 : 1;
+ }
+ } while (c1);
+
+ return 0; // strings are equal
+}
+
+int Q_stricmp (const char *s1, const char *s2) {
+ return Q_stricmpn (s1, s2, 99999);
+}
+
+
+char *Q_strlwr( char *s1 ) {
+ char *s;
+
+ s = s1;
+ while ( *s ) {
+ *s = tolower(*s);
+ s++;
+ }
+ return s1;
+}
+
+char *Q_strupr( char *s1 ) {
+ char *s;
+
+ s = s1;
+ while ( *s ) {
+ *s = toupper(*s);
+ s++;
+ }
+ return s1;
+}
+
+
+// never goes past bounds or leaves without a terminating 0
+void Q_strcat( char *dest, int size, const char *src ) {
+ int l1;
+
+ l1 = strlen( dest );
+ if ( l1 >= size ) {
+ Com_Error( ERR_FATAL, "Q_strcat: already overflowed" );
+ }
+ Q_strncpyz( dest + l1, src, size - l1 );
+}
+
+
+int Q_PrintStrlen( const char *string ) {
+ int len;
+ const char *p;
+
+ if( !string ) {
+ return 0;
+ }
+
+ len = 0;
+ p = string;
+ while( *p ) {
+ if( Q_IsColorString( p ) ) {
+ p += 2;
+ continue;
+ }
+ p++;
+ len++;
+ }
+
+ return len;
+}
+
+
+char *Q_CleanStr( char *string ) {
+ char* d;
+ char* s;
+ int c;
+
+ s = string;
+ d = string;
+ while ((c = *s) != 0 ) {
+ if ( Q_IsColorString( s ) ) {
+ s++;
+ }
+ else if ( c >= 0x20 && c <= 0x7E ) {
+ *d++ = c;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return string;
+}
+
+
+void QDECL Com_sprintf( char *dest, int size, const char *fmt, ...) {
+ int len;
+ va_list argptr;
+ char bigbuffer[32000]; // big, but small enough to fit in PPC stack
+
+ va_start (argptr,fmt);
+ len = vsprintf (bigbuffer,fmt,argptr);
+ va_end (argptr);
+ if ( len >= sizeof( bigbuffer ) ) {
+ Com_Error( ERR_FATAL, "Com_sprintf: overflowed bigbuffer" );
+ }
+ if (len >= size) {
+ Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size);
+ }
+ Q_strncpyz (dest, bigbuffer, size );
+}
+
+
+/*
+============
+va
+
+does a varargs printf into a temp buffer, so I don't need to have
+varargs versions of all text functions.
+FIXME: make this buffer size safe someday
+============
+*/
+char * QDECL va( char *format, ... ) {
+ va_list argptr;
+ static char string[2][32000]; // in case va is called by nested functions
+ static int index = 0;
+ char *buf;
+
+ buf = string[index & 1];
+ index++;
+
+ va_start (argptr, format);
+ vsprintf (buf, format,argptr);
+ va_end (argptr);
+
+ return buf;
+}
+
+
+/*
+=====================================================================
+
+ INFO STRINGS
+
+=====================================================================
+*/
+
+/*
+===============
+Info_ValueForKey
+
+Searches the string for the given
+key and returns the associated value, or an empty string.
+FIXME: overflow check?
+===============
+*/
+char *Info_ValueForKey( const char *s, const char *key ) {
+ char pkey[MAX_INFO_KEY];
+ static char value[2][MAX_INFO_VALUE]; // use two buffers so compares
+ // work without stomping on each other
+ static int valueindex = 0;
+ char *o;
+
+ if ( !s || !key ) {
+ return "";
+ }
+
+ if ( strlen( s ) >= MAX_INFO_STRING ) {
+ Com_Error( ERR_DROP, "Info_ValueForKey: oversize infostring" );
+ }
+
+ valueindex ^= 1;
+ if (*s == '\\')
+ s++;
+ while (1)
+ {
+ o = pkey;
+ while (*s != '\\')
+ {
+ if (!*s)
+ return "";
+ *o++ = *s++;
+ }
+ *o = 0;
+ s++;
+
+ o = value[valueindex];
+
+ while (*s != '\\' && *s)
+ {
+ *o++ = *s++;
+ }
+ *o = 0;
+
+ if (!Q_stricmp (key, pkey) )
+ return value[valueindex];
+
+ if (!*s)
+ break;
+ s++;
+ }
+
+ return "";
+}
+
+
+/*
+===================
+Info_NextPair
+
+Used to itterate through all the key/value pairs in an info string
+===================
+*/
+void Info_NextPair( const char *(*head), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ) {
+ char *o;
+ const char *s;
+
+ s = *head;
+
+ if ( *s == '\\' ) {
+ s++;
+ }
+ key[0] = 0;
+ value[0] = 0;
+
+ o = key;
+ while ( *s != '\\' ) {
+ if ( !*s ) {
+ *o = 0;
+ *head = s;
+ return;
+ }
+ *o++ = *s++;
+ }
+ *o = 0;
+ s++;
+
+ o = value;
+ while ( *s != '\\' && *s ) {
+ *o++ = *s++;
+ }
+ *o = 0;
+
+ *head = s;
+}
+
+
+/*
+===================
+Info_RemoveKey
+===================
+*/
+void Info_RemoveKey( char *s, const char *key ) {
+ char *start;
+ char pkey[MAX_INFO_KEY];
+ char value[MAX_INFO_VALUE];
+ char *o;
+
+ if ( strlen( s ) >= MAX_INFO_STRING ) {
+ Com_Error( ERR_DROP, "Info_RemoveKey: oversize infostring" );
+ }
+
+ if (strchr (key, '\\')) {
+ return;
+ }
+
+ while (1)
+ {
+ start = s;
+ if (*s == '\\')
+ s++;
+ o = pkey;
+ while (*s != '\\')
+ {
+ if (!*s)
+ return;
+ *o++ = *s++;
+ }
+ *o = 0;
+ s++;
+
+ o = value;
+ while (*s != '\\' && *s)
+ {
+ if (!*s)
+ return;
+ *o++ = *s++;
+ }
+ *o = 0;
+
+ if (!strcmp (key, pkey) )
+ {
+ strcpy (start, s); // remove this part
+ return;
+ }
+
+ if (!*s)
+ return;
+ }
+
+}
+
+
+/*
+==================
+Info_Validate
+
+Some characters are illegal in info strings because they
+can mess up the server's parsing
+==================
+*/
+qboolean Info_Validate( const char *s ) {
+ if ( strchr( s, '\"' ) ) {
+ return qfalse;
+ }
+ if ( strchr( s, ';' ) ) {
+ return qfalse;
+ }
+ return qtrue;
+}
+
+/*
+==================
+Info_SetValueForKey
+
+Changes or adds a key/value pair
+==================
+*/
+void Info_SetValueForKey( char *s, const char *key, const char *value ) {
+ char newi[MAX_INFO_STRING];
+
+ if ( strlen( s ) >= MAX_INFO_STRING ) {
+ Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" );
+ }
+
+ if (strchr (key, '\\') || strchr (value, '\\'))
+ {
+ Com_Printf ("Can't use keys or values with a \\\n");
+ return;
+ }
+
+ if (strchr (key, ';') || strchr (value, ';'))
+ {
+ Com_Printf ("Can't use keys or values with a semicolon\n");
+ return;
+ }
+
+ if (strchr (key, '\"') || strchr (value, '\"'))
+ {
+ Com_Printf ("Can't use keys or values with a \"\n");
+ return;
+ }
+
+ Info_RemoveKey (s, key);
+ if (!value || !strlen(value))
+ return;
+
+ Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
+
+ if (strlen(newi) + strlen(s) > MAX_INFO_STRING)
+ {
+ Com_Printf ("Info string length exceeded\n");
+ return;
+ }
+
+ strcat (s, newi);
+}
+
+//====================================================================
+
+
+/*
+===============
+ParseHex
+===============
+*/
+int ParseHex( const char *text ) {
+ int value;
+ int c;
+
+ value = 0;
+ while ( ( c = *text++ ) != 0 ) {
+ if ( c >= '0' && c <= '9' ) {
+ value = value * 16 + c - '0';
+ continue;
+ }
+ if ( c >= 'a' && c <= 'f' ) {
+ value = value * 16 + 10 + c - 'a';
+ continue;
+ }
+ if ( c >= 'A' && c <= 'F' ) {
+ value = value * 16 + 10 + c - 'A';
+ continue;
+ }
+ }
+
+ return value;
+}
diff --git a/q3radiant/splines/q_shared.h b/q3radiant/splines/q_shared.h
new file mode 100755
index 0000000..6d9a563
--- /dev/null
+++ b/q3radiant/splines/q_shared.h
@@ -0,0 +1,798 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __Q_SHARED_H
+#define __Q_SHARED_H
+
+// q_shared.h -- included first by ALL program modules.
+// these are the definitions that have no dependance on
+// central system services, and can be used by any part
+// of the program without any state issues.
+
+// A user mod should never modify this file
+
+#define Q3_VERSION "DOOM 0.01"
+
+// alignment macros for SIMD
+#define ALIGN_ON
+#define ALIGN_OFF
+
+#ifdef _WIN32
+
+#pragma warning(disable : 4018) // signed/unsigned mismatch
+#pragma warning(disable : 4032)
+#pragma warning(disable : 4051)
+#pragma warning(disable : 4057) // slightly different base types
+#pragma warning(disable : 4100) // unreferenced formal parameter
+#pragma warning(disable : 4115)
+#pragma warning(disable : 4125) // decimal digit terminates octal escape sequence
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4136)
+#pragma warning(disable : 4201)
+#pragma warning(disable : 4214)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4305) // truncation from const double to float
+#pragma warning(disable : 4310) // cast truncates constant value
+#pragma warning(disable : 4514)
+#pragma warning(disable : 4711) // selected for automatic inline expansion
+#pragma warning(disable : 4220) // varargs matches remaining parameters
+
+#endif
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#ifdef WIN32 // mac doesn't have malloc.h
+#include <malloc.h> // for _alloca()
+#endif
+#ifdef _WIN32
+
+//#pragma intrinsic( memset, memcpy )
+
+#endif
+
+
+// this is the define for determining if we have an asm version of a C function
+#if (defined _M_IX86 || defined __i386__) && !defined __sun__ && !defined __LCC__
+#define id386 1
+#else
+#define id386 0
+#endif
+
+// for windows fastcall option
+
+#define QDECL
+
+//======================= WIN32 DEFINES =================================
+
+#ifdef WIN32
+
+#define MAC_STATIC
+
+#undef QDECL
+#define QDECL __cdecl
+
+// buildstring will be incorporated into the version string
+#ifdef NDEBUG
+#ifdef _M_IX86
+#define CPUSTRING "win-x86"
+#elif defined _M_ALPHA
+#define CPUSTRING "win-AXP"
+#endif
+#else
+#ifdef _M_IX86
+#define CPUSTRING "win-x86-debug"
+#elif defined _M_ALPHA
+#define CPUSTRING "win-AXP-debug"
+#endif
+#endif
+
+
+#define PATH_SEP '\\'
+
+#endif
+
+//======================= MAC OS X SERVER DEFINES =====================
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MAC_STATIC
+
+#ifdef __ppc__
+#define CPUSTRING "MacOSXS-ppc"
+#elif defined __i386__
+#define CPUSTRING "MacOSXS-i386"
+#else
+#define CPUSTRING "MacOSXS-other"
+#endif
+
+#define PATH_SEP '/'
+
+#define GAME_HARD_LINKED
+#define CGAME_HARD_LINKED
+#define UI_HARD_LINKED
+#define _alloca alloca
+
+#undef ALIGN_ON
+#undef ALIGN_OFF
+#define ALIGN_ON #pragma align(16)
+#define ALIGN_OFF #pragma align()
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+void *osxAllocateMemory(long size);
+void osxFreeMemory(void *pointer);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
+
+//======================= MAC DEFINES =================================
+
+#ifdef __MACOS__
+
+#define MAC_STATIC static
+
+#define CPUSTRING "MacOS-PPC"
+
+#define PATH_SEP ':'
+
+void Sys_PumpEvents( void );
+
+#endif
+
+#ifdef __MRC__
+
+#define MAC_STATIC
+
+#define CPUSTRING "MacOS-PPC"
+
+#define PATH_SEP ':'
+
+void Sys_PumpEvents( void );
+
+#undef QDECL
+#define QDECL __cdecl
+
+#define _alloca alloca
+#endif
+
+//======================= LINUX DEFINES =================================
+
+// the mac compiler can't handle >32k of locals, so we
+// just waste space and make big arrays static...
+#ifdef __linux__
+
+#define MAC_STATIC
+
+#ifdef __i386__
+#define CPUSTRING "linux-i386"
+#elif defined __axp__
+#define CPUSTRING "linux-alpha"
+#else
+#define CPUSTRING "linux-other"
+#endif
+
+#define PATH_SEP '/'
+
+#endif
+
+//=============================================================
+
+
+
+typedef enum {qfalse, qtrue} qboolean;
+
+typedef unsigned char byte;
+
+#define EQUAL_EPSILON 0.001
+
+typedef int qhandle_t;
+typedef int sfxHandle_t;
+typedef int fileHandle_t;
+typedef int clipHandle_t;
+
+typedef enum {
+ INVALID_JOINT = -1
+} jointHandle_t;
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define MAX_QINT 0x7fffffff
+#define MIN_QINT (-MAX_QINT-1)
+
+#ifndef max
+#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) )
+#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) )
+#endif
+
+#ifndef sign
+#define sign( f ) ( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) )
+#endif
+
+// angle indexes
+#define PITCH 0 // up / down
+#define YAW 1 // left / right
+#define ROLL 2 // fall over
+
+// the game guarantees that no string from the network will ever
+// exceed MAX_STRING_CHARS
+#define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString
+#define MAX_STRING_TOKENS 256 // max tokens resulting from Cmd_TokenizeString
+#define MAX_TOKEN_CHARS 1024 // max length of an individual token
+
+#define MAX_INFO_STRING 1024
+#define MAX_INFO_KEY 1024
+#define MAX_INFO_VALUE 1024
+
+
+#define MAX_QPATH 64 // max length of a quake game pathname
+#define MAX_OSPATH 128 // max length of a filesystem pathname
+
+#define MAX_NAME_LENGTH 32 // max length of a client name
+
+// paramters for command buffer stuffing
+typedef enum {
+ EXEC_NOW, // don't return until completed, a VM should NEVER use this,
+ // because some commands might cause the VM to be unloaded...
+ EXEC_INSERT, // insert at current position, but don't run yet
+ EXEC_APPEND // add to end of the command buffer (normal case)
+} cbufExec_t;
+
+
+//
+// these aren't needed by any of the VMs. put in another header?
+//
+#define MAX_MAP_AREA_BYTES 32 // bit vector of area visibility
+
+#undef ERR_FATAL // malloc.h on unix
+
+// parameters to the main Error routine
+typedef enum {
+ ERR_NONE,
+ ERR_FATAL, // exit the entire game with a popup window
+ ERR_DROP, // print to console and disconnect from game
+ ERR_DISCONNECT, // don't kill server
+ ERR_NEED_CD // pop up the need-cd dialog
+} errorParm_t;
+
+
+// font rendering values used by ui and cgame
+
+#define PROP_GAP_WIDTH 3
+#define PROP_SPACE_WIDTH 8
+#define PROP_HEIGHT 27
+#define PROP_SMALL_SIZE_SCALE 0.75
+
+#define BLINK_DIVISOR 200
+#define PULSE_DIVISOR 75
+
+#define UI_LEFT 0x00000000 // default
+#define UI_CENTER 0x00000001
+#define UI_RIGHT 0x00000002
+#define UI_FORMATMASK 0x00000007
+#define UI_SMALLFONT 0x00000010
+#define UI_BIGFONT 0x00000020 // default
+#define UI_GIANTFONT 0x00000040
+#define UI_DROPSHADOW 0x00000800
+#define UI_BLINK 0x00001000
+#define UI_INVERSE 0x00002000
+#define UI_PULSE 0x00004000
+
+
+/*
+==============================================================
+
+MATHLIB
+
+==============================================================
+*/
+#ifdef __cplusplus // so we can include this in C code
+#define SIDE_FRONT 0
+#define SIDE_BACK 1
+#define SIDE_ON 2
+#define SIDE_CROSS 3
+
+#define Q_PI 3.14159265358979323846
+#ifndef M_PI
+#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
+#endif
+
+#include "math_vector.h"
+#include "math_angles.h"
+#include "math_matrix.h"
+#include "math_quaternion.h"
+
+class idVec3_t; // for defining vectors
+typedef idVec3_t &vec3_p; // for passing vectors as function arguments
+typedef const idVec3_t &vec3_c; // for passing vectors as const function arguments
+
+class angles_t; // for defining angle vectors
+typedef angles_t &angles_p; // for passing angles as function arguments
+typedef const angles_t &angles_c; // for passing angles as const function arguments
+
+class mat3_t; // for defining matrices
+typedef mat3_t &mat3_p; // for passing matrices as function arguments
+typedef const mat3_t &mat3_c; // for passing matrices as const function arguments
+
+
+
+#define NUMVERTEXNORMALS 162
+extern idVec3_t bytedirs[NUMVERTEXNORMALS];
+
+// all drawing is done to a 640*480 virtual screen size
+// and will be automatically scaled to the real resolution
+#define SCREEN_WIDTH 640
+#define SCREEN_HEIGHT 480
+
+#define TINYCHAR_WIDTH (SMALLCHAR_WIDTH)
+#define TINYCHAR_HEIGHT (SMALLCHAR_HEIGHT/2)
+
+#define SMALLCHAR_WIDTH 8
+#define SMALLCHAR_HEIGHT 16
+
+#define BIGCHAR_WIDTH 16
+#define BIGCHAR_HEIGHT 16
+
+#define GIANTCHAR_WIDTH 32
+#define GIANTCHAR_HEIGHT 48
+
+extern vec4_t colorBlack;
+extern vec4_t colorRed;
+extern vec4_t colorGreen;
+extern vec4_t colorBlue;
+extern vec4_t colorYellow;
+extern vec4_t colorMagenta;
+extern vec4_t colorCyan;
+extern vec4_t colorWhite;
+extern vec4_t colorLtGrey;
+extern vec4_t colorMdGrey;
+extern vec4_t colorDkGrey;
+
+#define Q_COLOR_ESCAPE '^'
+#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE )
+
+#define COLOR_BLACK '0'
+#define COLOR_RED '1'
+#define COLOR_GREEN '2'
+#define COLOR_YELLOW '3'
+#define COLOR_BLUE '4'
+#define COLOR_CYAN '5'
+#define COLOR_MAGENTA '6'
+#define COLOR_WHITE '7'
+#define ColorIndex(c) ( ( (c) - '0' ) & 7 )
+
+#define S_COLOR_BLACK "^0"
+#define S_COLOR_RED "^1"
+#define S_COLOR_GREEN "^2"
+#define S_COLOR_YELLOW "^3"
+#define S_COLOR_BLUE "^4"
+#define S_COLOR_CYAN "^5"
+#define S_COLOR_MAGENTA "^6"
+#define S_COLOR_WHITE "^7"
+
+extern vec4_t g_color_table[8];
+
+#define MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b
+#define MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a
+
+#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F )
+#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI )
+
+struct cplane_s;
+
+extern idVec3_t vec3_origin;
+extern vec4_t vec4_origin;
+extern mat3_t axisDefault;
+
+#define nanmask (255<<23)
+
+#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
+
+float Q_fabs( float f );
+float Q_rsqrt( float f ); // reciprocal square root
+
+#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) )
+
+signed char ClampChar( int i );
+signed short ClampShort( int i );
+
+// this isn't a real cheap function to call!
+int DirToByte( const idVec3_t &dir );
+void ByteToDir( int b, vec3_p dir );
+
+#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
+
+#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
+#define VectorMA(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
+#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+
+#define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
+#define VectorSubtract4(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
+#define VectorAdd4(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
+#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+#define VectorScale4(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
+#define VectorMA4(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
+
+
+#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
+#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
+#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
+#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+
+#define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
+
+float NormalizeColor( vec3_c in, vec3_p out );
+
+int VectorCompare( vec3_c v1, vec3_c v2 );
+float VectorLength( vec3_c v );
+float Distance( vec3_c p1, vec3_c p2 );
+float DistanceSquared( vec3_c p1, vec3_c p2 );
+float VectorNormalize (vec3_p v); // returns vector length
+void VectorNormalizeFast(vec3_p v); // does NOT return vector length, uses rsqrt approximation
+float VectorNormalize2( vec3_c v, vec3_p out );
+void VectorInverse (vec3_p v);
+void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out );
+void VectorPolar(vec3_p v, float radius, float theta, float phi);
+void VectorSnap(vec3_p v);
+void Vector53Copy( const idVec5_t &in, vec3_p out);
+void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out);
+void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out);
+void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out);
+void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out);
+
+
+int Q_log2(int val);
+
+int Q_rand( int *seed );
+float Q_random( int *seed );
+float Q_crandom( int *seed );
+
+#define random() ((rand () & 0x7fff) / ((float)0x7fff))
+#define crandom() (2.0 * (random() - 0.5))
+
+float Q_rint( float in );
+
+void vectoangles( vec3_c value1, angles_p angles);
+void AnglesToAxis( angles_c angles, mat3_p axis );
+
+void AxisCopy( mat3_c in, mat3_p out );
+qboolean AxisRotated( mat3_c in ); // assumes a non-degenerate axis
+
+int SignbitsForNormal( vec3_c normal );
+int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p );
+
+float AngleMod(float a);
+float LerpAngle (float from, float to, float frac);
+float AngleSubtract( float a1, float a2 );
+void AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 );
+
+float AngleNormalize360 ( float angle );
+float AngleNormalize180 ( float angle );
+float AngleDelta ( float angle1, float angle2 );
+
+qboolean PlaneFromPoints( vec4_t &plane, vec3_c a, vec3_c b, vec3_c c );
+void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal );
+void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees );
+void RotateAroundDirection( mat3_p axis, float yaw );
+void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up );
+// perpendicular vector could be replaced by this
+
+int PlaneTypeForNormal( vec3_c normal );
+
+void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out );
+void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out ); // in2 is transposed during multiply
+void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out );
+void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system.
+void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up);
+void PerpendicularVector( vec3_p dst, vec3_c src );
+
+float TriangleArea( vec3_c a, vec3_c b, vec3_c c );
+#endif // __cplusplus
+
+//=============================================
+
+float Com_Clamp( float min, float max, float value );
+
+#define FILE_HASH_SIZE 1024
+int Com_HashString( const char *fname );
+
+char *Com_SkipPath( char *pathname );
+
+// it is ok for out == in
+void Com_StripExtension( const char *in, char *out );
+
+// "extension" should include the dot: ".map"
+void Com_DefaultExtension( char *path, int maxSize, const char *extension );
+
+int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] );
+
+/*
+=====================================================================================
+
+SCRIPT PARSING
+
+=====================================================================================
+*/
+
+// this just controls the comment printing, it doesn't actually load a file
+void Com_BeginParseSession( const char *filename );
+void Com_EndParseSession( void );
+
+int Com_GetCurrentParseLine( void );
+
+// Will never return NULL, just empty strings.
+// An empty string will only be returned at end of file.
+// ParseOnLine will return empty if there isn't another token on this line
+
+// this funny typedef just means a moving pointer into a const char * buffer
+const char *Com_Parse( const char *(*data_p) );
+const char *Com_ParseOnLine( const char *(*data_p) );
+const char *Com_ParseRestOfLine( const char *(*data_p) );
+
+void Com_UngetToken( void );
+
+#ifdef __cplusplus
+void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse );
+#else
+void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning );
+#endif
+
+void Com_ScriptError( const char *msg, ... );
+void Com_ScriptWarning( const char *msg, ... );
+
+void Com_SkipBracedSection( const char *(*program) );
+void Com_SkipRestOfLine( const char *(*data) );
+
+float Com_ParseFloat( const char *(*buf_p) );
+int Com_ParseInt( const char *(*buf_p) );
+
+void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m );
+void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m );
+void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m );
+
+//=====================================================================================
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
+
+
+// mode parm for FS_FOpenFile
+typedef enum {
+ FS_READ,
+ FS_WRITE,
+ FS_APPEND,
+ FS_APPEND_SYNC
+} fsMode_t;
+
+typedef enum {
+ FS_SEEK_CUR,
+ FS_SEEK_END,
+ FS_SEEK_SET
+} fsOrigin_t;
+
+//=============================================
+
+int Q_isprint( int c );
+int Q_islower( int c );
+int Q_isupper( int c );
+int Q_isalpha( int c );
+
+// portable case insensitive compare
+int Q_stricmp (const char *s1, const char *s2);
+int Q_strncmp (const char *s1, const char *s2, int n);
+int Q_stricmpn (const char *s1, const char *s2, int n);
+char *Q_strlwr( char *s1 );
+char *Q_strupr( char *s1 );
+char *Q_strrchr( const char* string, int c );
+
+// buffer size safe library replacements
+void Q_strncpyz( char *dest, const char *src, int destsize );
+void Q_strcat( char *dest, int size, const char *src );
+
+// strlen that discounts Quake color sequences
+int Q_PrintStrlen( const char *string );
+// removes color sequences from string
+char *Q_CleanStr( char *string );
+
+int Com_Filter( const char *filter, const char *name, int casesensitive );
+const char *Com_StringContains( const char *str1, const char *str2, int casesensitive );
+
+
+//=============================================
+
+short BigShort(short l);
+short LittleShort(short l);
+int BigLong (int l);
+int LittleLong (int l);
+float BigFloat (float l);
+float LittleFloat (float l);
+
+void Swap_Init (void);
+char * QDECL va(char *format, ...);
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+//=============================================
+#ifdef __cplusplus
+//
+// mapfile parsing
+//
+typedef struct ePair_s {
+ char *key;
+ char *value;
+} ePair_t;
+
+typedef struct mapSide_s {
+ char material[MAX_QPATH];
+ vec4_t plane;
+ vec4_t textureVectors[2];
+} mapSide_t;
+
+typedef struct {
+ int numSides;
+ mapSide_t **sides;
+} mapBrush_t;
+
+typedef struct {
+ idVec3_t xyz;
+ float st[2];
+} patchVertex_t;
+
+typedef struct {
+ char material[MAX_QPATH];
+ int width, height;
+ patchVertex_t *patchVerts;
+} mapPatch_t;
+
+typedef struct {
+ char modelName[MAX_QPATH];
+ float matrix[16];
+} mapModel_t;
+
+typedef struct mapPrimitive_s {
+ int numEpairs;
+ ePair_t **ePairs;
+
+ // only one of these will be non-NULL
+ mapBrush_t *brush;
+ mapPatch_t *patch;
+ mapModel_t *model;
+} mapPrimitive_t;
+
+typedef struct mapEntity_s {
+ int numPrimitives;
+ mapPrimitive_t **primitives;
+
+ int numEpairs;
+ ePair_t **ePairs;
+} mapEntity_t;
+
+typedef struct {
+ int numEntities;
+ mapEntity_t **entities;
+} mapFile_t;
+
+
+// the order of entities, brushes, and sides will be maintained, the
+// lists won't be swapped on each load or save
+mapFile_t *ParseMapFile( const char *text );
+void FreeMapFile( mapFile_t *mapFile );
+void WriteMapFile( const mapFile_t *mapFile, FILE *f );
+
+// key names are case-insensitive
+const char *ValueForMapEntityKey( const mapEntity_t *ent, const char *key );
+float FloatForMapEntityKey( const mapEntity_t *ent, const char *key );
+qboolean GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3_t &vec );
+
+typedef struct {
+ idVec3_t xyz;
+ idVec2_t st;
+ idVec3_t normal;
+ idVec3_t tangents[2];
+ byte smoothing[4]; // colors for silhouette smoothing
+} drawVert_t;
+
+typedef struct {
+ int width, height;
+ drawVert_t *verts;
+} drawVertMesh_t;
+
+// Tesselate a map patch into smoothed, drawable vertexes
+// MaxError of around 4 is reasonable
+drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError );
+#endif // __cplusplus
+
+//=========================================
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+void QDECL Com_Error( int level, const char *error, ... );
+void QDECL Com_Printf( const char *msg, ... );
+void QDECL Com_DPrintf( const char *msg, ... );
+
+#ifdef __cplusplus
+ }
+#endif
+
+
+typedef struct {
+ qboolean frameMemory;
+ int currentElements;
+ int maxElements; // will reallocate and move when exceeded
+ void **elements;
+} growList_t;
+
+// you don't need to init the growlist if you don't mind it growing and moving
+// the list as it expands
+void Com_InitGrowList( growList_t *list, int maxElements );
+int Com_AddToGrowList( growList_t *list, void *data );
+void *Com_GrowListElement( const growList_t *list, int index );
+int Com_IndexForGrowListElement( const growList_t *list, const void *element );
+
+
+//
+// key / value info strings
+//
+char *Info_ValueForKey( const char *s, const char *key );
+void Info_RemoveKey( char *s, const char *key );
+void Info_SetValueForKey( char *s, const char *key, const char *value );
+qboolean Info_Validate( const char *s );
+void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] );
+
+// get cvar defs, collision defs, etc
+//#include "../shared/interface.h"
+
+// get key code numbers for events
+//#include "../shared/keycodes.h"
+
+#ifdef __cplusplus
+// get the polygon winding functions
+//#include "../shared/windings.h"
+
+// get the flags class
+//#include "../shared/idflags.h"
+#endif // __cplusplus
+
+#endif // __Q_SHARED_H
+
diff --git a/q3radiant/splines/splines.cpp b/q3radiant/splines/splines.cpp
new file mode 100755
index 0000000..9c2b804
--- /dev/null
+++ b/q3radiant/splines/splines.cpp
@@ -0,0 +1,1244 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+//#include "stdafx.h"
+//#include "qe3.h"
+
+#include "q_shared.h"
+#include "splines.h"
+
+extern "C" {
+int FS_Write( const void *buffer, int len, fileHandle_t h );
+int FS_ReadFile( const char *qpath, void **buffer );
+void FS_FreeFile( void *buffer );
+fileHandle_t FS_FOpenFileWrite( const char *filename );
+void FS_FCloseFile( fileHandle_t f );
+}
+
+float Q_fabs( float f ) {
+ int tmp = * ( int * ) &f;
+ tmp &= 0x7FFFFFFF;
+ return * ( float * ) &tmp;
+}
+
+
+//#include "../shared/windings.h"
+//#include "../qcommon/qcommon.h"
+//#include "../sys/sys_public.h"
+//#include "../game/game_entity.h"
+
+idCameraDef splineList;
+idCameraDef *g_splineList = &splineList;
+
+idVec3_t idSplineList::zero(0,0,0);
+
+void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label) {
+ qglColor3fv(color);
+ qglPointSize(size);
+ qglBegin(GL_POINTS);
+ qglVertex3fv(point);
+ qglEnd();
+ idVec3_t v = point;
+ v.x += 1;
+ v.y += 1;
+ v.z += 1;
+ qglRasterPos3fv (v);
+ qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);
+}
+
+
+void glBox(idVec3_t &color, idVec3_t &point, float size) {
+ idVec3_t mins(point);
+ idVec3_t maxs(point);
+ mins[0] -= size;
+ mins[1] += size;
+ mins[2] -= size;
+ maxs[0] += size;
+ maxs[1] -= size;
+ maxs[2] += size;
+ qglColor3fv(color);
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f(mins[0],mins[1],mins[2]);
+ qglVertex3f(maxs[0],mins[1],mins[2]);
+ qglVertex3f(maxs[0],maxs[1],mins[2]);
+ qglVertex3f(mins[0],maxs[1],mins[2]);
+ qglEnd();
+ qglBegin(GL_LINE_LOOP);
+ qglVertex3f(mins[0],mins[1],maxs[2]);
+ qglVertex3f(maxs[0],mins[1],maxs[2]);
+ qglVertex3f(maxs[0],maxs[1],maxs[2]);
+ qglVertex3f(mins[0],maxs[1],maxs[2]);
+ qglEnd();
+
+ qglBegin(GL_LINES);
+ qglVertex3f(mins[0],mins[1],mins[2]);
+ qglVertex3f(mins[0],mins[1],maxs[2]);
+ qglVertex3f(mins[0],maxs[1],maxs[2]);
+ qglVertex3f(mins[0],maxs[1],mins[2]);
+ qglVertex3f(maxs[0],mins[1],mins[2]);
+ qglVertex3f(maxs[0],mins[1],maxs[2]);
+ qglVertex3f(maxs[0],maxs[1],maxs[2]);
+ qglVertex3f(maxs[0],maxs[1],mins[2]);
+ qglEnd();
+
+}
+
+void splineTest() {
+ //g_splineList->load("p:/doom/base/maps/test_base1.camera");
+}
+
+void splineDraw() {
+ //g_splineList->addToRenderer();
+}
+
+
+//extern void D_DebugLine( const idVec3_t &color, const idVec3_t &start, const idVec3_t &end );
+
+void debugLine(idVec3_t &color, float x, float y, float z, float x2, float y2, float z2) {
+ idVec3_t from(x, y, z);
+ idVec3_t to(x2, y2, z2);
+ //D_DebugLine(color, from, to);
+}
+
+void idSplineList::addToRenderer() {
+
+ if (controlPoints.Num() == 0) {
+ return;
+ }
+
+ idVec3_t mins, maxs;
+ idVec3_t yellow(1.0, 1.0, 0);
+ idVec3_t white(1.0, 1.0, 1.0);
+ int i;
+
+ for(i = 0; i < controlPoints.Num(); i++) {
+ VectorCopy(*controlPoints[i], mins);
+ VectorCopy(mins, maxs);
+ mins[0] -= 8;
+ mins[1] += 8;
+ mins[2] -= 8;
+ maxs[0] += 8;
+ maxs[1] -= 8;
+ maxs[2] += 8;
+ debugLine( yellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]);
+ debugLine( yellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]);
+ debugLine( yellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]);
+ debugLine( yellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]);
+
+ debugLine( yellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]);
+ debugLine( yellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]);
+ debugLine( yellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]);
+ debugLine( yellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]);
+
+ }
+
+ int step = 0;
+ idVec3_t step1;
+ for(i = 3; i < controlPoints.Num(); i++) {
+ for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) {
+ float x = 0;
+ float y = 0;
+ float z = 0;
+ for (int j = 0; j < 4; j++) {
+ x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
+ y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
+ z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
+ }
+ if (step == 0) {
+ step1[0] = x;
+ step1[1] = y;
+ step1[2] = z;
+ step = 1;
+ } else {
+ debugLine( white, step1[0], step1[1], step1[2], x, y, z);
+ step = 0;
+ }
+
+ }
+ }
+}
+
+void idSplineList::buildSpline() {
+ //int start = Sys_Milliseconds();
+ clearSpline();
+ for(int i = 3; i < controlPoints.Num(); i++) {
+ for (float tension = 0.0f; tension < 1.001f; tension += granularity) {
+ float x = 0;
+ float y = 0;
+ float z = 0;
+ for (int j = 0; j < 4; j++) {
+ x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
+ y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
+ z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
+ }
+ splinePoints.Append(new idVec3_t(x, y, z));
+ }
+ }
+ dirty = false;
+ //Com_Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000);
+}
+
+
+void idSplineList::draw(bool editMode) {
+ int i;
+ vec4_t yellow(1, 1, 0, 1);
+
+ if (controlPoints.Num() == 0) {
+ return;
+ }
+
+ if (dirty) {
+ buildSpline();
+ }
+
+
+ qglColor3fv(controlColor);
+ qglPointSize(5);
+
+ qglBegin(GL_POINTS);
+ for (i = 0; i < controlPoints.Num(); i++) {
+ qglVertex3fv(*controlPoints[i]);
+ }
+ qglEnd();
+
+ if (editMode) {
+ for(i = 0; i < controlPoints.Num(); i++) {
+ glBox(activeColor, *controlPoints[i], 4);
+ }
+ }
+
+ //Draw the curve
+ qglColor3fv(pathColor);
+ qglBegin(GL_LINE_STRIP);
+ int count = splinePoints.Num();
+ for (i = 0; i < count; i++) {
+ qglVertex3fv(*splinePoints[i]);
+ }
+ qglEnd();
+
+ if (editMode) {
+ qglColor3fv(segmentColor);
+ qglPointSize(3);
+ qglBegin(GL_POINTS);
+ for (i = 0; i < count; i++) {
+ qglVertex3fv(*splinePoints[i]);
+ }
+ qglEnd();
+ }
+ if (count > 0) {
+ //assert(activeSegment >=0 && activeSegment < count);
+ if (activeSegment >=0 && activeSegment < count) {
+ glBox(activeColor, *splinePoints[activeSegment], 6);
+ glBox(yellow, *splinePoints[activeSegment], 8);
+ }
+ }
+
+}
+
+float idSplineList::totalDistance() {
+
+ if (controlPoints.Num() == 0) {
+ return 0.0;
+ }
+
+ if (dirty) {
+ buildSpline();
+ }
+
+ float dist = 0.0;
+ idVec3_t temp;
+ int count = splinePoints.Num();
+ for(int i = 1; i < count; i++) {
+ temp = *splinePoints[i-1];
+ temp -= *splinePoints[i];
+ dist += temp.Length();
+ }
+ return dist;
+}
+
+void idSplineList::initPosition(long bt, long totalTime) {
+
+ if (dirty) {
+ buildSpline();
+ }
+
+ if (splinePoints.Num() == 0) {
+ return;
+ }
+
+ baseTime = bt;
+ time = totalTime;
+
+ // calc distance to travel ( this will soon be broken into time segments )
+ splineTime.Clear();
+ splineTime.Append(0);
+ float dist = totalDistance();
+ float distSoFar = 0.0;
+ idVec3_t temp;
+ int count = splinePoints.Num();
+ //for(int i = 2; i < count - 1; i++) {
+ for(int i = 1; i < count; i++) {
+ temp = *splinePoints[i-1];
+ temp -= *splinePoints[i];
+ distSoFar += temp.Length();
+ float percent = distSoFar / dist;
+ percent *= totalTime;
+ splineTime.Append(percent + bt);
+ }
+ assert(splineTime.Num() == splinePoints.Num());
+ activeSegment = 0;
+}
+
+
+
+float idSplineList::calcSpline(int step, float tension) {
+ switch(step) {
+ case 0: return (pow(1 - tension, 3)) / 6;
+ case 1: return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6;
+ case 2: return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6;
+ case 3: return pow(tension, 3) / 6;
+ }
+ return 0.0;
+}
+
+
+
+void idSplineList::updateSelection(const idVec3_t &move) {
+ if (selected) {
+ dirty = true;
+ VectorAdd(*selected, move, *selected);
+ }
+}
+
+
+void idSplineList::setSelectedPoint(idVec3_t *p) {
+ if (p) {
+ p->Snap();
+ for(int i = 0; i < controlPoints.Num(); i++) {
+ if (*p == *controlPoints[i]) {
+ selected = controlPoints[i];
+ }
+ }
+ } else {
+ selected = NULL;
+ }
+}
+
+const idVec3_t *idSplineList::getPosition(long t) {
+ static idVec3_t interpolatedPos;
+
+ int count = splineTime.Num();
+ if (count == 0) {
+ return &zero;
+ }
+
+ assert(splineTime.Num() == splinePoints.Num());
+
+ while (activeSegment < count) {
+ if (splineTime[activeSegment] >= t) {
+ if (activeSegment > 0 && activeSegment < count - 1) {
+ float timeHi = splineTime[activeSegment + 1];
+ float timeLo = splineTime[activeSegment - 1];
+ //float percent = (float)(baseTime + time - t) / time;
+ float percent = (timeHi - t) / (timeHi - timeLo);
+ // pick two bounding points
+ idVec3_t v1 = *splinePoints[activeSegment-1];
+ idVec3_t v2 = *splinePoints[activeSegment+1];
+ v2 *= (1.0 - percent);
+ v1 *= percent;
+ v2 += v1;
+ interpolatedPos = v2;
+ return &interpolatedPos;
+ }
+ return splinePoints[activeSegment];
+ } else {
+ activeSegment++;
+ }
+ }
+ return splinePoints[count-1];
+}
+
+void idSplineList::parse(const char *(*text) ) {
+ const char *token;
+ //Com_MatchToken( text, "{" );
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !Q_stricmp (token, "}") ) {
+ break;
+ }
+
+ do {
+ // if token is not a brace, it is a key for a key/value pair
+ if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) {
+ break;
+ }
+
+ Com_UngetToken();
+ idStr key = Com_ParseOnLine(text);
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key.c_str(), "granularity") == 0) {
+ granularity = atof(token);
+ } else if (Q_stricmp(key.c_str(), "name") == 0) {
+ name = token;
+ }
+ token = Com_Parse(text);
+
+ } while (1);
+
+ if ( !Q_stricmp (token, "}") ) {
+ break;
+ }
+
+ Com_UngetToken();
+ // read the control point
+ idVec3_t point;
+ Com_Parse1DMatrix( text, 3, point );
+ addPoint(point.x, point.y, point.z);
+ } while (1);
+
+ //Com_UngetToken();
+ //Com_MatchToken( text, "}" );
+ dirty = true;
+}
+
+void idSplineList::write(fileHandle_t file, const char *p) {
+ idStr s = va("\t\t%s {\n", p);
+ FS_Write(s.c_str(), s.length(), file);
+ //s = va("\t\tname %s\n", name.c_str());
+ //FS_Write(s.c_str(), s.length(), file);
+ s = va("\t\t\tgranularity %f\n", granularity);
+ FS_Write(s.c_str(), s.length(), file);
+ int count = controlPoints.Num();
+ for (int i = 0; i < count; i++) {
+ s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z);
+ FS_Write(s.c_str(), s.length(), file);
+ }
+ s = "\t\t}\n";
+ FS_Write(s.c_str(), s.length(), file);
+}
+
+
+void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) {
+#if 0
+ if (!cameraSpline.validTime()) {
+ buildCamera();
+ }
+ double d = (double)segment / numSegments();
+ getCameraInfo(d * totalTime * 1000, origin, direction, fov);
+#endif
+/*
+ if (!cameraSpline.validTime()) {
+ buildCamera();
+ }
+ origin = *cameraSpline.getSegmentPoint(segment);
+
+
+ idVec3_t temp;
+
+ int numTargets = getTargetSpline()->controlPoints.Num();
+ int count = cameraSpline.splineTime.Num();
+ if (numTargets == 0) {
+ // follow the path
+ if (cameraSpline.getActiveSegment() < count - 1) {
+ temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
+ }
+ } else if (numTargets == 1) {
+ temp = *getTargetSpline()->controlPoints[0];
+ } else {
+ temp = *getTargetSpline()->getSegmentPoint(segment);
+ }
+
+ temp -= origin;
+ temp.Normalize();
+ direction = temp;
+*/
+}
+
+bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) {
+
+
+ if ((time - startTime) / 1000 > totalTime) {
+ return false;
+ }
+
+
+ for (int i = 0; i < events.Num(); i++) {
+ if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
+ events[i]->setTriggered(true);
+ if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
+ setActiveTargetByName(events[i]->getParam());
+ getActiveTarget()->start(startTime + events[i]->getTime());
+ //Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam());
+ } else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
+ //idEntity *ent = NULL;
+ //ent = level.FindTarget( ent, events[i]->getParam());
+ //if (ent) {
+ // ent->signal( SIG_TRIGGER );
+ // ent->ProcessEvent( &EV_Activate, world );
+ //}
+ } else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
+ //*fv = fov = atof(events[i]->getParam());
+ } else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
+ return false;
+ }
+ }
+ }
+
+ origin = *cameraPosition->getPosition(time);
+
+ *fv = fov.getFOV(time);
+
+ idVec3_t temp = origin;
+
+ int numTargets = targetPositions.Num();
+ if (numTargets == 0) {
+/*
+ // follow the path
+ if (cameraSpline.getActiveSegment() < count - 1) {
+ temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
+ if (temp == origin) {
+ int index = cameraSpline.getActiveSegment() + 2;
+ while (temp == origin && index < count - 1) {
+ temp = *cameraSpline.splinePoints[index++];
+ }
+ }
+ }
+*/
+ } else {
+ temp = *getActiveTarget()->getPosition(time);
+ }
+
+ temp -= origin;
+ temp.Normalize();
+ direction = temp;
+
+ return true;
+}
+
+bool idCameraDef::waitEvent(int index) {
+ //for (int i = 0; i < events.Num(); i++) {
+ // if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
+ // return true;
+ // }
+ //}
+ return false;
+}
+
+
+#define NUM_CCELERATION_SEGS 10
+#define CELL_AMT 5
+
+void idCameraDef::buildCamera() {
+ int i;
+ int lastSwitch = 0;
+ idList<float> waits;
+ idList<int> targets;
+
+ totalTime = baseTime;
+ cameraPosition->setTime(totalTime * 1000);
+ // we have a base time layout for the path and the target path
+ // now we need to layer on any wait or speed changes
+ for (i = 0; i < events.Num(); i++) {
+ idCameraEvent *ev = events[i];
+ events[i]->setTriggered(false);
+ switch (events[i]->getType()) {
+ case idCameraEvent::EVENT_TARGET : {
+ targets.Append(i);
+ break;
+ }
+ case idCameraEvent::EVENT_WAIT : {
+ waits.Append(atof(events[i]->getParam()));
+ cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
+ break;
+ }
+ case idCameraEvent::EVENT_TARGETWAIT : {
+ //targetWaits.Append(i);
+ break;
+ }
+ case idCameraEvent::EVENT_SPEED : {
+/*
+ // take the average delay between up to the next five segments
+ float adjust = atof(events[i]->getParam());
+ int index = events[i]->getSegment();
+ total = 0;
+ count = 0;
+
+ // get total amount of time over the remainder of the segment
+ for (j = index; j < cameraSpline.numSegments() - 1; j++) {
+ total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
+ count++;
+ }
+
+ // multiply that by the adjustment
+ double newTotal = total * adjust;
+ // what is the difference..
+ newTotal -= total;
+ totalTime += newTotal / 1000;
+
+ // per segment difference
+ newTotal /= count;
+ int additive = newTotal;
+
+ // now propogate that difference out to each segment
+ for (j = index; j < cameraSpline.numSegments(); j++) {
+ cameraSpline.addSegmentTime(j, additive);
+ additive += newTotal;
+ }
+ break;
+*/
+ }
+ }
+ }
+
+
+ for (i = 0; i < waits.Num(); i++) {
+ totalTime += waits[i];
+ }
+
+ // on a new target switch, we need to take time to this point ( since last target switch )
+ // and allocate it across the active target, then reset time to this point
+ long timeSoFar = 0;
+ long total = totalTime * 1000;
+ for (i = 0; i < targets.Num(); i++) {
+ long t;
+ if (i < targets.Num() - 1) {
+ t = events[targets[i+1]]->getTime();
+ } else {
+ t = total - timeSoFar;
+ }
+ // t is how much time to use for this target
+ setActiveTargetByName(events[targets[i]]->getParam());
+ getActiveTarget()->setTime(t);
+ timeSoFar += t;
+ }
+
+
+}
+
+void idCameraDef::startCamera(long t) {
+ buildCamera();
+ cameraPosition->start(t);
+ //for (int i = 0; i < targetPositions.Num(); i++) {
+ // targetPositions[i]->
+ //}
+ startTime = t;
+ cameraRunning = true;
+}
+
+
+void idCameraDef::parse(const char *(*text) ) {
+
+ const char *token;
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !Q_stricmp (token, "}") ) {
+ break;
+ }
+
+ if (Q_stricmp(token, "time") == 0) {
+ baseTime = Com_ParseFloat(text);
+ }
+
+ if (Q_stricmp(token, "camera_fixed") == 0) {
+ cameraPosition = new idFixedPosition();
+ cameraPosition->parse(text);
+ }
+
+ if (Q_stricmp(token, "camera_interpolated") == 0) {
+ cameraPosition = new idInterpolatedPosition();
+ cameraPosition->parse(text);
+ }
+
+ if (Q_stricmp(token, "camera_spline") == 0) {
+ cameraPosition = new idSplinePosition();
+ cameraPosition->parse(text);
+ }
+
+ if (Q_stricmp(token, "target_fixed") == 0) {
+ idFixedPosition *pos = new idFixedPosition();
+ pos->parse(text);
+ targetPositions.Append(pos);
+ }
+
+ if (Q_stricmp(token, "target_interpolated") == 0) {
+ idInterpolatedPosition *pos = new idInterpolatedPosition();
+ pos->parse(text);
+ targetPositions.Append(pos);
+ }
+
+ if (Q_stricmp(token, "target_spline") == 0) {
+ idSplinePosition *pos = new idSplinePosition();
+ pos->parse(text);
+ targetPositions.Append(pos);
+ }
+
+ if (Q_stricmp(token, "fov") == 0) {
+ fov.parse(text);
+ }
+
+ if (Q_stricmp(token, "event") == 0) {
+ idCameraEvent *event = new idCameraEvent();
+ event->parse(text);
+ addEvent(event);
+ }
+
+
+ } while (1);
+
+ Com_UngetToken();
+ Com_MatchToken( text, "}" );
+
+}
+
+bool idCameraDef::load(const char *filename) {
+ char *buf;
+ const char *buf_p;
+ int length = FS_ReadFile( filename, (void **)&buf );
+ if ( !buf ) {
+ return false;
+ }
+
+ clear();
+ Com_BeginParseSession( filename );
+ buf_p = buf;
+ parse(&buf_p);
+ Com_EndParseSession();
+ FS_FreeFile( buf );
+
+ return true;
+}
+
+void idCameraDef::save(const char *filename) {
+ fileHandle_t file = FS_FOpenFileWrite(filename);
+ if (file) {
+ int i;
+ idStr s = "cameraPathDef { \n";
+ FS_Write(s.c_str(), s.length(), file);
+ s = va("\ttime %f\n", baseTime);
+ FS_Write(s.c_str(), s.length(), file);
+
+ cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr()));
+
+ for (i = 0; i < numTargets(); i++) {
+ targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr()));
+ }
+
+ for (i = 0; i < events.Num(); i++) {
+ events[i]->write(file, "event");
+ }
+
+ fov.write(file, "fov");
+
+ s = "}\n";
+ FS_Write(s.c_str(), s.length(), file);
+ }
+ FS_FCloseFile(file);
+}
+
+int idCameraDef::sortEvents(const void *p1, const void *p2) {
+ idCameraEvent *ev1 = (idCameraEvent*)(p1);
+ idCameraEvent *ev2 = (idCameraEvent*)(p2);
+
+ if (ev1->getTime() > ev2->getTime()) {
+ return -1;
+ }
+ if (ev1->getTime() < ev2->getTime()) {
+ return 1;
+ }
+ return 0;
+}
+
+void idCameraDef::addEvent(idCameraEvent *event) {
+ events.Append(event);
+ //events.Sort(&sortEvents);
+
+}
+void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
+ addEvent(new idCameraEvent(t, param, time));
+ buildCamera();
+}
+
+
+const char *idCameraEvent::eventStr[] = {
+ "NA",
+ "WAIT",
+ "TARGETWAIT",
+ "SPEED",
+ "TARGET",
+ "SNAPTARGET",
+ "FOV",
+ "SCRIPT",
+ "TRIGGER",
+ "STOP"
+};
+
+void idCameraEvent::parse(const char *(*text) ) {
+ const char *token;
+ Com_MatchToken( text, "{" );
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ // here we may have to jump over brush epairs ( only used in editor )
+ do {
+ // if token is not a brace, it is a key for a key/value pair
+ if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
+ break;
+ }
+
+ Com_UngetToken();
+ idStr key = Com_ParseOnLine(text);
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key.c_str(), "type") == 0) {
+ type = static_cast<idCameraEvent::eventType>(atoi(token));
+ } else if (Q_stricmp(key.c_str(), "param") == 0) {
+ paramStr = token;
+ } else if (Q_stricmp(key.c_str(), "time") == 0) {
+ time = atoi(token);
+ }
+ token = Com_Parse(text);
+
+ } while (1);
+
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ } while (1);
+
+ Com_UngetToken();
+ Com_MatchToken( text, "}" );
+}
+
+void idCameraEvent::write(fileHandle_t file, const char *name) {
+ idStr s = va("\t%s {\n", name);
+ FS_Write(s.c_str(), s.length(), file);
+ s = va("\t\ttype %d\n", static_cast<int>(type));
+ FS_Write(s.c_str(), s.length(), file);
+ s = va("\t\tparam %s\n", paramStr.c_str());
+ FS_Write(s.c_str(), s.length(), file);
+ s = va("\t\ttime %d\n", time);
+ FS_Write(s.c_str(), s.length(), file);
+ s = "\t}\n";
+ FS_Write(s.c_str(), s.length(), file);
+}
+
+
+const char *idCameraPosition::positionStr[] = {
+ "Fixed",
+ "Interpolated",
+ "Spline",
+};
+
+
+
+const idVec3_t *idInterpolatedPosition::getPosition(long t) {
+ static idVec3_t interpolatedPos;
+
+ float velocity = getVelocity(t);
+ float timePassed = t - lastTime;
+ lastTime = t;
+
+ // convert to seconds
+ timePassed /= 1000;
+
+ float distToTravel = timePassed *= velocity;
+
+ idVec3_t temp = startPos;
+ temp -= endPos;
+ float distance = temp.Length();
+
+ distSoFar += distToTravel;
+ float percent = (float)(distSoFar) / distance;
+
+ if (percent > 1.0) {
+ percent = 1.0;
+ } else if (percent < 0.0) {
+ percent = 0.0;
+ }
+
+ // the following line does a straigt calc on percentage of time
+ // float percent = (float)(startTime + time - t) / time;
+
+ idVec3_t v1 = startPos;
+ idVec3_t v2 = endPos;
+ v1 *= (1.0 - percent);
+ v2 *= percent;
+ v1 += v2;
+ interpolatedPos = v1;
+ return &interpolatedPos;
+}
+
+
+void idCameraFOV::parse(const char *(*text) ) {
+ const char *token;
+ Com_MatchToken( text, "{" );
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ // here we may have to jump over brush epairs ( only used in editor )
+ do {
+ // if token is not a brace, it is a key for a key/value pair
+ if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
+ break;
+ }
+
+ Com_UngetToken();
+ idStr key = Com_ParseOnLine(text);
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key.c_str(), "fov") == 0) {
+ fov = atof(token);
+ } else if (Q_stricmp(key.c_str(), "startFOV") == 0) {
+ startFOV = atof(token);
+ } else if (Q_stricmp(key.c_str(), "endFOV") == 0) {
+ endFOV = atof(token);
+ } else if (Q_stricmp(key.c_str(), "time") == 0) {
+ time = atoi(token);
+ }
+ token = Com_Parse(text);
+
+ } while (1);
+
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ } while (1);
+
+ Com_UngetToken();
+ Com_MatchToken( text, "}" );
+}
+
+bool idCameraPosition::parseToken(const char *key, const char *(*text)) {
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key, "time") == 0) {
+ time = atol(token);
+ return true;
+ } else if (Q_stricmp(key, "type") == 0) {
+ type = static_cast<idCameraPosition::positionType>(atoi(token));
+ return true;
+ } else if (Q_stricmp(key, "velocity") == 0) {
+ long t = atol(token);
+ token = Com_Parse(text);
+ long d = atol(token);
+ token = Com_Parse(text);
+ float s = atof(token);
+ addVelocity(t, d, s);
+ return true;
+ } else if (Q_stricmp(key, "baseVelocity") == 0) {
+ baseVelocity = atof(token);
+ return true;
+ } else if (Q_stricmp(key, "name") == 0) {
+ name = token;
+ return true;
+ } else if (Q_stricmp(key, "time") == 0) {
+ time = atoi(token);
+ return true;
+ }
+ Com_UngetToken();
+ return false;
+}
+
+
+
+void idFixedPosition::parse(const char *(*text) ) {
+ const char *token;
+ Com_MatchToken( text, "{" );
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ // here we may have to jump over brush epairs ( only used in editor )
+ do {
+ // if token is not a brace, it is a key for a key/value pair
+ if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
+ break;
+ }
+
+ Com_UngetToken();
+ idStr key = Com_ParseOnLine(text);
+
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key.c_str(), "pos") == 0) {
+ Com_UngetToken();
+ Com_Parse1DMatrix( text, 3, pos );
+ } else {
+ Com_UngetToken();
+ idCameraPosition::parseToken(key.c_str(), text);
+ }
+ token = Com_Parse(text);
+
+ } while (1);
+
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ } while (1);
+
+ Com_UngetToken();
+ Com_MatchToken( text, "}" );
+}
+
+void idInterpolatedPosition::parse(const char *(*text) ) {
+ const char *token;
+ Com_MatchToken( text, "{" );
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ // here we may have to jump over brush epairs ( only used in editor )
+ do {
+ // if token is not a brace, it is a key for a key/value pair
+ if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
+ break;
+ }
+
+ Com_UngetToken();
+ idStr key = Com_ParseOnLine(text);
+
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key.c_str(), "startPos") == 0) {
+ Com_UngetToken();
+ Com_Parse1DMatrix( text, 3, startPos );
+ } else if (Q_stricmp(key.c_str(), "endPos") == 0) {
+ Com_UngetToken();
+ Com_Parse1DMatrix( text, 3, endPos );
+ } else {
+ Com_UngetToken();
+ idCameraPosition::parseToken(key.c_str(), text);
+ }
+ token = Com_Parse(text);
+
+ } while (1);
+
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ } while (1);
+
+ Com_UngetToken();
+ Com_MatchToken( text, "}" );
+}
+
+
+void idSplinePosition::parse(const char *(*text) ) {
+ const char *token;
+ Com_MatchToken( text, "{" );
+ do {
+ token = Com_Parse( text );
+
+ if ( !token[0] ) {
+ break;
+ }
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ // here we may have to jump over brush epairs ( only used in editor )
+ do {
+ // if token is not a brace, it is a key for a key/value pair
+ if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
+ break;
+ }
+
+ Com_UngetToken();
+ idStr key = Com_ParseOnLine(text);
+
+ const char *token = Com_Parse(text);
+ if (Q_stricmp(key.c_str(), "target") == 0) {
+ target.parse(text);
+ } else {
+ Com_UngetToken();
+ idCameraPosition::parseToken(key.c_str(), text);
+ }
+ token = Com_Parse(text);
+
+ } while (1);
+
+ if ( !strcmp (token, "}") ) {
+ break;
+ }
+
+ } while (1);
+
+ Com_UngetToken();
+ Com_MatchToken( text, "}" );
+}
+
+
+
+void idCameraFOV::write(fileHandle_t file, const char *p) {
+ idStr s = va("\t%s {\n", p);
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\tfov %f\n", fov);
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\tstartFOV %f\n", startFOV);
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\tendFOV %f\n", endFOV);
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\ttime %i\n", time);
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = "\t}\n";
+ FS_Write(s.c_str(), s.length(), file);
+}
+
+
+void idCameraPosition::write(fileHandle_t file, const char *p) {
+
+ idStr s = va("\t\ttime %i\n", time);
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\ttype %i\n", static_cast<int>(type));
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\tname %s\n", name.c_str());
+ FS_Write(s.c_str(), s.length(), file);
+
+ s = va("\t\tbaseVelocity %f\n", baseVelocity);
+ FS_Write(s.c_str(), s.length(), file);
+
+ for (int i = 0; i < velocities.Num(); i++) {
+ s = va("\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed);
+ FS_Write(s.c_str(), s.length(), file);
+ }
+
+}
+
+void idFixedPosition::write(fileHandle_t file, const char *p) {
+ idStr s = va("\t%s {\n", p);
+ FS_Write(s.c_str(), s.length(), file);
+ idCameraPosition::write(file, p);
+ s = va("\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z);
+ FS_Write(s.c_str(), s.length(), file);
+ s = "\t}\n";
+ FS_Write(s.c_str(), s.length(), file);
+}
+
+void idInterpolatedPosition::write(fileHandle_t file, const char *p) {
+ idStr s = va("\t%s {\n", p);
+ FS_Write(s.c_str(), s.length(), file);
+ idCameraPosition::write(file, p);
+ s = va("\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z);
+ FS_Write(s.c_str(), s.length(), file);
+ s = va("\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z);
+ FS_Write(s.c_str(), s.length(), file);
+ s = "\t}\n";
+ FS_Write(s.c_str(), s.length(), file);
+}
+
+void idSplinePosition::write(fileHandle_t file, const char *p) {
+ idStr s = va("\t%s {\n", p);
+ FS_Write(s.c_str(), s.length(), file);
+ idCameraPosition::write(file, p);
+ target.write(file, "target");
+ s = "\t}\n";
+ FS_Write(s.c_str(), s.length(), file);
+}
+
+void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) {
+ const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name;
+ idCameraPosition *pos = newFromType(type);
+ if (pos) {
+ pos->setName(name);
+ targetPositions.Append(pos);
+ activeTarget = numTargets()-1;
+ if (activeTarget == 0) {
+ // first one
+ addEvent(idCameraEvent::EVENT_TARGET, name, 0);
+ }
+ }
+}
+
+
+
+idCameraDef camera;
+
+extern "C" {
+qboolean loadCamera(const char *name) {
+ camera.clear();
+ return static_cast<qboolean>(camera.load(name));
+}
+
+qboolean getCameraInfo(int time, float *origin, float*angles) {
+ idVec3_t dir, org;
+ org[0] = origin[0];
+ org[1] = origin[1];
+ org[2] = origin[2];
+ float fov = 90;
+ if (camera.getCameraInfo(time, org, dir, &fov)) {
+ origin[0] = org[0];
+ origin[1] = org[1];
+ origin[2] = org[2];
+ angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
+ angles[0] = asin (dir[2])*180/3.14159;
+ return qtrue;
+ }
+ return qfalse;
+}
+
+void startCamera(int time) {
+ camera.startCamera(time);
+}
+
+}
+
+
diff --git a/q3radiant/splines/splines.h b/q3radiant/splines/splines.h
new file mode 100755
index 0000000..1cd0d58
--- /dev/null
+++ b/q3radiant/splines/splines.h
@@ -0,0 +1,1080 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __SPLINES_H
+#define __SPLINES_H
+
+extern "C" {
+#ifdef Q3RADIANT
+#include "../qgl.h"
+#else
+#include "../renderer/qgl.h"
+#endif
+}
+#include "util_list.h"
+#include "util_str.h"
+#include "math_vector.h"
+
+typedef int fileHandle_t;
+
+extern void glBox(idVec3_t &color, idVec3_t &point, float size);
+extern void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label);
+
+static vec4_t blue(0, 0, 1, 1);
+static vec4_t red(1, 0, 0, 1);
+
+class idPointListInterface {
+public:
+ idPointListInterface() {
+ selectedPoints.Clear();
+ };
+ ~idPointListInterface() {};
+
+ virtual int numPoints() {
+ return 0;
+ }
+
+ virtual void addPoint(const float x, const float y, const float z) {}
+ virtual void addPoint(const idVec3_t &v) {}
+ virtual void removePoint(int index) {}
+ virtual idVec3_t *getPoint(int index) { return NULL; }
+
+ int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
+ idVec3_t origin(ox, oy, oz);
+ idVec3_t dir(dx, dy, dz);
+ return selectPointByRay(origin, dir, single);
+ }
+
+ int selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) {
+ int i, besti, count;
+ float d, bestd;
+ idVec3_t temp, temp2;
+
+ // find the point closest to the ray
+ besti = -1;
+ bestd = 8;
+ count = numPoints();
+
+ for (i=0; i < count; i++) {
+ temp = *getPoint(i);
+ temp2 = temp;
+ temp -= origin;
+ d = DotProduct(temp, direction);
+ __VectorMA (origin, d, direction, temp);
+ temp2 -= temp;
+ d = temp2.Length();
+ if (d <= bestd) {
+ bestd = d;
+ besti = i;
+ }
+ }
+
+ if (besti >= 0) {
+ selectPoint(besti, single);
+ }
+
+ return besti;
+ }
+
+ int isPointSelected(int index) {
+ int count = selectedPoints.Num();
+ for (int i = 0; i < count; i++) {
+ if (selectedPoints[i] == index) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ int selectPoint(int index, bool single) {
+ if (index >= 0 && index < numPoints()) {
+ if (single) {
+ deselectAll();
+ } else {
+ if (isPointSelected(index) >= 0) {
+ selectedPoints.Remove(index);
+ }
+ }
+ return selectedPoints.Append(index);
+ }
+ return -1;
+ }
+
+ void selectAll() {
+ selectedPoints.Clear();
+ for (int i = 0; i < numPoints(); i++) {
+ selectedPoints.Append(i);
+ }
+ }
+
+ void deselectAll() {
+ selectedPoints.Clear();
+ }
+
+ int numSelectedPoints();
+
+ idVec3_t *getSelectedPoint(int index) {
+ assert(index >= 0 && index < numSelectedPoints());
+ return getPoint(selectedPoints[index]);
+ }
+
+ virtual void updateSelection(float x, float y, float z) {
+ idVec3_t move(x, y, z);
+ updateSelection(move);
+ }
+
+ virtual void updateSelection(const idVec3_t &move) {
+ int count = selectedPoints.Num();
+ for (int i = 0; i < count; i++) {
+ *getPoint(selectedPoints[i]) += move;
+ }
+ }
+
+ void drawSelection() {
+ int count = selectedPoints.Num();
+ for (int i = 0; i < count; i++) {
+ glBox(red, *getPoint(selectedPoints[i]), 4);
+ }
+ }
+
+protected:
+ idList<int> selectedPoints;
+
+};
+
+
+class idSplineList {
+
+public:
+
+ idSplineList() {
+ clear();
+ }
+
+ idSplineList(const char *p) {
+ clear();
+ name = p;
+ };
+
+ ~idSplineList() {
+ clear();
+ };
+
+ void clearControl() {
+ for (int i = 0; i < controlPoints.Num(); i++) {
+ delete controlPoints[i];
+ }
+ controlPoints.Clear();
+ }
+
+ void clearSpline() {
+ for (int i = 0; i < splinePoints.Num(); i++) {
+ delete splinePoints[i];
+ }
+ splinePoints.Clear();
+ }
+
+ void parse(const char *(*text));
+ void write(fileHandle_t file, const char *name);
+
+ void clear() {
+ clearControl();
+ clearSpline();
+ splineTime.Clear();
+ selected = NULL;
+ dirty = true;
+ activeSegment = 0;
+ granularity = 0.025;
+ pathColor.set(1.0, 0.5, 0.0);
+ controlColor.set(0.7, 0.0, 1.0);
+ segmentColor.set(0.0, 0.0, 1.0);
+ activeColor.set(1.0, 0.0, 0.0);
+ }
+
+ void initPosition(long startTime, long totalTime);
+ const idVec3_t *getPosition(long time);
+
+
+ void draw(bool editMode);
+ void addToRenderer();
+
+ void setSelectedPoint(idVec3_t *p);
+ idVec3_t *getSelectedPoint() {
+ return selected;
+ }
+
+ void addPoint(const idVec3_t &v) {
+ controlPoints.Append(new idVec3_t(v));
+ dirty = true;
+ }
+
+ void addPoint(float x, float y, float z) {
+ controlPoints.Append(new idVec3_t(x, y, z));
+ dirty = true;
+ }
+
+ void updateSelection(const idVec3_t &move);
+
+ void startEdit() {
+ editMode = true;
+ }
+
+ void stopEdit() {
+ editMode = false;
+ }
+
+ void buildSpline();
+
+ void setGranularity(float f) {
+ granularity = f;
+ }
+
+ float getGranularity() {
+ return granularity;
+ }
+
+ int numPoints() {
+ return controlPoints.Num();
+ }
+
+ idVec3_t *getPoint(int index) {
+ assert(index >= 0 && index < controlPoints.Num());
+ return controlPoints[index];
+ }
+
+ idVec3_t *getSegmentPoint(int index) {
+ assert(index >= 0 && index < splinePoints.Num());
+ return splinePoints[index];
+ }
+
+
+ void setSegmentTime(int index, int time) {
+ assert(index >= 0 && index < splinePoints.Num());
+ splineTime[index] = time;
+ }
+
+ int getSegmentTime(int index) {
+ assert(index >= 0 && index < splinePoints.Num());
+ return splineTime[index];
+ }
+ void addSegmentTime(int index, int time) {
+ assert(index >= 0 && index < splinePoints.Num());
+ splineTime[index] += time;
+ }
+
+ float totalDistance();
+
+ static idVec3_t zero;
+
+ int getActiveSegment() {
+ return activeSegment;
+ }
+
+ void setActiveSegment(int i) {
+ //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
+ activeSegment = i;
+ }
+
+ int numSegments() {
+ return splinePoints.Num();
+ }
+
+ void setColors(idVec3_t &path, idVec3_t &segment, idVec3_t &control, idVec3_t &active) {
+ pathColor = path;
+ segmentColor = segment;
+ controlColor = control;
+ activeColor = active;
+ }
+
+ const char *getName() {
+ return name.c_str();
+ }
+
+ void setName(const char *p) {
+ name = p;
+ }
+
+ bool validTime() {
+ if (dirty) {
+ buildSpline();
+ }
+ // gcc doesn't allow static casting away from bools
+ // why? I've no idea...
+ return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
+ }
+
+ void setTime(long t) {
+ time = t;
+ }
+
+ void setBaseTime(long t) {
+ baseTime = t;
+ }
+
+protected:
+ idStr name;
+ float calcSpline(int step, float tension);
+ idList<idVec3_t*> controlPoints;
+ idList<idVec3_t*> splinePoints;
+ idList<float> splineTime;
+ idVec3_t *selected;
+ idVec3_t pathColor, segmentColor, controlColor, activeColor;
+ float granularity;
+ bool editMode;
+ bool dirty;
+ int activeSegment;
+ long baseTime;
+ long time;
+ friend class idCamera;
+};
+
+// time in milliseconds
+// velocity where 1.0 equal rough walking speed
+struct idVelocity {
+ idVelocity(long start, long duration, float s) {
+ startTime = start;
+ time = duration;
+ speed = s;
+ }
+ long startTime;
+ long time;
+ float speed;
+};
+
+// can either be a look at or origin position for a camera
+//
+class idCameraPosition : public idPointListInterface {
+public:
+
+ virtual void clear() {
+ editMode = false;
+ for (int i = 0; i < velocities.Num(); i++) {
+ delete velocities[i];
+ velocities[i] = NULL;
+ }
+ velocities.Clear();
+ }
+
+ idCameraPosition(const char *p) {
+ name = p;
+ }
+
+ idCameraPosition() {
+ time = 0;
+ name = "position";
+ }
+
+ idCameraPosition(long t) {
+ time = t;
+ }
+
+ virtual ~idCameraPosition() {
+ clear();
+ }
+
+
+ // this can be done with RTTI syntax but i like the derived classes setting a type
+ // makes serialization a bit easier to see
+ //
+ enum positionType {
+ FIXED = 0x00,
+ INTERPOLATED,
+ SPLINE,
+ POSITION_COUNT
+ };
+
+
+ virtual void start(long t) {
+ startTime = t;
+ }
+
+ long getTime() {
+ return time;
+ }
+
+ virtual void setTime(long t) {
+ time = t;
+ }
+
+ float getVelocity(long t) {
+ long check = t - startTime;
+ for (int i = 0; i < velocities.Num(); i++) {
+ if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
+ return velocities[i]->speed;
+ }
+ }
+ return baseVelocity;
+ }
+
+ void addVelocity(long start, long duration, float speed) {
+ velocities.Append(new idVelocity(start, duration, speed));
+ }
+
+ virtual const idVec3_t *getPosition(long t) {
+ assert(true);
+ return NULL;
+ }
+
+ virtual void draw(bool editMode) {};
+
+ virtual void parse(const char *(*text)) {};
+ virtual void write(fileHandle_t file, const char *name);
+ virtual bool parseToken(const char *key, const char *(*text));
+
+ const char *getName() {
+ return name.c_str();
+ }
+
+ void setName(const char *p) {
+ name = p;
+ }
+
+ virtual startEdit() {
+ editMode = true;
+ }
+
+ virtual stopEdit() {
+ editMode = false;
+ }
+
+ virtual void draw() {};
+
+ const char *typeStr() {
+ return positionStr[static_cast<int>(type)];
+ }
+
+ void calcVelocity(float distance) {
+ float secs = (float)time / 1000;
+ baseVelocity = distance / secs;
+ }
+
+protected:
+ static const char* positionStr[POSITION_COUNT];
+ long startTime;
+ long time;
+ idCameraPosition::positionType type;
+ idStr name;
+ bool editMode;
+ idList<idVelocity*> velocities;
+ float baseVelocity;
+};
+
+class idFixedPosition : public idCameraPosition {
+public:
+
+ void init() {
+ pos.Zero();
+ type = idCameraPosition::FIXED;
+ }
+
+ idFixedPosition() : idCameraPosition() {
+ init();
+ }
+
+ idFixedPosition(idVec3_t p) : idCameraPosition() {
+ init();
+ pos = p;
+ }
+
+ virtual void addPoint(const idVec3_t &v) {
+ pos = v;
+ }
+
+ virtual void addPoint(const float x, const float y, const float z) {
+ pos.set(x, y, z);
+ }
+
+
+ ~idFixedPosition() {
+ }
+
+ virtual const idVec3_t *getPosition(long t) {
+ return &pos;
+ }
+
+ void parse(const char *(*text));
+ void write(fileHandle_t file, const char *name);
+
+ virtual int numPoints() {
+ return 1;
+ }
+
+ virtual idVec3_t *getPoint(int index) {
+ if (index != 0) {
+ assert(true);
+ };
+ return &pos;
+ }
+
+ virtual void draw(bool editMode) {
+ glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
+ }
+
+protected:
+ idVec3_t pos;
+};
+
+class idInterpolatedPosition : public idCameraPosition {
+public:
+
+ void init() {
+ type = idCameraPosition::INTERPOLATED;
+ first = true;
+ startPos.Zero();
+ endPos.Zero();
+ }
+
+ idInterpolatedPosition() : idCameraPosition() {
+ init();
+ }
+
+ idInterpolatedPosition(idVec3_t start, idVec3_t end, long time) : idCameraPosition(time) {
+ init();
+ startPos = start;
+ endPos = end;
+ }
+
+ ~idInterpolatedPosition() {
+ }
+
+ virtual const idVec3_t *getPosition(long t);
+
+ void parse(const char *(*text));
+ void write(fileHandle_t file, const char *name);
+
+ virtual int numPoints() {
+ return 2;
+ }
+
+ virtual idVec3_t *getPoint(int index) {
+ assert(index >= 0 && index < 2);
+ if (index == 0) {
+ return &startPos;
+ }
+ return &endPos;
+ }
+
+ virtual void addPoint(const float x, const float y, const float z) {
+ if (first) {
+ startPos.set(x, y, z);
+ first = false;
+ } else {
+ endPos.set(x, y, z);
+ first = true;
+ }
+ }
+
+ virtual void addPoint(const idVec3_t &v) {
+ if (first) {
+ startPos = v;
+ first = false;
+ } else {
+ endPos = v;
+ first = true;
+ }
+ }
+
+ virtual void draw(bool editMode) {
+ glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
+ glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
+ qglBegin(GL_LINES);
+ qglVertex3fv(startPos);
+ qglVertex3fv(endPos);
+ qglEnd();
+ }
+
+ virtual void start(long t) {
+ idCameraPosition::start(t);
+ lastTime = startTime;
+ distSoFar = 0.0;
+ idVec3_t temp = startPos;
+ temp -= endPos;
+ calcVelocity(temp.Length());
+ }
+
+protected:
+ bool first;
+ idVec3_t startPos;
+ idVec3_t endPos;
+ long lastTime;
+ float distSoFar;
+};
+
+class idSplinePosition : public idCameraPosition {
+public:
+
+ void init() {
+ type = idCameraPosition::SPLINE;
+ }
+
+ idSplinePosition() : idCameraPosition() {
+ init();
+ }
+
+ idSplinePosition(long time) : idCameraPosition(time) {
+ init();
+ }
+
+ ~idSplinePosition() {
+ }
+
+ virtual void start(long t) {
+ idCameraPosition::start(t);
+ target.initPosition(t, time);
+ calcVelocity(target.totalDistance());
+ }
+
+ virtual const idVec3_t *getPosition(long t) {
+ return target.getPosition(t);
+ }
+
+ //virtual const idVec3_t *getPosition(long t) const {
+
+ void addControlPoint(idVec3_t &v) {
+ target.addPoint(v);
+ }
+
+ void parse(const char *(*text));
+ void write(fileHandle_t file, const char *name);
+
+ virtual int numPoints() {
+ return target.numPoints();
+ }
+
+ virtual idVec3_t *getPoint(int index) {
+ return target.getPoint(index);
+ }
+
+ virtual void addPoint(const idVec3_t &v) {
+ target.addPoint(v);
+ }
+
+ virtual void addPoint(const float x, const float y, const float z) {
+ target.addPoint(x, y, z);
+ }
+
+ virtual void draw(bool editMode) {
+ target.draw(editMode);
+ }
+
+ virtual void updateSelection(const idVec3_t &move) {
+ idCameraPosition::updateSelection(move);
+ target.buildSpline();
+ }
+
+protected:
+ idSplineList target;
+};
+
+class idCameraFOV {
+public:
+
+ idCameraFOV() {
+ time = 0;
+ fov = 90;
+ }
+
+ idCameraFOV(int v) {
+ time = 0;
+ fov = v;
+ }
+
+ idCameraFOV(int s, int e, long t) {
+ startFOV = s;
+ endFOV = e;
+ time = t;
+ }
+
+
+ ~idCameraFOV(){}
+
+ void setFOV(float f) {
+ fov = f;
+ }
+
+ float getFOV(long t) {
+ if (time) {
+ assert(startTime);
+ float percent = t / startTime;
+ float temp = startFOV - endFOV;
+ temp *= percent;
+ fov = startFOV + temp;
+ }
+ return fov;
+ }
+
+ int start(long t) {
+ startTime = t;
+ }
+
+ void parse(const char *(*text));
+ void write(fileHandle_t file, const char *name);
+
+protected:
+ float fov;
+ float startFOV;
+ float endFOV;
+ int startTime;
+ int time;
+};
+
+
+
+
+class idCameraEvent {
+public:
+ enum eventType {
+ EVENT_NA = 0x00,
+ EVENT_WAIT,
+ EVENT_TARGETWAIT,
+ EVENT_SPEED,
+ EVENT_TARGET,
+ EVENT_SNAPTARGET,
+ EVENT_FOV,
+ EVENT_SCRIPT,
+ EVENT_TRIGGER,
+ EVENT_STOP,
+ EVENT_COUNT
+ };
+
+ static const char* eventStr[EVENT_COUNT];
+
+ idCameraEvent() {
+ paramStr = "";
+ type = EVENT_NA;
+ time = 0;
+ }
+
+ idCameraEvent(eventType t, const char *param, long n) {
+ type = t;
+ paramStr = param;
+ time = n;
+ }
+
+ ~idCameraEvent() {};
+
+ eventType getType() {
+ return type;
+ }
+
+ const char *typeStr() {
+ return eventStr[static_cast<int>(type)];
+ }
+
+ const char *getParam() {
+ return paramStr.c_str();
+ }
+
+ long getTime() {
+ return time;
+ }
+
+ void setTime(long n) {
+ time = n;
+ }
+
+ void parse(const char *(*text));
+ void write(fileHandle_t file, const char *name);
+
+ void setTriggered(bool b) {
+ triggered = b;
+ }
+
+ bool getTriggered() {
+ return triggered;
+ }
+
+protected:
+ eventType type;
+ idStr paramStr;
+ long time;
+ bool triggered;
+
+};
+
+class idCameraDef {
+public:
+
+ void clear() {
+ currentCameraPosition = 0;
+ cameraRunning = false;
+ lastDirection.Zero();
+ baseTime = 30;
+ activeTarget = 0;
+ name = "camera01";
+ fov.setFOV(90);
+ int i;
+ for (i = 0; i < targetPositions.Num(); i++) {
+ delete targetPositions[i];
+ }
+ for (i = 0; i < events.Num(); i++) {
+ delete events[i];
+ }
+ delete cameraPosition;
+ cameraPosition = NULL;
+ events.Clear();
+ targetPositions.Clear();
+ }
+
+ idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
+ clear();
+ if (type == idCameraPosition::SPLINE) {
+ cameraPosition = new idSplinePosition();
+ } else if (type == idCameraPosition::INTERPOLATED) {
+ cameraPosition = new idInterpolatedPosition();
+ } else {
+ cameraPosition = new idFixedPosition();
+ }
+ return cameraPosition;
+ }
+
+ idCameraDef() {
+ clear();
+ }
+
+ ~idCameraDef() {
+ clear();
+ }
+
+ void addEvent(idCameraEvent::eventType t, const char *param, long time);
+
+ void addEvent(idCameraEvent *event);
+
+ static int sortEvents(const void *p1, const void *p2);
+
+ int numEvents() {
+ return events.Num();
+ }
+
+ idCameraEvent *getEvent(int index) {
+ assert(index >= 0 && index < events.Num());
+ return events[index];
+ }
+
+ void parse(const char *(*text));
+ bool load(const char *filename);
+ void save(const char *filename);
+
+ void buildCamera();
+
+ //idSplineList *getcameraPosition() {
+ // return &cameraPosition;
+ //}
+
+ static idCameraPosition *newFromType(idCameraPosition::positionType t) {
+ switch (t) {
+ case idCameraPosition::FIXED : return new idFixedPosition();
+ case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
+ case idCameraPosition::SPLINE : return new idSplinePosition();
+ };
+ return NULL;
+ }
+
+ void addTarget(const char *name, idCameraPosition::positionType type);
+
+ idCameraPosition *getActiveTarget() {
+ if (targetPositions.Num() == 0) {
+ addTarget(NULL, idCameraPosition::FIXED);
+ }
+ return targetPositions[activeTarget];
+ }
+
+ idCameraPosition *getActiveTarget(int index) {
+ if (targetPositions.Num() == 0) {
+ addTarget(NULL, idCameraPosition::FIXED);
+ return targetPositions[0];
+ }
+ return targetPositions[index];
+ }
+
+ int numTargets() {
+ return targetPositions.Num();
+ }
+
+
+ void setActiveTargetByName(const char *name) {
+ for (int i = 0; i < targetPositions.Num(); i++) {
+ if (stricmp(name, targetPositions[i]->getName()) == 0) {
+ setActiveTarget(i);
+ return;
+ }
+ }
+ }
+
+ void setActiveTarget(int index) {
+ assert(index >= 0 && index < targetPositions.Num());
+ activeTarget = index;
+ }
+
+ void setRunning(bool b) {
+ cameraRunning = b;
+ }
+
+ void setBaseTime(float f) {
+ baseTime = f;
+ }
+
+ float getBaseTime() {
+ return baseTime;
+ }
+
+ float getTotalTime() {
+ return totalTime;
+ }
+
+ void startCamera(long t);
+ void stopCamera() {
+ cameraRunning = true;
+ }
+ void getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fv);
+
+ bool getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv);
+ bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
+ idVec3_t org, dir;
+ org[0] = origin[0];
+ org[1] = origin[1];
+ org[2] = origin[2];
+ dir[0] = direction[0];
+ dir[1] = direction[1];
+ dir[2] = direction[2];
+ bool b = getCameraInfo(time, org, dir, fv);
+ origin[0] = org[0];
+ origin[1] = org[1];
+ origin[2] = org[2];
+ direction[0] = dir[0];
+ direction[1] = dir[1];
+ direction[2] = dir[2];
+ return b;
+ }
+
+ void draw(bool editMode) {
+ // gcc doesn't allow casting away from bools
+ // why? I've no idea...
+ if (cameraPosition) {
+ cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
+ int count = targetPositions.Num();
+ for (int i = 0; i < count; i++) {
+ targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
+ }
+ }
+ }
+
+/*
+ int numSegments() {
+ if (cameraEdit) {
+ return cameraPosition.numSegments();
+ }
+ return getTargetSpline()->numSegments();
+ }
+
+ int getActiveSegment() {
+ if (cameraEdit) {
+ return cameraPosition.getActiveSegment();
+ }
+ return getTargetSpline()->getActiveSegment();
+ }
+
+ void setActiveSegment(int i) {
+ if (cameraEdit) {
+ cameraPosition.setActiveSegment(i);
+ } else {
+ getTargetSpline()->setActiveSegment(i);
+ }
+ }
+*/
+ int numPoints() {
+ if (cameraEdit) {
+ return cameraPosition->numPoints();
+ }
+ return getActiveTarget()->numPoints();
+ }
+
+ const idVec3_t *getPoint(int index) {
+ if (cameraEdit) {
+ return cameraPosition->getPoint(index);
+ }
+ return getActiveTarget()->getPoint(index);
+ }
+
+ void stopEdit() {
+ editMode = false;
+ if (cameraEdit) {
+ cameraPosition->stopEdit();
+ } else {
+ getActiveTarget()->stopEdit();
+ }
+ }
+
+ void startEdit(bool camera) {
+ cameraEdit = camera;
+ if (camera) {
+ cameraPosition->startEdit();
+ for (int i = 0; i < targetPositions.Num(); i++) {
+ targetPositions[i]->stopEdit();
+ }
+ } else {
+ getActiveTarget()->startEdit();
+ cameraPosition->stopEdit();
+ }
+ editMode = true;
+ }
+
+ bool waitEvent(int index);
+
+ const char *getName() {
+ return name.c_str();
+ }
+
+ void setName(const char *p) {
+ name = p;
+ }
+
+ idCameraPosition *getPositionObj() {
+ if (cameraPosition == NULL) {
+ cameraPosition = new idFixedPosition();
+ }
+ return cameraPosition;
+ }
+
+protected:
+ idStr name;
+ int currentCameraPosition;
+ idVec3_t lastDirection;
+ bool cameraRunning;
+ idCameraPosition *cameraPosition;
+ idList<idCameraPosition*> targetPositions;
+ idList<idCameraEvent*> events;
+ idCameraFOV fov;
+ int activeTarget;
+ float totalTime;
+ float baseTime;
+ long startTime;
+
+ bool cameraEdit;
+ bool editMode;
+};
+
+extern bool g_splineMode;
+
+extern idCameraDef *g_splineList;
+
+
+#endif \ No newline at end of file
diff --git a/q3radiant/splines/util_list.h b/q3radiant/splines/util_list.h
new file mode 100755
index 0000000..4f93244
--- /dev/null
+++ b/q3radiant/splines/util_list.h
@@ -0,0 +1,346 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __UTIL_LIST_H__
+#define __UTIL_LIST_H__
+
+#include <stdlib.h>
+#include <assert.h>
+
+template< class type >
+class idList {
+private:
+ int m_num;
+ int m_size;
+ int m_granularity;
+ type *m_list;
+
+public:
+ idList( int granularity = 16 );
+ ~idList<type>();
+ void Clear( void );
+ int Num( void );
+ void SetNum( int num );
+ void SetGranularity( int granularity );
+ void Condense( void );
+ int Size( void );
+ void Resize( int size );
+ type operator[]( int index ) const;
+ type &operator[]( int index );
+ int Append( type const & obj );
+ int AddUnique( type const & obj );
+ type *Find( type const & obj, int *index = NULL );
+ bool RemoveIndex( int index );
+ bool Remove( type const & obj );
+ typedef int cmp_t(const void *, const void *);
+ void Sort( cmp_t *compare );
+};
+
+/*
+================
+idList<type>::idList( int )
+================
+*/
+template< class type >
+inline idList<type>::idList( int granularity ) {
+ assert( granularity > 0 );
+
+ m_list = NULL;
+ m_granularity = granularity;
+ Clear();
+}
+
+/*
+================
+idList<type>::~idList<type>
+================
+*/
+template< class type >
+inline idList<type>::~idList() {
+ Clear();
+}
+
+/*
+================
+idList<type>::Clear
+================
+*/
+template< class type >
+inline void idList<type>::Clear( void ) {
+ if ( m_list ) {
+ delete[] m_list;
+ }
+
+ m_list = NULL;
+ m_num = 0;
+ m_size = 0;
+}
+
+/*
+================
+idList<type>::Num
+================
+*/
+template< class type >
+inline int idList<type>::Num( void ) {
+ return m_num;
+}
+
+/*
+================
+idList<type>::SetNum
+================
+*/
+template< class type >
+inline void idList<type>::SetNum( int num ) {
+ assert( num >= 0 );
+ if ( num > m_size ) {
+ // resize it up to the closest level of granularity
+ Resize( ( ( num + m_granularity - 1 ) / m_granularity ) * m_granularity );
+ }
+ m_num = num;
+}
+
+/*
+================
+idList<type>::SetGranularity
+================
+*/
+template< class type >
+inline void idList<type>::SetGranularity( int granularity ) {
+ int newsize;
+
+ assert( granularity > 0 );
+ m_granularity = granularity;
+
+ if ( m_list ) {
+ // resize it to the closest level of granularity
+ newsize = ( ( m_num + m_granularity - 1 ) / m_granularity ) * m_granularity;
+ if ( newsize != m_size ) {
+ Resize( newsize );
+ }
+ }
+}
+
+/*
+================
+idList<type>::Condense
+
+Resizes the array to exactly the number of elements it contains
+================
+*/
+template< class type >
+inline void idList<type>::Condense( void ) {
+ if ( m_list ) {
+ if ( m_num ) {
+ Resize( m_num );
+ } else {
+ Clear();
+ }
+ }
+}
+
+/*
+================
+idList<type>::Size
+================
+*/
+template< class type >
+inline int idList<type>::Size( void ) {
+ return m_size;
+}
+
+/*
+================
+idList<type>::Resize
+================
+*/
+template< class type >
+inline void idList<type>::Resize( int size ) {
+ type *temp;
+ int i;
+
+ assert( size > 0 );
+
+ if ( size <= 0 ) {
+ Clear();
+ return;
+ }
+
+ temp = m_list;
+ m_size = size;
+ if ( m_size < m_num ) {
+ m_num = m_size;
+ }
+
+ m_list = new type[ m_size ];
+ for( i = 0; i < m_num; i++ ) {
+ m_list[ i ] = temp[ i ];
+ }
+
+ if ( temp ) {
+ delete[] temp;
+ }
+}
+
+/*
+================
+idList<type>::operator[] const
+================
+*/
+template< class type >
+inline type idList<type>::operator[]( int index ) const {
+ assert( index >= 0 );
+ assert( index < m_num );
+
+ return m_list[ index ];
+}
+
+/*
+================
+idList<type>::operator[]
+================
+*/
+template< class type >
+inline type &idList<type>::operator[]( int index ) {
+ assert( index >= 0 );
+ assert( index < m_num );
+
+ return m_list[ index ];
+}
+
+/*
+================
+idList<type>::Append
+================
+*/
+template< class type >
+inline int idList<type>::Append( type const & obj ) {
+ if ( !m_list ) {
+ Resize( m_granularity );
+ }
+
+ if ( m_num == m_size ) {
+ Resize( m_size + m_granularity );
+ }
+
+ m_list[ m_num ] = obj;
+ m_num++;
+
+ return m_num - 1;
+}
+
+/*
+================
+idList<type>::AddUnique
+================
+*/
+template< class type >
+inline int idList<type>::AddUnique( type const & obj ) {
+ int index;
+
+ if ( !Find( obj, &index ) ) {
+ index = Append( obj );
+ }
+
+ return index;
+}
+
+/*
+================
+idList<type>::Find
+================
+*/
+template< class type >
+inline type *idList<type>::Find( type const & obj, int *index ) {
+ int i;
+
+ for( i = 0; i < m_num; i++ ) {
+ if ( m_list[ i ] == obj ) {
+ if ( index ) {
+ *index = i;
+ }
+ return &m_list[ i ];
+ }
+ }
+
+ return NULL;
+}
+
+/*
+================
+idList<type>::RemoveIndex
+================
+*/
+template< class type >
+inline bool idList<type>::RemoveIndex( int index ) {
+ int i;
+
+ if ( !m_list || !m_num ) {
+ return false;
+ }
+
+ assert( index >= 0 );
+ assert( index < m_num );
+
+ if ( ( index < 0 ) || ( index >= m_num ) ) {
+ return false;
+ }
+
+ m_num--;
+ for( i = index; i < m_num; i++ ) {
+ m_list[ i ] = m_list[ i + 1 ];
+ }
+
+ return true;
+}
+
+/*
+================
+idList<type>::Remove
+================
+*/
+template< class type >
+inline bool idList<type>::Remove( type const & obj ) {
+ int index;
+
+ if ( Find( obj, &index ) ) {
+ return RemoveIndex( index );
+ }
+
+ return false;
+}
+
+/*
+================
+idList<type>::Sort
+================
+*/
+template< class type >
+inline void idList<type>::Sort( cmp_t *compare ) {
+ if ( !m_list ) {
+ return;
+ }
+
+ qsort( ( void * )m_list, ( size_t )m_num, sizeof( type ), compare );
+}
+
+#endif /* !__UTIL_LIST_H__ */
diff --git a/q3radiant/splines/util_str.cpp b/q3radiant/splines/util_str.cpp
new file mode 100755
index 0000000..230a77f
--- /dev/null
+++ b/q3radiant/splines/util_str.cpp
@@ -0,0 +1,618 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//need to rewrite this
+
+#include "util_str.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data
+#pragma warning(disable : 4710) // function 'blah' not inlined
+#endif
+
+static const int STR_ALLOC_GRAN = 20;
+
+char *idStr::tolower
+ (
+ char *s1
+ )
+
+ {
+ char *s;
+
+ s = s1;
+ while( *s )
+ {
+ *s = ::tolower( *s );
+ s++;
+ }
+
+ return s1;
+ }
+
+char *idStr::toupper
+ (
+ char *s1
+ )
+
+ {
+ char *s;
+
+ s = s1;
+ while( *s )
+ {
+ *s = ::toupper( *s );
+ s++;
+ }
+
+ return s1;
+ }
+
+int idStr::icmpn
+ (
+ const char *s1,
+ const char *s2,
+ int n
+ )
+
+ {
+ int c1;
+ int c2;
+
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if ( !n-- )
+ {
+ // idStrings are equal until end point
+ return 0;
+ }
+
+ if ( c1 != c2 )
+ {
+ if ( c1 >= 'a' && c1 <= 'z' )
+ {
+ c1 -= ( 'a' - 'A' );
+ }
+
+ if ( c2 >= 'a' && c2 <= 'z' )
+ {
+ c2 -= ( 'a' - 'A' );
+ }
+
+ if ( c1 < c2 )
+ {
+ // strings less than
+ return -1;
+ }
+ else if ( c1 > c2 )
+ {
+ // strings greater than
+ return 1;
+ }
+ }
+ }
+ while( c1 );
+
+ // strings are equal
+ return 0;
+ }
+
+int idStr::icmp
+ (
+ const char *s1,
+ const char *s2
+ )
+
+ {
+ int c1;
+ int c2;
+
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if ( c1 != c2 )
+ {
+ if ( c1 >= 'a' && c1 <= 'z' )
+ {
+ c1 -= ( 'a' - 'A' );
+ }
+
+ if ( c2 >= 'a' && c2 <= 'z' )
+ {
+ c2 -= ( 'a' - 'A' );
+ }
+
+ if ( c1 < c2 )
+ {
+ // strings less than
+ return -1;
+ }
+ else if ( c1 > c2 )
+ {
+ // strings greater than
+ return 1;
+ }
+ }
+ }
+ while( c1 );
+
+ // strings are equal
+ return 0;
+ }
+
+int idStr::cmpn
+ (
+ const char *s1,
+ const char *s2,
+ int n
+ )
+
+ {
+ int c1;
+ int c2;
+
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if ( !n-- )
+ {
+ // strings are equal until end point
+ return 0;
+ }
+
+ if ( c1 < c2 )
+ {
+ // strings less than
+ return -1;
+ }
+ else if ( c1 > c2 )
+ {
+ // strings greater than
+ return 1;
+ }
+ }
+ while( c1 );
+
+ // strings are equal
+ return 0;
+ }
+
+int idStr::cmp
+ (
+ const char *s1,
+ const char *s2
+ )
+
+ {
+ int c1;
+ int c2;
+
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ if ( c1 < c2 )
+ {
+ // strings less than
+ return -1;
+ }
+ else if ( c1 > c2 )
+ {
+ // strings greater than
+ return 1;
+ }
+ }
+ while( c1 );
+
+ // strings are equal
+ return 0;
+ }
+
+/*
+============
+IsNumeric
+
+Checks a string to see if it contains only numerical values.
+============
+*/
+bool idStr::isNumeric
+ (
+ const char *str
+ )
+
+ {
+ int len;
+ int i;
+ bool dot;
+
+ if ( *str == '-' )
+ {
+ str++;
+ }
+
+ dot = false;
+ len = strlen( str );
+ for( i = 0; i < len; i++ )
+ {
+ if ( !isdigit( str[ i ] ) )
+ {
+ if ( ( str[ i ] == '.' ) && !dot )
+ {
+ dot = true;
+ continue;
+ }
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+idStr operator+
+ (
+ const idStr& a,
+ const float b
+ )
+
+ {
+ char text[ 20 ];
+
+ idStr result( a );
+
+ sprintf( text, "%f", b );
+ result.append( text );
+
+ return result;
+ }
+
+idStr operator+
+ (
+ const idStr& a,
+ const int b
+ )
+
+ {
+ char text[ 20 ];
+
+ idStr result( a );
+
+ sprintf( text, "%d", b );
+ result.append( text );
+
+ return result;
+ }
+
+idStr operator+
+ (
+ const idStr& a,
+ const unsigned b
+ )
+
+ {
+ char text[ 20 ];
+
+ idStr result( a );
+
+ sprintf( text, "%u", b );
+ result.append( text );
+
+ return result;
+ }
+
+idStr& idStr::operator+=
+ (
+ const float a
+ )
+
+ {
+ char text[ 20 ];
+
+ sprintf( text, "%f", a );
+ append( text );
+
+ return *this;
+ }
+
+idStr& idStr::operator+=
+ (
+ const int a
+ )
+
+ {
+ char text[ 20 ];
+
+ sprintf( text, "%d", a );
+ append( text );
+
+ return *this;
+ }
+
+idStr& idStr::operator+=
+ (
+ const unsigned a
+ )
+
+ {
+ char text[ 20 ];
+
+ sprintf( text, "%u", a );
+ append( text );
+
+ return *this;
+ }
+
+void idStr::CapLength
+ (
+ int newlen
+ )
+
+ {
+ assert ( m_data );
+
+ if ( length() <= newlen )
+ return;
+
+ EnsureDataWritable ();
+
+ m_data->data[newlen] = 0;
+ m_data->len = newlen;
+ }
+
+void idStr::EnsureDataWritable
+ (
+ void
+ )
+
+ {
+ assert ( m_data );
+ strdata *olddata;
+ int len;
+
+ if ( !m_data->refcount )
+ return;
+
+ olddata = m_data;
+ len = length();
+
+ m_data = new strdata;
+
+ EnsureAlloced ( len + 1, false );
+ strncpy ( m_data->data, olddata->data, len+1 );
+ m_data->len = len;
+
+ olddata->DelRef ();
+ }
+
+void idStr::EnsureAlloced (int amount, bool keepold) {
+
+ if ( !m_data ) {
+ m_data = new strdata();
+ }
+
+ // Now, let's make sure it's writable
+ EnsureDataWritable ();
+
+ char *newbuffer;
+ bool wasalloced = ( m_data->alloced != 0 );
+
+ if ( amount < m_data->alloced ) {
+ return;
+ }
+
+ assert ( amount );
+ if ( amount == 1 ) {
+ m_data->alloced = 1;
+ } else {
+ int newsize, mod;
+ mod = amount % STR_ALLOC_GRAN;
+ if ( !mod ) {
+ newsize = amount;
+ } else {
+ newsize = amount + STR_ALLOC_GRAN - mod;
+ }
+ m_data->alloced = newsize;
+ }
+
+ newbuffer = new char[m_data->alloced];
+ if ( wasalloced && keepold ) {
+ strcpy ( newbuffer, m_data->data );
+ }
+
+ if ( m_data->data ) {
+ delete [] m_data->data;
+ }
+ m_data->data = newbuffer;
+}
+
+void idStr::BackSlashesToSlashes
+ (
+ void
+ )
+
+ {
+ int i;
+
+ EnsureDataWritable ();
+
+ for ( i=0; i < m_data->len; i++ )
+ {
+ if ( m_data->data[i] == '\\' )
+ m_data->data[i] = '/';
+ }
+ }
+
+void idStr::snprintf
+ (
+ char *dst,
+ int size,
+ const char *fmt,
+ ...
+ )
+
+ {
+ char buffer[0x10000];
+ int len;
+ va_list argptr;
+
+ va_start (argptr,fmt);
+ len = vsprintf (buffer,fmt,argptr);
+ va_end (argptr);
+
+ assert ( len < size );
+
+ strncpy (dst, buffer, size-1);
+ }
+
+#ifdef _WIN32
+#pragma warning(disable : 4189) // local variable is initialized but not referenced
+#endif
+
+/*
+=================
+TestStringClass
+
+This is a fairly rigorous test of the idStr class's functionality.
+Because of the fairly global and subtle ramifications of a bug occuring
+in this class, it should be run after any changes to the class.
+Add more tests as functionality is changed. Tests should include
+any possible bounds violation and NULL data tests.
+=================
+*/
+void TestStringClass
+ (
+ void
+ )
+
+ {
+ char ch; // ch == ?
+ idStr *t; // t == ?
+ idStr a; // a.len == 0, a.data == "\0"
+ idStr b; // b.len == 0, b.data == "\0"
+ idStr c( "test" ); // c.len == 4, c.data == "test\0"
+ idStr d( c ); // d.len == 4, d.data == "test\0"
+ idStr e( reinterpret_cast<const char *>(NULL) );
+ // e.len == 0, e.data == "\0" ASSERT!
+ int i; // i == ?
+
+ i = a.length(); // i == 0
+ i = c.length(); // i == 4
+
+ const char *s1 = a.c_str(); // s1 == "\0"
+ const char *s2 = c.c_str(); // s2 == "test\0"
+
+ t = new idStr(); // t->len == 0, t->data == "\0"
+ delete t; // t == ?
+
+ b = "test"; // b.len == 4, b.data == "test\0"
+ t = new idStr( "test" ); // t->len == 4, t->data == "test\0"
+ delete t; // t == ?
+
+ a = c; // a.len == 4, a.data == "test\0"
+// a = "";
+ a = NULL; // a.len == 0, a.data == "\0" ASSERT!
+ a = c + d; // a.len == 8, a.data == "testtest\0"
+ a = c + "wow"; // a.len == 7, a.data == "testwow\0"
+ a = c + reinterpret_cast<const char *>(NULL);
+ // a.len == 4, a.data == "test\0" ASSERT!
+ a = "this" + d; // a.len == 8, a.data == "thistest\0"
+ a = reinterpret_cast<const char *>(NULL) + d;
+ // a.len == 4, a.data == "test\0" ASSERT!
+ a += c; // a.len == 8, a.data == "testtest\0"
+ a += "wow"; // a.len == 11, a.data == "testtestwow\0"
+ a += reinterpret_cast<const char *>(NULL);
+ // a.len == 11, a.data == "testtestwow\0" ASSERT!
+
+ a = "test"; // a.len == 4, a.data == "test\0"
+ ch = a[ 0 ]; // ch == 't'
+ ch = a[ -1 ]; // ch == 0 ASSERT!
+ ch = a[ 1000 ]; // ch == 0 ASSERT!
+ ch = a[ 0 ]; // ch == 't'
+ ch = a[ 1 ]; // ch == 'e'
+ ch = a[ 2 ]; // ch == 's'
+ ch = a[ 3 ]; // ch == 't'
+ ch = a[ 4 ]; // ch == '\0' ASSERT!
+ ch = a[ 5 ]; // ch == '\0' ASSERT!
+
+ a[ 1 ] = 'b'; // a.len == 4, a.data == "tbst\0"
+ a[ -1 ] = 'b'; // a.len == 4, a.data == "tbst\0" ASSERT!
+ a[ 0 ] = '0'; // a.len == 4, a.data == "0bst\0"
+ a[ 1 ] = '1'; // a.len == 4, a.data == "01st\0"
+ a[ 2 ] = '2'; // a.len == 4, a.data == "012t\0"
+ a[ 3 ] = '3'; // a.len == 4, a.data == "0123\0"
+ a[ 4 ] = '4'; // a.len == 4, a.data == "0123\0" ASSERT!
+ a[ 5 ] = '5'; // a.len == 4, a.data == "0123\0" ASSERT!
+ a[ 7 ] = '7'; // a.len == 4, a.data == "0123\0" ASSERT!
+
+ a = "test"; // a.len == 4, a.data == "test\0"
+ b = "no"; // b.len == 2, b.data == "no\0"
+
+ i = ( a == b ); // i == 0
+ i = ( a == c ); // i == 1
+
+ i = ( a == "blow" ); // i == 0
+ i = ( a == "test" ); // i == 1
+ i = ( a == NULL ); // i == 0 ASSERT!
+
+ i = ( "test" == b ); // i == 0
+ i = ( "test" == a ); // i == 1
+ i = ( NULL == a ); // i == 0 ASSERT!
+
+ i = ( a != b ); // i == 1
+ i = ( a != c ); // i == 0
+
+ i = ( a != "blow" ); // i == 1
+ i = ( a != "test" ); // i == 0
+ i = ( a != NULL ); // i == 1 ASSERT!
+
+ i = ( "test" != b ); // i == 1
+ i = ( "test" != a ); // i == 0
+ i = ( NULL != a ); // i == 1 ASSERT!
+
+ a = "test"; // a.data == "test"
+ b = a; // b.data == "test"
+
+ a = "not"; // a.data == "not", b.data == "test"
+
+ a = b; // a.data == b.data == "test"
+
+ a += b; // a.data == "testtest", b.data = "test"
+
+ a = b;
+
+ a[1] = '1'; // a.data = "t1st", b.data = "test"
+ }
+
+#ifdef _WIN32
+#pragma warning(default : 4189) // local variable is initialized but not referenced
+#pragma warning(disable : 4514) // unreferenced inline function has been removed
+#endif
diff --git a/q3radiant/splines/util_str.h b/q3radiant/splines/util_str.h
new file mode 100755
index 0000000..896bf89
--- /dev/null
+++ b/q3radiant/splines/util_str.h
@@ -0,0 +1,817 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+//need to rewrite this
+
+#ifndef __UTIL_STR_H__
+#define __UTIL_STR_H__
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4710) // function 'blah' not inlined
+#endif
+
+void TestStringClass ();
+
+class strdata
+ {
+ public:
+ strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
+ ~strdata ()
+ {
+ if ( data )
+ delete [] data;
+ }
+
+ void AddRef () { refcount++; }
+ bool DelRef () // True if killed
+ {
+ refcount--;
+ if ( refcount < 0 )
+ {
+ delete this;
+ return true;
+ }
+
+ return false;
+ }
+
+ int len;
+ int refcount;
+ char *data;
+ int alloced;
+ };
+
+class idStr {
+protected:
+ strdata *m_data;
+ void EnsureAlloced ( int, bool keepold = true );
+ void EnsureDataWritable ();
+
+public:
+ ~idStr();
+ idStr();
+ idStr( const char *text );
+ idStr( const idStr& string );
+ idStr( const idStr string, int start, int end );
+ idStr( const char ch );
+ idStr( const int num );
+ idStr( const float num );
+ idStr( const unsigned num );
+ int length( void ) const;
+ int allocated( void ) const;
+ const char * c_str( void ) const;
+
+ void append( const char *text );
+ void append( const idStr& text );
+ char operator[]( int index ) const;
+ char& operator[]( int index );
+
+ void operator=( const idStr& text );
+ void operator=( const char *text );
+
+ friend idStr operator+( const idStr& a, const idStr& b );
+ friend idStr operator+( const idStr& a, const char *b );
+ friend idStr operator+( const char *a, const idStr& b );
+
+ friend idStr operator+( const idStr& a, const float b );
+ friend idStr operator+( const idStr& a, const int b );
+ friend idStr operator+( const idStr& a, const unsigned b );
+ friend idStr operator+( const idStr& a, const bool b );
+ friend idStr operator+( const idStr& a, const char b );
+
+ idStr& operator+=( const idStr& a );
+ idStr& operator+=( const char *a );
+ idStr& operator+=( const float a );
+ idStr& operator+=( const char a );
+ idStr& operator+=( const int a );
+ idStr& operator+=( const unsigned a );
+ idStr& operator+=( const bool a );
+
+ friend bool operator==( const idStr& a, const idStr& b );
+ friend bool operator==( const idStr& a, const char *b );
+ friend bool operator==( const char *a, const idStr& b );
+
+ friend bool operator!=( const idStr& a, const idStr& b );
+ friend bool operator!=( const idStr& a, const char *b );
+ friend bool operator!=( const char *a, const idStr& b );
+
+ operator const char * () const;
+ operator const char * ();
+
+ int icmpn( const char *text, int n ) const;
+ int icmpn( const idStr& text, int n ) const;
+ int icmp( const char *text ) const;
+ int icmp( const idStr& text ) const;
+ int cmpn( const char *text, int n ) const;
+ int cmpn( const idStr& text, int n ) const;
+ int cmp( const char *text ) const;
+ int cmp( const idStr& text ) const;
+
+ void tolower( void );
+ void toupper( void );
+
+ static char *tolower( char *s1 );
+ static char *toupper( char *s1 );
+
+ static int icmpn( const char *s1, const char *s2, int n );
+ static int icmp( const char *s1, const char *s2 );
+ static int cmpn( const char *s1, const char *s2, int n );
+ static int cmp( const char *s1, const char *s2 );
+
+ static void snprintf ( char *dst, int size, const char *fmt, ... );
+
+ static bool isNumeric( const char *str );
+ bool isNumeric( void ) const;
+
+ void CapLength ( int );
+
+ void BackSlashesToSlashes ();
+
+};
+
+inline idStr::~idStr()
+ {
+ if ( m_data )
+ {
+ m_data->DelRef ();
+ m_data = NULL;
+ }
+ }
+
+inline idStr::idStr() : m_data ( NULL )
+ {
+ EnsureAlloced ( 1 );
+ m_data->data[ 0 ] = 0;
+ }
+
+inline idStr::idStr
+ (
+ const char *text
+ ) : m_data ( NULL )
+
+ {
+ int len;
+
+ assert( text );
+
+ if ( text )
+ {
+ len = strlen( text );
+ EnsureAlloced ( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+ else
+ {
+ EnsureAlloced ( 1 );
+ m_data->data[ 0 ] = 0;
+ m_data->len = 0;
+ }
+ }
+
+inline idStr::idStr
+ (
+ const idStr& text
+ ) : m_data ( NULL )
+
+ {
+ m_data = text.m_data;
+ m_data->AddRef ();
+ }
+
+inline idStr::idStr
+ (
+ const idStr text,
+ int start,
+ int end
+ ) : m_data ( NULL )
+
+ {
+ int i;
+ int len;
+
+ if ( end > text.length() )
+ {
+ end = text.length();
+ }
+
+ if ( start > text.length() )
+ {
+ start = text.length();
+ }
+
+ len = end - start;
+ if ( len < 0 )
+ {
+ len = 0;
+ }
+
+ EnsureAlloced ( len + 1 );
+
+ for( i = 0; i < len; i++ )
+ {
+ m_data->data[ i ] = text[ start + i ];
+ }
+
+ m_data->data[ len ] = 0;
+ m_data->len = len;
+ }
+
+inline idStr::idStr
+ (
+ const char ch
+ ) : m_data ( NULL )
+
+ {
+ EnsureAlloced ( 2 );
+
+ m_data->data[ 0 ] = ch;
+ m_data->data[ 1 ] = 0;
+ m_data->len = 1;
+ }
+
+inline idStr::idStr
+ (
+ const float num
+ ) : m_data ( NULL )
+
+ {
+ char text[ 32 ];
+ int len;
+
+ sprintf( text, "%.3f", num );
+ len = strlen( text );
+ EnsureAlloced( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline idStr::idStr
+ (
+ const int num
+ ) : m_data ( NULL )
+
+ {
+ char text[ 32 ];
+ int len;
+
+ sprintf( text, "%d", num );
+ len = strlen( text );
+ EnsureAlloced( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline idStr::idStr
+ (
+ const unsigned num
+ ) : m_data ( NULL )
+
+ {
+ char text[ 32 ];
+ int len;
+
+ sprintf( text, "%u", num );
+ len = strlen( text );
+ EnsureAlloced( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline int idStr::length( void ) const
+ {
+ return ( m_data != NULL ) ? m_data->len : 0;
+ }
+
+inline int idStr::allocated( void ) const
+ {
+ return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
+ }
+
+inline const char *idStr::c_str( void ) const
+ {
+ assert( m_data );
+
+ return m_data->data;
+ }
+
+inline void idStr::append
+ (
+ const char *text
+ )
+
+ {
+ int len;
+
+ assert( text );
+
+ if ( text )
+ {
+ len = length() + strlen( text );
+ EnsureAlloced( len + 1 );
+
+ strcat( m_data->data, text );
+ m_data->len = len;
+ }
+ }
+
+inline void idStr::append
+ (
+ const idStr& text
+ )
+
+ {
+ int len;
+
+ len = length() + text.length();
+ EnsureAlloced ( len + 1 );
+
+ strcat ( m_data->data, text.c_str () );
+ m_data->len = len;
+ }
+
+inline char idStr::operator[]( int index ) const
+ {
+ assert ( m_data );
+
+ if ( !m_data )
+ return 0;
+
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ assert( ( index >= 0 ) && ( index < m_data->len ) );
+
+ // In release mode, give them a null character
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ if ( ( index < 0 ) || ( index >= m_data->len ) )
+ {
+ return 0;
+ }
+
+ return m_data->data[ index ];
+ }
+
+inline char& idStr::operator[]
+ (
+ int index
+ )
+
+ {
+ // Used for result for invalid indices
+ static char dummy = 0;
+ assert ( m_data );
+
+ // We don't know if they'll write to it or not
+ // if it's not a const object
+ EnsureDataWritable ();
+
+ if ( !m_data )
+ return dummy;
+
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ assert( ( index >= 0 ) && ( index < m_data->len ) );
+
+ // In release mode, let them change a safe variable
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ if ( ( index < 0 ) || ( index >= m_data->len ) )
+ {
+ return dummy;
+ }
+
+ return m_data->data[ index ];
+ }
+
+inline void idStr::operator=
+ (
+ const idStr& text
+ )
+
+ {
+ // adding the reference before deleting our current reference prevents
+ // us from deleting our string if we are copying from ourself
+ text.m_data->AddRef();
+ m_data->DelRef();
+ m_data = text.m_data;
+ }
+
+inline void idStr::operator=
+ (
+ const char *text
+ )
+
+ {
+ int len;
+
+ assert( text );
+
+ if ( !text )
+ {
+ // safe behaviour if NULL
+ EnsureAlloced ( 1, false );
+ m_data->data[0] = 0;
+ m_data->len = 0;
+ return;
+ }
+
+ if ( !m_data )
+ {
+ len = strlen ( text );
+ EnsureAlloced( len + 1, false );
+ strcpy ( m_data->data, text );
+ m_data->len = len;
+ return;
+ }
+
+ if ( text == m_data->data )
+ return; // Copying same thing. Punt.
+
+ // If we alias and I don't do this, I could corrupt other strings... This
+ // will get called with EnsureAlloced anyway
+ EnsureDataWritable ();
+
+ // Now we need to check if we're aliasing..
+ if ( text >= m_data->data && text <= m_data->data + m_data->len )
+ {
+ // Great, we're aliasing. We're copying from inside ourselves.
+ // This means that I don't have to ensure that anything is alloced,
+ // though I'll assert just in case.
+ int diff = text - m_data->data;
+ int i;
+
+ assert ( strlen ( text ) < (unsigned) m_data->len );
+
+ for ( i = 0; text[i]; i++ )
+ {
+ m_data->data[i] = text[i];
+ }
+
+ m_data->data[i] = 0;
+
+ m_data->len -= diff;
+
+ return;
+ }
+
+ len = strlen( text );
+ EnsureAlloced ( len + 1, false );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const idStr& b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const char *b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const char *a,
+ const idStr& b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const bool b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b ? "true" : "false" );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const char b
+ )
+
+ {
+ char text[ 2 ];
+
+ text[ 0 ] = b;
+ text[ 1 ] = 0;
+
+ return a + text;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const idStr& a
+ )
+
+ {
+ append( a );
+ return *this;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const char *a
+ )
+
+ {
+ append( a );
+ return *this;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const char a
+ )
+
+ {
+ char text[ 2 ];
+
+ text[ 0 ] = a;
+ text[ 1 ] = 0;
+ append( text );
+
+ return *this;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const bool a
+ )
+
+ {
+ append( a ? "true" : "false" );
+ return *this;
+ }
+
+inline bool operator==
+ (
+ const idStr& a,
+ const idStr& b
+ )
+
+ {
+ return ( !strcmp( a.c_str(), b.c_str() ) );
+ }
+
+inline bool operator==
+ (
+ const idStr& a,
+ const char *b
+ )
+
+ {
+ assert( b );
+ if ( !b )
+ {
+ return false;
+ }
+ return ( !strcmp( a.c_str(), b ) );
+ }
+
+inline bool operator==
+ (
+ const char *a,
+ const idStr& b
+ )
+
+ {
+ assert( a );
+ if ( !a )
+ {
+ return false;
+ }
+ return ( !strcmp( a, b.c_str() ) );
+ }
+
+inline bool operator!=
+ (
+ const idStr& a,
+ const idStr& b
+ )
+
+ {
+ return !( a == b );
+ }
+
+inline bool operator!=
+ (
+ const idStr& a,
+ const char *b
+ )
+
+ {
+ return !( a == b );
+ }
+
+inline bool operator!=
+ (
+ const char *a,
+ const idStr& b
+ )
+
+ {
+ return !( a == b );
+ }
+
+inline int idStr::icmpn
+ (
+ const char *text,
+ int n
+ ) const
+
+ {
+ assert( m_data );
+ assert( text );
+
+ return idStr::icmpn( m_data->data, text, n );
+ }
+
+inline int idStr::icmpn
+ (
+ const idStr& text,
+ int n
+ ) const
+
+ {
+ assert( m_data );
+ assert( text.m_data );
+
+ return idStr::icmpn( m_data->data, text.m_data->data, n );
+ }
+
+inline int idStr::icmp
+ (
+ const char *text
+ ) const
+
+ {
+ assert( m_data );
+ assert( text );
+
+ return idStr::icmp( m_data->data, text );
+ }
+
+inline int idStr::icmp
+ (
+ const idStr& text
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text.c_str () );
+
+ return idStr::icmp( c_str () , text.c_str () );
+ }
+
+inline int idStr::cmp
+ (
+ const char *text
+ ) const
+
+ {
+ assert( m_data );
+ assert( text );
+
+ return idStr::cmp( m_data->data, text );
+ }
+
+inline int idStr::cmp
+ (
+ const idStr& text
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text.c_str () );
+
+ return idStr::cmp( c_str () , text.c_str () );
+ }
+
+inline int idStr::cmpn
+ (
+ const char *text,
+ int n
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text );
+
+ return idStr::cmpn( c_str () , text, n );
+ }
+
+inline int idStr::cmpn
+ (
+ const idStr& text,
+ int n
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text.c_str () );
+
+ return idStr::cmpn( c_str () , text.c_str () , n );
+ }
+
+inline void idStr::tolower
+ (
+ void
+ )
+
+ {
+ assert( m_data );
+
+ EnsureDataWritable ();
+
+ idStr::tolower( m_data->data );
+ }
+
+inline void idStr::toupper
+ (
+ void
+ )
+
+ {
+ assert( m_data );
+
+ EnsureDataWritable ();
+
+ idStr::toupper( m_data->data );
+ }
+
+inline bool idStr::isNumeric
+ (
+ void
+ ) const
+
+ {
+ assert( m_data );
+ return idStr::isNumeric( m_data->data );
+ }
+
+inline idStr::operator const char *() {
+ return c_str();
+}
+
+inline idStr::operator const char *
+ (
+ void
+ ) const
+
+ {
+ return c_str ();
+ }
+
+#endif \ No newline at end of file
diff --git a/q3radiant/terrain.cpp b/q3radiant/terrain.cpp
new file mode 100755
index 0000000..284d30b
--- /dev/null
+++ b/q3radiant/terrain.cpp
@@ -0,0 +1,1735 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+/*
+
+Todo:
+
+immediate:
+Texture placement
+New map format
+q3map
+
+
+later:
+Smoothing brush
+Stitching terrains together
+Cross terrain selection
+
+
+
+
+
+Terrain_ApplyMatrix
+UpdateTerrainInspector
+
+*/
+
+#include "stdafx.h"
+#include "qe3.h"
+#include "DialogInfo.h"
+#include "assert.h"
+
+//random in the range [0, 1]
+#define random() ((rand () & 0x7fff) / ((float)0x7fff))
+
+//random in the range [-1, 1]
+#define crandom() (2.0 * (random() - 0.5))
+
+typedef struct {
+ int index;
+ vec3_t xyz;
+ vec4_t rgba;
+ vec2_t tc;
+} terravert_t;
+
+/*
+==============
+Terrain_SetEpair
+sets an epair for the given patch
+==============
+*/
+void Terrain_SetEpair( terrainMesh_t *p, const char *pKey, const char *pValue ) {
+ if ( g_qeglobals.m_bBrushPrimitMode ) {
+ SetKeyValue( p->epairs, pKey, pValue );
+ }
+}
+
+/*
+=================
+Terrain_GetKeyValue
+=================
+*/
+const char *Terrain_GetKeyValue( terrainMesh_t *p, const char *pKey ) {
+ if ( g_qeglobals.m_bBrushPrimitMode ) {
+ return ValueForKey( p->epairs, pKey );
+ }
+ return "";
+}
+
+/*
+==================
+Terrain_MemorySize
+==================
+*/
+int Terrain_MemorySize( terrainMesh_t *p ) {
+ return _msize( p );
+}
+
+void Terrain_GetVert( terrainMesh_t *pm, int x, int y, float s, float t, terravert_t *v, qtexture_t *texture = NULL ) {
+ terrainVert_t *cell;
+
+ v->index = x + y * pm->width;
+
+ cell = &pm->heightmap[ v->index ];
+
+ v->xyz[ 0 ] = pm->origin[ 0 ] + x * pm->scale_x;
+ v->xyz[ 1 ] = pm->origin[ 1 ] + y * pm->scale_y;
+ v->xyz[ 2 ] = pm->origin[ 2 ] + cell->height;
+
+ VectorCopy( cell->rgba, v->rgba );
+
+ if ( !texture || ( texture == cell->tri.texture ) ) {
+ v->rgba[ 3 ] = 1.0f;
+ } else {
+ v->rgba[ 3 ] = 0.0f;
+ }
+
+ v->tc[ 0 ] = s;
+ v->tc[ 1 ] = t;
+}
+
+void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terravert_t *a0, terravert_t *a1, terravert_t *a2, terravert_t *b0, terravert_t *b1, terravert_t *b2, qtexture_t *texture ) {
+ if ( ( x + y ) & 1 ) {
+ // first tri
+ Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0, texture );
+ Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1, texture );
+ Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a2, texture );
+
+ // second tri
+ *b0 = *a2;
+ Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, b1, texture );
+ *b2 = *a0;
+ } else {
+ // first tri
+ Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0, texture );
+ Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1, texture );
+ Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a2, texture );
+
+ // second tri
+ *b0 = *a2;
+ *b1 = *a1;
+ Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, b2, texture );
+ }
+}
+
+void Terrain_GetTriangle( terrainMesh_t *pm, int index, terravert_t *a0, terravert_t *a1, terravert_t *a2 ) {
+ int x;
+ int y;
+ int which;
+
+ which = index & 1;
+ index >>= 1;
+ y = index / pm->width;
+ x = index % pm->width;
+
+ if ( ( x + y ) & 1 ) {
+ if ( !which ) {
+ // first tri
+ Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0 );
+ Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1 );
+ Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a2 );
+ } else {
+ Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a0 );
+ Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a1 );
+ Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a2 );
+ }
+ } else {
+ if ( !which ) {
+ // first tri
+ Terrain_GetVert( pm, x, y, 1.0f, 1.0f, a0 );
+ Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1 );
+ Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a2 );
+ } else {
+ Terrain_GetVert( pm, x + 1, y, 0.0f, 1.0f, a0 );
+ Terrain_GetVert( pm, x, y + 1, 1.0f, 0.0f, a1 );
+ Terrain_GetVert( pm, x + 1, y + 1, 0.0f, 0.0f, a2 );
+ }
+ }
+}
+
+void Terrain_Delete( terrainMesh_t *p ) {
+ if ( p->pSymbiot ) {
+ p->pSymbiot->pTerrain = NULL;
+ p->pSymbiot->terrainBrush = false;
+ }
+
+ free( p );
+
+ p = NULL;
+
+ UpdateTerrainInspector();
+}
+
+void Terrain_AddTexture( terrainMesh_t *pm, qtexture_t *texture ) {
+ int i;
+
+ if ( !texture ) {
+ return;
+ }
+
+ for( i = 0; i < pm->numtextures; i++ ) {
+ if ( pm->textures[ i ] == texture ) {
+ return;
+ }
+ }
+
+ if ( pm->numtextures >= MAX_TERRAIN_TEXTURES ) {
+ Warning( "Too many textures on terrain" );
+ return;
+ }
+
+ pm->textures[ pm->numtextures++ ] = texture;
+}
+
+void Terrain_RemoveTexture( terrainMesh_t *p, qtexture_t *texture ) {
+ int i;
+
+ for( i = 0; i < p->numtextures; i++ ) {
+ if ( p->textures[ i ] == texture ) {
+ break;
+ }
+ }
+
+ if ( i < p->numtextures ) {
+ // shift all textures down to remove the texture from the list
+ p->numtextures--;
+ for( ; i < p->numtextures; i++ ) {
+ p->textures[ i ] = p->textures[ i + 1 ];
+ }
+ }
+}
+
+terrainMesh_t *MakeNewTerrain( int width, int height, qtexture_t *texture ) {
+ int h;
+ int w;
+ terrainMesh_t *pm;
+ size_t size;
+ size_t heightmapsize;
+ terrainVert_t *vert;
+ int index;
+
+ heightmapsize = sizeof( terrainVert_t ) * width * height;
+ size = sizeof( terrainMesh_t ) + heightmapsize;
+
+ pm = reinterpret_cast< terrainMesh_t * >( qmalloc( size ) );
+
+ memset( pm, 0x00, size );
+
+ pm->numtextures = 0;
+ pm->width = width;
+ pm->height = height;
+ pm->heightmap = reinterpret_cast< terrainVert_t * >( pm + 1 );
+
+ if ( texture ) {
+ Terrain_AddTexture( pm, texture );
+ }
+
+ index = 0;
+ vert = pm->heightmap;
+ for( h = 0; h < pm->height; h++ ) {
+ for( w = 0; w < pm->width; w++, vert++ ) {
+ vert->tri.index = index++;
+ vert->tri.texture = texture;
+ if ( texture ) {
+ vert->tri.texdef.SetName( texture->name );
+ }
+
+ vert->height = 0;
+
+ VectorClear( vert->normal );
+ VectorSet( vert->rgba, 1.0f, 1.0f, 1.0f );
+ vert->rgba[ 3 ] = 1.0f;
+ }
+ }
+
+ return pm;
+}
+
+brush_t *AddBrushForTerrain( terrainMesh_t *pm, bool bLinkToWorld ) {
+ int j;
+ vec3_t vMin;
+ vec3_t vMax;
+ brush_t *b;
+ face_t *f;
+
+ // calculate the face normals
+ Terrain_CalcNormals( pm );
+
+ // find the farthest points in x,y,z
+ Terrain_CalcBounds( pm, vMin, vMax );
+
+ for( j = 0; j < 3; j++ ) {
+ if ( vMin[ j ] == vMax[ j ] ) {
+ vMin[ j ] -= 4;
+ vMax[ j ] += 4;
+ }
+ }
+
+ b = Brush_Create( vMin, vMax, &pm->heightmap->tri.texdef );
+
+ for( f = b->brush_faces; f != NULL; f = f->next ) {
+ // copy the texdef to the brush faces texdef
+ f->texdef = pm->heightmap->tri.texdef;
+ }
+
+ // FIXME: this entire type of linkage needs to be fixed
+ b->pTerrain = pm;
+ b->terrainBrush = true;
+ pm->pSymbiot = b;
+ pm->bSelected = false;
+ pm->bDirty = true;
+ pm->nListID = -1;
+
+ if ( bLinkToWorld ) {
+ Brush_AddToList( b, &active_brushes );
+ Entity_LinkBrush( world_entity, b );
+ Brush_Build( b, true );
+ }
+
+ return b;
+}
+
+terrainMesh_t *Terrain_Duplicate( terrainMesh_t *pFrom ) {
+ terrainMesh_t *p;
+ int w;
+ int h;
+ int index;
+
+ p = MakeNewTerrain( pFrom->width, pFrom->height );
+
+ VectorCopy( pFrom->origin, p->origin );
+ VectorCopy( pFrom->mins, p->mins );
+ VectorCopy( pFrom->maxs, p->maxs );
+
+ p->scale_x = pFrom->scale_x;
+ p->scale_y = pFrom->scale_y;
+ p->pSymbiot = pFrom->pSymbiot;
+
+ for( index = 0; index < pFrom->numtextures; index++ ) {
+ Terrain_AddTexture( p, pFrom->textures[ index ] );
+ }
+
+ index = 0;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, index++ ) {
+ p->heightmap[ index ] = pFrom->heightmap[ index ];
+ }
+ }
+
+ p->bSelected = false;
+ p->bDirty = true;
+ p->nListID = -1;
+
+ AddBrushForTerrain( p );
+
+ return p;
+}
+
+void Terrain_BrushToMesh( void ) {
+ brush_t *b;
+ terrainMesh_t *p;
+
+ if ( !QE_SingleBrush() ) {
+ return;
+ }
+
+ b = selected_brushes.next;
+
+ if ( g_qeglobals.d_terrainWidth < 1 ) {
+ g_qeglobals.d_terrainWidth = 1;
+ }
+
+ if ( g_qeglobals.d_terrainHeight < 1 ) {
+ g_qeglobals.d_terrainHeight = 1;
+ }
+
+ p = MakeNewTerrain( g_qeglobals.d_terrainWidth + 1, g_qeglobals.d_terrainHeight + 1, b->brush_faces->d_texture );
+ p->scale_x = ( b->maxs[ 0 ] - b->mins[ 0 ] ) / float( p->width - 1 );
+ p->scale_y = ( b->maxs[ 1 ] - b->mins[ 1 ] ) / float( p->height - 1 );
+
+ VectorCopy( b->mins, p->origin );
+
+ b = AddBrushForTerrain( p );
+ Select_Delete();
+ Select_Brush( b );
+}
+
+terrainFace_t *Terrain_ParseFace( terrainFace_t *f ) {
+ // read the texturename
+ GetToken( false );
+ f->texdef.SetName( token );
+
+ // Load the texture, and set the face to that texture's defaults
+ f->texture = Texture_ForName( f->texdef.Name() );
+
+ // read the texturedef
+ GetToken( false );
+ f->texdef.shift[ 0 ] = ( float )atoi( token );
+ GetToken( false );
+ f->texdef.shift[ 1 ] = ( float )atoi( token );
+ GetToken( false );
+ f->texdef.rotate = atof( token );
+ GetToken( false );
+ f->texdef.scale[ 0 ] = atof( token );
+ GetToken( false );
+ f->texdef.scale[ 1 ] = atof( token );
+
+ // the flags and value field aren't necessarily present
+ //f->texture = Texture_ForName( f->texdef.Name() );
+ f->texdef.flags = f->texture->flags;
+ f->texdef.value = f->texture->value;
+ f->texdef.contents = f->texture->contents;
+
+ if ( TokenAvailable () ) {
+ GetToken (false);
+ f->texdef.contents = atoi(token);
+ GetToken (false);
+ f->texdef.flags = atoi(token);
+ GetToken (false);
+ f->texdef.value = atoi(token);
+ }
+
+ return f;
+}
+
+brush_t *Terrain_Parse( void ) {
+ terrainMesh_t *pm;
+ terrainVert_t *vert;
+ int w;
+ int h;
+
+ GetToken( true );
+ if ( strcmp( token, "{" ) ) {
+ return NULL;
+ }
+
+ // get width
+ GetToken( false );
+ w = atoi( token );
+
+ // get height
+ GetToken( false );
+ h = atoi( token );
+
+ pm = MakeNewTerrain( w, h );
+
+ // get scale_x
+ GetToken( false );
+ pm->scale_x = atoi( token );
+
+ // get scale_y
+ GetToken( false );
+ pm->scale_y = atoi( token );
+
+ // get origin
+ GetToken( true );
+ pm->origin[ 0 ] = atoi( token );
+ GetToken( false );
+ pm->origin[ 1 ] = atoi( token );
+ GetToken( false );
+ pm->origin[ 2 ] = atoi( token );
+
+ // get the height map
+ vert = pm->heightmap;
+ for( h = 0; h < pm->height; h++ ) {
+ for( w = 0; w < pm->width; w++, vert++ ) {
+ GetToken( true );
+ vert->height = atoi( token );
+
+ if ( !Terrain_ParseFace( &vert->tri ) ) {
+ Terrain_Delete( pm );
+ return NULL;
+ }
+
+ Terrain_AddTexture( pm, vert->tri.texture );
+ }
+ }
+
+ GetToken( true );
+ if ( strcmp( token, "}" ) ) {
+ Terrain_Delete( pm );
+ return NULL;
+ }
+
+ return AddBrushForTerrain( pm, false );
+}
+
+CString Terrain_SurfaceString( terrainFace_t *face ) {
+ char temp[ 1024 ];
+ CString text;
+ const char *pname;
+
+ pname = face->texdef.Name();
+ if ( pname[ 0 ] == 0 ) {
+ pname = "unnamed";
+ }
+
+ sprintf( temp, "%s %i %i %.2f ", pname, ( int )face->texdef.shift[ 0 ], ( int )face->texdef.shift[ 1 ], face->texdef.rotate );
+ text += temp;
+
+ if ( face->texdef.scale[ 0 ] == ( int )face->texdef.scale[ 0 ] ) {
+ sprintf( temp, "%i ", ( int )face->texdef.scale[ 0 ] );
+ } else {
+ sprintf( temp, "%f ", ( float )face->texdef.scale[ 0 ] );
+ }
+ text += temp;
+
+ if ( face->texdef.scale[ 1 ] == (int)face->texdef.scale[ 1 ] ) {
+ sprintf( temp, "%i", ( int )face->texdef.scale[ 1 ] );
+ } else {
+ sprintf( temp, "%f", ( float )face->texdef.scale[ 1 ] );
+ }
+ text += temp;
+
+ // only output flags and value if not default
+ sprintf( temp, " %i %i %i ", face->texdef.contents, face->texdef.flags, face->texdef.value );
+ text += temp;
+
+ return text;
+}
+
+void Terrain_Write( terrainMesh_t *p, CMemFile *file ) {
+ int w;
+ int h;
+ terrainVert_t *vert;
+
+ MemFile_fprintf( file, " {\n terrainDef\n {\n" );
+ MemFile_fprintf( file, " %d %d %f %f\n", p->width, p->height, p->scale_x, p->scale_y );
+ MemFile_fprintf( file, " %f %f %f\n", p->origin[ 0 ], p->origin[ 1 ], p->origin[ 2 ] );
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ MemFile_fprintf( file, " %f %s\n", vert->height, ( const char * )Terrain_SurfaceString( &vert->tri ) );
+ }
+ }
+
+ MemFile_fprintf( file, " }\n }\n" );
+}
+
+void Terrain_Write( terrainMesh_t *p, FILE *file ) {
+ int w;
+ int h;
+ terrainVert_t *vert;
+
+ fprintf( file, " {\n terrainDef\n {\n" );
+ fprintf( file, " %d %d %f %f\n", p->width, p->height, p->scale_x, p->scale_y );
+ fprintf( file, " %f %f %f\n", p->origin[ 0 ], p->origin[ 1 ], p->origin[ 2 ] );
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ fprintf( file, " %f %s\n", vert->height, ( const char * )Terrain_SurfaceString( &vert->tri ) );
+ }
+ }
+
+ fprintf( file, " }\n }\n" );
+}
+
+void Terrain_Select( terrainMesh_t *p ) {
+ p->bSelected = true;
+}
+
+void Terrain_Deselect( terrainMesh_t *p ) {
+ p->bSelected = false;
+}
+
+void Terrain_Move( terrainMesh_t *pm, const vec3_t vMove, bool bRebuild ) {
+ pm->bDirty = true;
+
+ VectorAdd( pm->origin, vMove, pm->origin );
+
+ if ( bRebuild ) {
+ vec3_t vMin;
+ vec3_t vMax;
+
+ Terrain_CalcBounds( pm, vMin, vMax );
+ }
+
+ UpdateTerrainInspector();
+}
+
+void UpdateTerrainInspector( void ) {
+ // not written yet
+}
+
+void Terrain_CalcBounds( terrainMesh_t *p, vec3_t &vMin, vec3_t &vMax ) {
+ int w;
+ int h;
+ float f;
+ terrainVert_t *vert;
+
+ vMin[ 0 ] = p->origin[ 0 ];
+ vMin[ 1 ] = p->origin[ 1 ];
+ vMin[ 2 ] = MAX_WORLD_COORD;
+
+ vMax[ 0 ] = p->origin[ 0 ] + ( p->width - 1 ) * p->scale_x;
+ vMax[ 1 ] = p->origin[ 1 ] + ( p->height - 1 ) * p->scale_y;
+ vMax[ 2 ] = MIN_WORLD_COORD;
+
+ p->bDirty = true;
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ f = p->origin[ 2 ] + vert->height;
+ if ( f < vMin[ 2 ] ) {
+ vMin[ 2 ] = f;
+ }
+
+ if ( f > vMax[ 2 ] ) {
+ vMax[ 2 ] = f;
+ }
+ }
+ }
+}
+
+void CalcTriNormal( const vec3_t a, const vec3_t b, const vec3_t c, vec3_t o ) {
+ vec3_t a1;
+ vec3_t b1;
+
+ VectorSubtract( b, a, a1 );
+ VectorNormalize( a1 );
+
+ VectorSubtract( c, a, b1 );
+ VectorNormalize( b1 );
+
+ CrossProduct( a1, b1, o );
+ VectorNormalize( o );
+}
+
+inline void Terrain_CalcVertPos( terrainMesh_t *p, int x, int y, vec3_t vert ) {
+ int index;
+
+ index = x + y * p->width;
+ vert[ 0 ] = p->origin[ 0 ] + x * p->scale_x;
+ vert[ 1 ] = p->origin[ 1 ] + y * p->scale_y;
+ vert[ 2 ] = p->origin[ 2 ] + p->heightmap[ index ].height;
+
+ VectorCopy( vert, p->heightmap[ index ].xyz );
+}
+
+void Terrain_CalcNormals( terrainMesh_t *p ) {
+ int x;
+ int y;
+ int width;
+ int num;
+ terrainVert_t *vert;
+ vec3_t norm;
+ terravert_t a0;
+ terravert_t a1;
+ terravert_t a2;
+ terravert_t b0;
+ terravert_t b1;
+ terravert_t b2;
+
+ p->bDirty = true;
+
+ num = p->height * p->width;
+ vert = p->heightmap;
+ //for( x = 0; x < num; x++, vert++ ) {
+ for( y = 0; y < p->height - 1; y++ ) {
+ for( x = 0; x < p->width - 1; x++, vert++ ) {
+ VectorClear( vert->normal );
+ Terrain_CalcVertPos( p, x, y, norm );
+ }
+ }
+
+ width = p->width;
+ vert = p->heightmap;
+
+ for( y = 0; y < p->height - 1; y++ ) {
+ for( x = 0; x < width - 1; x++ ) {
+ Terrain_GetTriangles( p, x, y, &a0, &a1, &a2, &b0, &b1, &b2, NULL );
+
+ CalcTriNormal( a0.xyz, a2.xyz, a1.xyz, norm );
+
+ VectorAdd( vert[ a0.index ].normal, norm, vert[ a0.index ].normal );
+ VectorAdd( vert[ a1.index ].normal, norm, vert[ a1.index ].normal );
+ VectorAdd( vert[ a2.index ].normal, norm, vert[ a2.index ].normal );
+
+ CalcTriNormal( b0.xyz, b2.xyz, b1.xyz, norm );
+
+ VectorAdd( vert[ b0.index ].normal, norm, vert[ b0.index ].normal );
+ VectorAdd( vert[ b1.index ].normal, norm, vert[ b1.index ].normal );
+ VectorAdd( vert[ b2.index ].normal, norm, vert[ b2.index ].normal );
+ }
+ }
+
+ for( x = 0; x < num; x++, vert++ ) {
+ VectorNormalize( vert->normal );
+ //FIXME
+ vert->normal[ 2 ] += 0.5;
+ VectorNormalize( vert->normal );
+ assert( vert->normal[ 2 ] > 0 );
+ VectorSet( vert->rgba, vert->normal[ 2 ], vert->normal[ 2 ], vert->normal[ 2 ] );
+ vert->rgba[ 3 ] = 1.0f;
+ }
+}
+
+void Terrain_FindReplaceTexture( terrainMesh_t *p, const char *pFind, const char *pReplace, bool bForce ) {
+ int w;
+ int h;
+ terrainVert_t *vert;
+ qtexture_t *texture;
+
+ texture = Texture_ForName( pReplace );
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ if ( bForce || strcmpi( vert->tri.texture->name, pFind ) == 0 ) {
+ vert->tri.texture = texture;
+ vert->tri.texdef.SetName( texture->name );
+ }
+ }
+ }
+
+ if ( bForce ) {
+ p->numtextures = 0;
+ Terrain_AddTexture( p, Texture_ForName( pReplace ) );
+ } else {
+ Terrain_RemoveTexture( p, Texture_ForName( pFind ) );
+ Terrain_AddTexture( p, texture );
+ }
+}
+
+bool Terrain_HasTexture( terrainMesh_t *p, const char *name ) {
+ int w;
+ int h;
+ terrainVert_t *vert;
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ if ( strcmpi( vert->tri.texture->name, name ) == 0 ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+void Terrain_ReplaceQTexture( terrainMesh_t *p, qtexture_t *pOld, qtexture_t *pNew ) {
+ int w;
+ int h;
+ terrainVert_t *vert;
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ if ( vert->tri.texture == pOld ) {
+ vert->tri.texture = pNew;
+ vert->tri.texdef.SetName( pNew->name );
+ }
+ }
+ }
+
+ Terrain_RemoveTexture( p, pOld );
+ Terrain_AddTexture( p, pNew );
+}
+
+void Terrain_SetTexture( terrainMesh_t *p, texdef_t *tex_def ) {
+ int w;
+ int h;
+ qtexture_t *newtex;
+ terrainVert_t *vert;
+
+ p->bDirty = 1;
+
+ newtex = Texture_ForName( tex_def->name );
+
+ p->numtextures = 0;
+ Terrain_AddTexture( p, newtex );
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ for( w = 0; w < p->width; w++, vert++ ) {
+ vert->tri.texture = newtex;
+ vert->tri.texdef.SetName( newtex->name );
+ }
+ }
+
+ UpdateTerrainInspector();
+}
+
+void Terrain_Scale( terrainMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuild ) {
+ int w;
+ int h;
+ vec3_t pos;
+ terrainVert_t *vert;
+ vec3_t vMin;
+ vec3_t vMax;
+
+ vert = p->heightmap;
+ for( h = 0; h < p->height; h++ ) {
+ pos[ 1 ] = p->origin[ 1 ] + h * p->scale_y;
+ for( w = 0; w < p->width; w++, vert++ ) {
+ pos[ 0 ] = p->origin[ 0 ] + w * p->scale_x;
+ pos[ 2 ] = vert->height;
+
+ if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) && ( Terrain_PointInMoveList( vert ) == -1 ) ) {
+ continue;
+ }
+
+ vert->height -= vOrigin[ 2 ] - p->origin[ 2 ];
+ vert->height *= vAmt[ 2 ];
+ vert->height += vOrigin[ 2 ] - p->origin[ 2 ];
+ }
+ }
+
+ if ( g_qeglobals.d_select_mode != sel_terrainpoint ) {
+ p->scale_x *= vAmt[ 0 ];
+ p->scale_y *= vAmt[ 1 ];
+
+ p->origin[ 0 ] -= vOrigin[ 0 ];
+ p->origin[ 0 ] *= vAmt[ 0 ];
+ p->origin[ 0 ] += vOrigin[ 0 ];
+
+ p->origin[ 1 ] -= vOrigin[ 1 ];
+ p->origin[ 1 ] *= vAmt[ 1 ];
+ p->origin[ 1 ] += vOrigin[ 1 ];
+ }
+
+ if ( bRebuild ) {
+ Terrain_CalcBounds( p, vMin, vMax );
+ Terrain_CalcNormals( p );
+ Brush_RebuildBrush( p->pSymbiot, vMin, vMax );
+ }
+
+ UpdateTerrainInspector();
+}
+
+bool Terrain_DragScale( terrainMesh_t *p, vec3_t vAmt, vec3_t vMove ) {
+ vec3_t vMin;
+ vec3_t vMax;
+ vec3_t vScale;
+ vec3_t vTemp;
+ vec3_t vMid;
+ int i;
+
+ Terrain_CalcBounds( p, vMin, vMax );
+
+ VectorSubtract( vMax, vMin, vTemp );
+
+ // if we are scaling in the same dimension the terrain has no depth
+ for( i = 0; i < 3; i++ ) {
+ if ( ( vTemp[ i ] == 0 ) && ( vMove[ i ] != 0 ) ) {
+ return false;
+ }
+ }
+
+ for( i = 0; i < 3; i++ ) {
+ vMid[ i ] = ( vMin[ i ] + vMax[ i ] ) / 2;
+ }
+
+ for( i = 0; i < 3; i++ ) {
+ if ( vAmt[ i ] != 0 ) {
+ vScale[i] = 1.0 + vAmt[i] / vTemp[i];
+ } else {
+ vScale[i] = 1.0;
+ }
+ }
+
+ Terrain_Scale( p, vMid, vScale, false );
+ VectorSubtract( vMax, vMin, vTemp );
+ Terrain_CalcBounds( p, vMin, vMax );
+ VectorSubtract( vMax, vMin, vMid );
+ VectorSubtract( vMid, vTemp, vTemp );
+ VectorScale( vTemp, 0.5f, vTemp );
+
+ // abs of both should always be equal
+ if ( !VectorCompare( vMove, vAmt ) ) {
+ for( i = 0; i < 3; i++ ) {
+ if ( vMove[ i ] != vAmt[ i ] ) {
+ vTemp[ i ] = -vTemp[ i ];
+ }
+ }
+ }
+
+ Terrain_CalcNormals( p );
+ Terrain_Move( p, vTemp );
+
+ return true;
+}
+
+void Terrain_ApplyMatrix( terrainMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[ 3 ], bool bSnap ) {
+}
+
+void Terrain_DrawFace( brush_t *brush, terrainFace_t *terraface ) {
+ terrainMesh_t *pm;
+ terravert_t a0;
+ terravert_t a1;
+ terravert_t a2;
+
+ pm = brush->pTerrain;
+
+ Terrain_GetTriangle( pm, terraface->index, &a0, &a1, &a2 );
+
+ qglBindTexture( GL_TEXTURE_2D, terraface->texture->texture_number );
+ qglBegin( GL_TRIANGLES );
+
+ // first tri
+ qglColor4fv( a0.rgba );
+ qglTexCoord2fv( a0.tc );
+ qglVertex3fv( a0.xyz );
+
+ qglColor4fv( a1.rgba );
+ qglTexCoord2fv( a1.tc );
+ qglVertex3fv( a1.xyz );
+
+ qglColor4fv( a2.rgba );
+ qglTexCoord2fv( a2.tc );
+ qglVertex3fv( a2.xyz );
+
+ qglEnd ();
+}
+
+void DrawTerrain( terrainMesh_t *pm, bool bPoints, bool bShade ) {
+ int i;
+ int w;
+ int h;
+ int x;
+ int y;
+ //int n;
+ //float x1;
+ //float y1;
+ float scale_x;
+ float scale_y;
+ //vec3_t pSelectedPoints[ MAX_TERRA_POINTS ];
+ //int nIndex;
+ terravert_t a0;
+ terravert_t a1;
+ terravert_t a2;
+ terravert_t b0;
+ terravert_t b1;
+ terravert_t b2;
+ terrainVert_t *vert;
+ qtexture_t *texture;
+
+ h = pm->height - 1;
+ w = pm->width - 1;
+
+ scale_x = pm->scale_x;
+ scale_y = pm->scale_y;
+
+ qglShadeModel (GL_SMOOTH);
+
+ if ( bShade ) {
+ for( i = 0; i < pm->numtextures; i++ ) {
+ texture = pm->textures[ i ];
+
+ qglBindTexture( GL_TEXTURE_2D, texture->texture_number );
+
+ vert = pm->heightmap;
+ for( y = 0; y < h; y++ ) {
+ qglBegin( GL_TRIANGLES );
+
+ for( x = 0; x < w; x++, vert++ ) {
+ Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, texture );
+
+ // first tri
+ if ( a0.rgba[ 3 ] || a1.rgba[ 3 ] || a2.rgba[ 3 ] ) {
+ qglColor4fv( a0.rgba );
+ qglTexCoord2fv( a0.tc );
+ qglVertex3fv( a0.xyz );
+
+ qglColor4fv( a1.rgba );
+ qglTexCoord2fv( a1.tc );
+ qglVertex3fv( a1.xyz );
+
+ qglColor4fv( a2.rgba );
+ qglTexCoord2fv( a2.tc );
+ qglVertex3fv( a2.xyz );
+ }
+
+ // second tri
+ if ( b0.rgba[ 3 ] || b1.rgba[ 3 ] || b2.rgba[ 3 ] ) {
+ qglColor4fv( b0.rgba );
+ qglTexCoord2fv( b0.tc );
+ qglVertex3fv( b0.xyz );
+
+ qglColor4fv( b1.rgba );
+ qglTexCoord2fv( b1.tc );
+ qglVertex3fv( b1.xyz );
+
+ qglColor4fv( b2.rgba );
+ qglTexCoord2fv( b2.tc );
+ qglVertex3fv( b2.xyz );
+ }
+ }
+
+ qglEnd ();
+ }
+ }
+ } else {
+ for( i = 0; i < pm->numtextures; i++ ) {
+ texture = pm->textures[ i ];
+
+ qglBindTexture( GL_TEXTURE_2D, texture->texture_number );
+
+ vert = pm->heightmap;
+ for( y = 0; y < h; y++ ) {
+ qglBegin( GL_TRIANGLES );
+
+ for( x = 0; x < w; x++, vert++ ) {
+ Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, texture );
+
+ // first tri
+ if ( a0.rgba[ 3 ] || a1.rgba[ 3 ] || a2.rgba[ 3 ] ) {
+ qglColor4fv( a0.rgba );
+ qglTexCoord2fv( a0.tc );
+ qglVertex3fv( a0.xyz );
+
+ qglColor4fv( a1.rgba );
+ qglTexCoord2fv( a1.tc );
+ qglVertex3fv( a1.xyz );
+
+ qglColor4fv( a2.rgba );
+ qglTexCoord2fv( a2.tc );
+ qglVertex3fv( a2.xyz );
+ }
+
+ // second tri
+ if ( b0.rgba[ 3 ] || b1.rgba[ 3 ] || b2.rgba[ 3 ] ) {
+ qglColor4fv( b0.rgba );
+ qglTexCoord2fv( b0.tc );
+ qglVertex3fv( b0.xyz );
+
+ qglColor4fv( b1.rgba );
+ qglTexCoord2fv( b1.tc );
+ qglVertex3fv( b1.xyz );
+
+ qglColor4fv( b2.rgba );
+ qglTexCoord2fv( b2.tc );
+ qglVertex3fv( b2.xyz );
+ }
+ }
+ qglEnd ();
+ }
+ }
+ }
+
+ qglPushAttrib( GL_CURRENT_BIT );
+
+ bool bDisabledLighting = qglIsEnabled( GL_LIGHTING );
+ if ( bDisabledLighting ) {
+ qglDisable( GL_LIGHTING );
+ }
+
+#if 0
+ terrainVert_t *currentrow;
+ terrainVert_t *nextrow;
+ float x2;
+ float y2;
+
+ // Draw normals
+ qglDisable( GL_TEXTURE_2D );
+ qglDisable( GL_BLEND );
+ qglColor3f( 1, 1, 1 );
+ qglBegin( GL_LINES );
+
+ y2 = pm->origin[ 1 ];
+ nextrow = pm->heightmap;
+ for( y = 0; y < h; y++ ) {
+ y1 = y2;
+ y2 += scale_y;
+
+ x2 = pm->origin[ 0 ];
+ currentrow = nextrow;
+ nextrow = currentrow + pm->width;
+ for( x = 0; x < w; x++ ) {
+ x1 = x2;
+ x2 += scale_x;
+
+ // normals
+ qglVertex3f( x1, y1, pm->origin[ 2 ] + currentrow[ x ].height );
+ qglVertex3f( x1 + currentrow[ x ].normal[ 0 ] * 16.0f, y1 + currentrow[ x ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + currentrow[ x ].height + currentrow[ x ].normal[ 2 ] * 16.0f );
+
+ qglVertex3f( x2, y1, pm->origin[ 2 ] + currentrow[ x + 1 ].height );
+ qglVertex3f( x2 + currentrow[ x + 1 ].normal[ 0 ] * 16.0f, y1 + currentrow[ x + 1 ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + currentrow[ x + 1 ].height + currentrow[ x + 1 ].normal[ 2 ] * 16.0f );
+
+ qglVertex3f( x1, y2, pm->origin[ 2 ] + nextrow[ x ].height );
+ qglVertex3f( x1 + nextrow[ x ].normal[ 0 ] * 16.0f, y2 + nextrow[ x ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + nextrow[ x ].height + nextrow[ x ].normal[ 2 ] * 16.0f );
+
+ qglVertex3f( x2, y2, pm->origin[ 2 ] + nextrow[ x + 1 ].height );
+ qglVertex3f( x2 + nextrow[ x + 1 ].normal[ 0 ] * 16.0f, y2 + nextrow[ x + 1 ].normal[ 1 ] * 16.0f, pm->origin[ 2 ] + nextrow[ x + 1 ].height + nextrow[ x + 1 ].normal[ 2 ] * 16.0f );
+ }
+ }
+
+ qglEnd ();
+ qglEnable( GL_TEXTURE_2D );
+#endif
+
+#if 0
+ if ( bPoints && ( g_qeglobals.d_select_mode == sel_terrainpoint || g_qeglobals.d_select_mode == sel_area ) ) {
+ qglPointSize( 6 );
+ qglDisable( GL_TEXTURE_2D );
+ qglDisable( GL_BLEND );
+
+ qglBegin( GL_POINTS );
+
+ nIndex = 0;
+
+ qglColor4f( 1, 0, 1, 1 );
+
+ y1 = pm->origin[ 1 ];
+ for ( y = 0; y < pm->height; y++, y1 += pm->scale_y ) {
+ x1 = pm->origin[ 0 ];
+ for( x = 0; x < pm->width; x++, x1 += pm->scale_x ) {
+ // FIXME: need to not do loop lookups inside here
+ n = Terrain_PointInMoveList( &pm->heightmap[ x + y * pm->width ] );
+ if ( n >= 0 ) {
+ VectorSet( pSelectedPoints[ nIndex ], x1, y1, pm->heightmap[ x + y * pm->width ].height + pm->origin[ 2 ] );
+ nIndex++;
+ } else {
+ qglVertex3f( x1, y1, pm->origin[ 2 ] + pm->heightmap[ x + y * pm->width ].height );
+ }
+ }
+ }
+
+ qglEnd();
+
+ qglEnable( GL_TEXTURE_2D );
+
+ if ( nIndex > 0 ) {
+ qglBegin( GL_POINTS );
+ qglColor4f( 0, 0, 1, 1 );
+ while( nIndex-- > 0 ) {
+ qglVertex3fv( pSelectedPoints[ nIndex ] );
+ }
+
+ qglEnd();
+ }
+ }
+#endif
+
+ if ( g_qeglobals.d_numterrapoints && ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) ) ) {
+#if 0
+ qglPointSize( 6 );
+ qglDisable( GL_TEXTURE_2D );
+ qglDisable( GL_BLEND );
+
+ qglBegin( GL_POINTS );
+
+ qglColor4f( 1, 0, 1, 1 );
+
+ for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
+ qglVertex3fv( g_qeglobals.d_terrapoints[ i ]->xyz );
+ }
+
+ qglEnd();
+
+ qglEnable( GL_TEXTURE_2D );
+#endif
+
+ brush_t *pb;
+ terrainMesh_t *pm;
+
+ pm = NULL;
+ for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ pm = pb->pTerrain;
+ break;
+ }
+ }
+
+ if ( pm ) {
+ qglDisable( GL_TEXTURE_2D );
+ qglBegin( GL_TRIANGLES );
+ qglEnable( GL_BLEND );
+
+ qglColor4f( 0.25, 0.5, 1, 0.35 );
+
+ for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
+ terravert_t a0;
+ terravert_t a1;
+ terravert_t a2;
+
+ qglColor4f( 0.25, 0.5, 1, g_qeglobals.d_terrapoints[ i ]->scale * 0.75 + 0.25 );
+ Terrain_GetTriangle( pm, g_qeglobals.d_terrapoints[ i ]->tri.index * 2, &a0, &a1, &a2 );
+
+ qglVertex3fv( a0.xyz );
+ qglVertex3fv( a1.xyz );
+ qglVertex3fv( a2.xyz );
+
+ Terrain_GetTriangle( pm, g_qeglobals.d_terrapoints[ i ]->tri.index * 2 + 1, &a0, &a1, &a2 );
+
+ qglVertex3fv( a0.xyz );
+ qglVertex3fv( a1.xyz );
+ qglVertex3fv( a2.xyz );
+ }
+ qglEnd();
+
+ qglDisable( GL_BLEND );
+ qglEnable( GL_TEXTURE_2D );
+ }
+ }
+}
+
+void Terrain_DrawCam( terrainMesh_t *pm ) {
+ qglColor3f( 1,1,1 );
+ qglPushAttrib( GL_ALL_ATTRIB_BITS );
+
+ if ( g_bPatchWireFrame ) {
+ if( pm->bSelected ) {
+ qglLineWidth( 2 );
+ } else {
+ qglLineWidth( 1 );
+ }
+
+ qglDisable( GL_CULL_FACE );
+ qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ qglDisable( GL_TEXTURE_2D );
+
+ if ( g_PrefsDlg.m_bGLLighting ) {
+ qglDisable( GL_LIGHTING );
+ }
+
+ DrawTerrain( pm, pm->bSelected, true );
+
+ if ( g_PrefsDlg.m_bGLLighting ) {
+ qglEnable( GL_LIGHTING );
+ }
+
+ qglEnable( GL_CULL_FACE );
+ qglLineWidth( 1 );
+ } else {
+ qglEnable( GL_CULL_FACE );
+ qglCullFace( GL_FRONT );
+
+ // draw the textured polys
+ DrawTerrain( pm, pm->bSelected, true );
+
+ // if selected, draw the red tint on the polys
+ if( pm->bSelected ) { // && ( g_qeglobals.d_savedinfo.include & INCLUDE_CAMERATINT ) ) {
+ qglColor4f( 1.0, 0.0, 0.0, 0.3 );
+ qglEnable( GL_BLEND );
+ qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+ qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ DrawTerrain( pm, pm->bSelected );
+
+ qglColor3f( 1, 1, 1 );
+ }
+
+ // draw the backside poly outlines
+ qglCullFace( GL_BACK );
+ qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+ qglDisable( GL_BLEND );
+ DrawTerrain( pm, pm->bSelected, true );
+ }
+
+ qglPopAttrib();
+}
+
+void Terrain_DrawXY( terrainMesh_t *pm, entity_t *owner ) {
+ qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+
+ if ( pm->bSelected ) {
+ qglColor3fv( g_qeglobals.d_savedinfo.colors[ COLOR_SELBRUSHES ] );
+ } else if ( owner != world_entity && _stricmp( owner->eclass->name, "func_group" ) ) {
+ qglColor3fv( owner->eclass->color );
+ } else {
+ //FIXME
+ qglColor3fv( g_qeglobals.d_savedinfo.colors[ COLOR_BRUSHES ] );
+ }
+
+ qglLineWidth( 1 );
+
+ DrawTerrain( pm, pm->bSelected );
+
+ qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+}
+
+bool OnlyTerrainSelected( void ) {
+ brush_t *pb;
+
+ //if ( numselfaces || selected_brushes.next == &selected_brushes )
+ if ( selected_brushes.next == &selected_brushes ) {
+ return false;
+ }
+
+ for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
+ if ( !pb->terrainBrush ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool AnyTerrainSelected( void ) {
+ brush_t *pb;
+
+ //if ( numselfaces || selected_brushes.next == &selected_brushes )
+ if ( selected_brushes.next == &selected_brushes ) {
+ return false;
+ }
+
+ for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+terrainMesh_t *SingleTerrainSelected( void ) {
+ if ( selected_brushes.next->terrainBrush ) {
+ return selected_brushes.next->pTerrain;
+ }
+
+ return NULL;
+}
+
+void Terrain_Edit( void ) {
+ //brush_t *pb;
+ //terrainMesh_t *p;
+ //int i;
+ //int j;
+
+// g_qeglobals.d_numpoints = 0;
+ g_qeglobals.d_numterrapoints = 0;
+#if 0
+ for( pb = selected_brushes.next; pb != &selected_brushes ; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ p = pb->pTerrain;
+
+ if ( ( g_qeglobals.d_numpoints + p->width * p->height ) > MAX_POINTS ) {
+ Warning( "Too many points on terrain\n" );
+ continue;
+ }
+ for( i = 0; i < p->width; i++ ) {
+ for( j = 0; j < p->height; j++ ) {
+ Terrain_CalcVertPos( p, i, j, g_qeglobals.d_points[ g_qeglobals.d_numpoints ] );
+ g_qeglobals.d_numpoints++;
+ }
+ }
+ }
+ }
+#endif
+
+ g_qeglobals.d_select_mode = sel_terrainpoint;
+}
+
+void Terrain_SelectPointByRay( vec3_t org, vec3_t dir, int buttons ) {
+ float bestd;
+ terrainFace_t *face;
+ terrainFace_t *bestface;
+ brush_t *pb;
+ float dist;
+ vec3_t vec;
+
+ // find the point closest to the ray
+ bestface = NULL;
+ bestd = WORLD_SIZE * 4;
+ for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ face = Terrain_Ray( org, dir, pb, &dist );
+ if ( face && ( dist < bestd ) ) {
+ bestface = face;
+ bestd = dist;
+ }
+ }
+ }
+
+ for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ face = Terrain_Ray( org, dir, pb, &dist );
+ if ( face && ( dist < bestd ) ) {
+ bestface = face;
+ bestd = dist;
+ }
+ }
+ }
+
+ if ( !bestface ) {
+ return;
+ }
+
+ VectorMA( org, bestd, dir, vec );
+ Terrain_AddMovePoint( vec, buttons & MK_CONTROL, buttons & MK_SHIFT, buttons );
+}
+
+void Terrain_AddMovePoint( vec3_t v, bool bMulti, bool bFull, int buttons ) {
+ brush_t *pb;
+ terrainMesh_t *p;
+ terrainVert_t *vert;
+ int x;
+ int y;
+ int x1, y1;
+ float dx, dy;
+ float dist;
+ float pd;
+
+ if ( !g_bSameView && !bMulti && !bFull ) {
+ g_bSameView = true;
+ return;
+ }
+
+ g_qeglobals.d_numterrapoints = 0;
+ for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
+ //for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ p = pb->pTerrain;
+
+ x = ( v[ 0 ] - p->origin[ 0 ] ) / p->scale_x;
+ y = ( v[ 1 ] - p->origin[ 1 ] ) / p->scale_x;
+ if ( ( x < 0 ) || ( x >= p->width ) || ( y < 0 ) || ( y >= p->height ) ) {
+ continue;
+ }
+
+ vert = p->heightmap;
+ for( y1 = 0; y1 < p->height; y1++ ) {
+ for( x1 = 0; x1 < p->width; x1++, vert++ ) {
+
+ if ( g_qeglobals.d_terrainBrush == TERRAIN_BRUSH_CIRCLE ) {
+ dx = x1 - x;
+ dy = y1 - y;
+ dist = sqrt( dx * dx + dy * dy );
+ } else {
+ dx = abs( x1 - x );
+ dy = abs( y1 - y );
+ if ( dx > dy ) {
+ dist = dx;
+ } else {
+ dist = dy;
+ }
+ }
+
+ pd = dist * 2.0f / g_qeglobals.d_terrainBrushSize;
+ if ( fabs( pd ) <= 1.0f ) {
+ Terrain_AddPoint( p, vert );
+
+ if ( ( buttons & MK_LBUTTON ) && ( g_qeglobals.d_select_mode == sel_terraintexture ) ) {
+ vert->tri.texture = Texture_ForName( g_qeglobals.d_texturewin.texdef.name );
+ vert->tri.texdef.SetName( vert->tri.texture->name );
+ Terrain_AddTexture( p, vert->tri.texture );
+ continue;
+ }
+
+ if ( g_qeglobals.d_terrainFalloff == TERRAIN_FALLOFF_CURVED ) {
+ if ( g_qeglobals.d_terrainBrush == TERRAIN_BRUSH_CIRCLE ) {
+ vert->scale = ( 0.5f + cos( pd * M_PI ) * 0.5f );
+ } else {
+ vert->scale = ( 0.5f + cos( dx/ g_qeglobals.d_terrainBrushSize * M_PI ) * 0.5f ) * ( 0.5f + cos( dy/ g_qeglobals.d_terrainBrushSize * M_PI ) * 0.5f ) - 0.25;
+ }
+ } else {
+ vert->scale = 1.0f - pd;
+ }
+
+ switch( g_qeglobals.d_terrainNoiseType ) {
+ case NOISE_PLUS :
+ vert->scale *= crandom();
+ break;
+
+ case NOISE_PLUSMINUS :
+ vert->scale *= random();
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void Terrain_UpdateSelected( vec3_t vMove ) {
+ int i;
+ brush_t *pb;
+ terrainMesh_t *p;
+ vec3_t vMin;
+ vec3_t vMax;
+
+ if ( g_qeglobals.d_select_mode == sel_terrainpoint ) {
+ for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
+ g_qeglobals.d_terrapoints[ i ]->height += vMove[ 2 ] * g_qeglobals.d_terrapoints[ i ]->scale;
+ }
+ }
+
+ for( pb = active_brushes .next; pb != &active_brushes; pb = pb->next ) {
+// for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ p = pb->pTerrain;
+
+ Terrain_CalcBounds( p, vMin, vMax );
+ Terrain_CalcNormals( p );
+ Brush_RebuildBrush( p->pSymbiot, vMin, vMax );
+ }
+ }
+}
+
+int Terrain_PointInMoveList( terrainVert_t *pf ) {
+ int i;
+
+ for( i = 0; i < g_qeglobals.d_numterrapoints; i++ ) {
+ if ( pf == g_qeglobals.d_terrapoints[ i ] ) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void Terrain_RemovePointFromMoveList( terrainVert_t *v ) {
+ int n;
+ int i;
+
+ while( ( n = Terrain_PointInMoveList( v ) ) >= 0 ) {
+ for( i = n; i < g_qeglobals.d_numterrapoints - 1; i++ ) {
+ g_qeglobals.d_terrapoints[ i ] = g_qeglobals.d_terrapoints[ i + 1 ];
+ }
+
+ g_qeglobals.d_numterrapoints--;
+ }
+}
+
+void Terrain_AddPoint( terrainMesh_t *p, terrainVert_t *v ) {
+ if ( g_qeglobals.d_numterrapoints < MAX_TERRA_POINTS ) {
+ g_qeglobals.d_terrapoints[ g_qeglobals.d_numterrapoints++ ] = v;
+ }
+}
+
+void Terrain_SelectAreaPoints( void ) {
+ brush_t *pb;
+ terrainMesh_t *p;
+ int x;
+ int y;
+ vec3_t vec;
+
+ g_qeglobals.d_numterrapoints = 0;
+ g_nPatchClickedView = -1;
+
+ for( pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next ) {
+ if ( pb->terrainBrush ) {
+ p = pb->pTerrain;
+ for( x = 0; x < p->width; x++ ) {
+ for( y = 0; y < p->height; y++ ) {
+ Terrain_CalcVertPos( p, x, y, vec );
+ if ( within( vec, g_qeglobals.d_vAreaTL, g_qeglobals.d_vAreaBR ) ) {
+ if ( g_qeglobals.d_numterrapoints < MAX_TERRA_POINTS ) {
+ g_qeglobals.d_terrapoints[ g_qeglobals.d_numterrapoints++ ] = &p->heightmap[ x + y * p->width ];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+#define EPSILON 0.0001
+
+bool RayTriangleIntersect( vec3_t orig, vec3_t dir, vec3_t vert1, vec3_t vert2, vec3_t vert3, float *t ) {
+ float u;
+ float v;
+ vec3_t edge1;
+ vec3_t edge2;
+ vec3_t tvec;
+ vec3_t pvec;
+ vec3_t qvec;
+ float det;
+
+ VectorSubtract( vert2, vert1, edge1 );
+ VectorSubtract( vert3, vert1, edge2 );
+
+ // begin calculating determinant - also used to calculate U parameter
+ CrossProduct( dir, edge2, pvec );
+
+ // if determinant is near zero, ray lies in plane of triangle
+ det = DotProduct( edge1, pvec );
+ if ( det < EPSILON ) {
+ return false;
+ }
+
+ // calculate distance from vert1 to ray origin
+ VectorSubtract( orig, vert1, tvec );
+
+ // calculate U parameter and test bounds
+ u = DotProduct( tvec, pvec );
+ if ( ( u < 0.0f ) || ( u > det ) ) {
+ return false;
+ }
+
+ // prepare to test V parameter
+ CrossProduct( tvec, edge1, qvec );
+
+ // calculate V parameter and test bounds
+ v = DotProduct( dir, qvec );
+ if ( ( v < 0.0f ) || ( u + v > det ) ) {
+ return false;
+ }
+
+ // calculate t, scale parameters, ray intersects triangle
+ *t = DotProduct( edge2, qvec ) / det;
+
+ return true;
+}
+
+/*
+==============
+Terrain_Ray
+
+Itersects a ray with a terrain
+Returns the face hit and the distance along the ray the intersection occured at
+Returns NULL and 0 if not hit at all
+==============
+*/
+terrainFace_t *Terrain_Ray( vec3_t origin, vec3_t dir, brush_t *b, float *dist ) {
+ terrainMesh_t *pm;
+ int h;
+ int w;
+ int x;
+ int y;
+ float best_t;
+ float t;
+ terravert_t a0;
+ terravert_t a1;
+ terravert_t a2;
+ terravert_t b0;
+ terravert_t b1;
+ terravert_t b2;
+ terrainVert_t *vert;
+ terrainFace_t *best;
+
+ best = NULL;
+ best_t = WORLD_SIZE * 2;
+
+ pm = b->pTerrain;
+ h = pm->height - 1;
+ w = pm->width - 1;
+
+ vert = pm->heightmap;
+ for( y = 0; y < h; y++, vert++ ) {
+ for( x = 0; x < w; x++, vert++ ) {
+ Terrain_GetTriangles( pm, x, y, &a0, &a1, &a2, &b0, &b1, &b2, NULL );
+
+ t = WORLD_SIZE * 2;
+ if ( RayTriangleIntersect( origin, dir, a2.xyz, a1.xyz, a0.xyz, &t ) ) {
+ if ( ( t >= 0 ) && ( t < best_t ) ) {
+ best = &vert->tri;
+ best_t = t;
+ }
+ }
+
+ t = WORLD_SIZE * 2;
+ if ( RayTriangleIntersect( origin, dir, b2.xyz, b1.xyz, b0.xyz, &t ) ) {
+ if ( ( t >= 0 ) && ( t < best_t ) ) {
+ best = &vert->tri;
+ best_t = t;
+ }
+ }
+ }
+ }
+
+ if ( !best ) {
+ *dist = 0;
+ return NULL;
+ }
+
+ *dist = best_t;
+
+ return best;
+}
+
+/*
+============
+Select_TerrainFace
+
+Select the face
+============
+*/
+void Select_TerrainFace ( brush_t * brush, terrainFace_t *terraface ) {
+#if 0
+ UnSelect_Brush( brush );
+
+ if( numselfaces < MAX_SEL_FACES ) {
+ selfaces[numselfaces].face = NULL;
+ selfaces[numselfaces].brush = brush;
+ selfaces[numselfaces].terraface = terraface;
+ numselfaces++;
+ }
+#endif
+}
+
+void Select_TerrainFacesFromBrush( brush_t *brush ) {
+ terrainMesh_t *pm;
+ int h;
+ int w;
+ int x;
+ int y;
+
+ pm = brush->pTerrain;
+ h = pm->height - 1;
+ w = pm->width - 1;
+
+ for( y = 0; y < h; y++ ) {
+ for( x = 0; x < w; x++ ) {
+ Select_TerrainFace( brush, &brush->pTerrain->heightmap[ x + y * pm->width ].tri );
+ }
+ }
+}
+
+void SetTerrainTexdef( brush_t *brush, terrainFace_t *face, texdef_t *texdef ) {
+ int oldFlags;
+ int oldContents;
+
+ oldFlags = face->texdef.flags;
+ oldContents = face->texdef.contents;
+
+ face->texdef = *texdef;
+
+ face->texdef.flags = ( face->texdef.flags & ~SURF_KEEP ) | ( oldFlags & SURF_KEEP );
+ face->texdef.contents = ( face->texdef.contents & ~CONTENTS_KEEP ) | ( oldContents & CONTENTS_KEEP );
+
+ face->texture = Texture_ForName( texdef->name );
+
+ //Terrain_AddTexture( face->texture );
+}
+
+void RotateTerrainFaceTexture( terrainFace_t *vert, int nAxis, float fDeg ) {
+}
+
+void TerrainFace_FitTexture( terrainFace_t *vert ) {
+}
+
+void Terrain_Init( void ) {
+ g_qeglobals.d_terrainWidth = 64;
+ g_qeglobals.d_terrainHeight = 64;
+ g_qeglobals.d_terrainBrushSize = 12;
+ g_qeglobals.d_terrainNoiseType = NOISE_NONE;
+ //g_qeglobals.d_terrainFalloff = TERRAIN_FALLOFF_LINEAR;
+ g_qeglobals.d_terrainFalloff = TERRAIN_FALLOFF_CURVED;
+ g_qeglobals.d_terrainBrush = TERRAIN_BRUSH_CIRCLE;
+ //g_qeglobals.d_terrainBrush = TERRAIN_BRUSH_SQUARE;
+}
diff --git a/q3radiant/terrain.h b/q3radiant/terrain.h
new file mode 100755
index 0000000..3d2298e
--- /dev/null
+++ b/q3radiant/terrain.h
@@ -0,0 +1,75 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+#ifndef __TERRAIN_H__
+#define __TERRAIN_H__
+
+void Terrain_SetEpair( terrainMesh_t *p, const char *pKey, const char *pValue );
+const char* Terrain_GetKeyValue( terrainMesh_t *p, const char *pKey );
+int Terrain_MemorySize( terrainMesh_t *p );
+void Terrain_Delete( terrainMesh_t *p );
+terrainMesh_t *MakeNewTerrain( int width, int height, qtexture_t *texture = NULL );
+brush_t *AddBrushForTerrain( terrainMesh_t *pm, bool bLinkToWorld = true );
+terrainMesh_t *Terrain_Duplicate( terrainMesh_t *pFrom );
+void Terrain_BrushToMesh( void );
+brush_t *Terrain_Parse( void );
+void Terrain_Write( terrainMesh_t *p, CMemFile *file );
+void Terrain_Write( terrainMesh_t *p, FILE *file );
+void Terrain_Select( terrainMesh_t *p );
+void Terrain_Deselect( terrainMesh_t *p );
+void Terrain_Move( terrainMesh_t *pm, const vec3_t vMove, bool bRebuild = false );
+void UpdateTerrainInspector( void );
+void Terrain_CalcBounds( terrainMesh_t *p, vec3_t &vMin, vec3_t &vMax );
+void CalcTriNormal( const vec3_t a, const vec3_t b, const vec3_t c, vec3_t o );
+void Terrain_CalcVertPos( terrainMesh_t *p, int x, int y, vec3_t vert );
+void Terrain_CalcNormals( terrainMesh_t *p );
+void Terrain_FindReplaceTexture( terrainMesh_t *p, const char *pFind, const char *pReplace, bool bForce );
+bool Terrain_HasTexture( terrainMesh_t *p, const char *name );
+void Terrain_ReplaceQTexture( terrainMesh_t *p, qtexture_t *pOld, qtexture_t *pNew );
+void Terrain_SetTexture( terrainMesh_t *p, texdef_t *tex_def );
+void Terrain_Scale( terrainMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuild = true );
+bool Terrain_DragScale( terrainMesh_t *p, vec3_t vAmt, vec3_t vMove );
+void Terrain_ApplyMatrix( terrainMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[ 3 ], bool bSnap );
+void Terrain_DrawFace( brush_t *brush, terrainFace_t *terraface );
+void DrawTerrain( terrainMesh_t *pm, bool bPoints, bool bShade = false );
+void Terrain_DrawCam( terrainMesh_t *pm );
+void Terrain_DrawXY( terrainMesh_t *pm, entity_t *owner );
+bool OnlyTerrainSelected( void );
+bool AnyTerrainSelected( void );
+terrainMesh_t *SingleTerrainSelected( void );
+void Terrain_Edit( void );
+void Terrain_SelectPointByRay ( vec3_t org, vec3_t dir, int buttons );
+void Terrain_AddMovePoint( vec3_t v, bool bMulti, bool bFull, int buttons );
+void Terrain_UpdateSelected( vec3_t vMove );
+int Terrain_PointInMoveList( terrainVert_t *pf );
+void Terrain_AddPoint( terrainMesh_t *p, terrainVert_t *v );
+void Terrain_RemovePointFromMoveList( terrainVert_t *v );
+void Terrain_SelectAreaPoints( void );
+bool RayTriangleIntersect( vec3_t orig, vec3_t dir, vec3_t vert1, vec3_t vert2, vec3_t vert3, float *t );
+terrainFace_t *Terrain_Ray( vec3_t origin, vec3_t dir, brush_t *b, float *dist );
+void Select_TerrainFacesFromBrush( brush_t *brush );
+void SetTerrainTexdef( brush_t *brush, terrainFace_t *vert, texdef_t *texdef );
+void RotateTerrainFaceTexture( terrainFace_t *vert, int nAxis, float fDeg );
+void TerrainFace_FitTexture( terrainFace_t *vert );
+void Select_TerrainFace( brush_t * brush, terrainFace_t *terraface );
+void Terrain_Init( void );
+
+#endif