2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
35 #include "DialogInfo.h"
37 #include "../../renderer/tr_local.h"
38 #include "../../renderer/model_local.h" // for idRenderModelLiquid
43 static char THIS_FILE[] = __FILE__;
46 const char *g_pDimStrings[] = { "x:%.f", "y:%.f", "z:%.f" };
47 const char *g_pOrgStrings[] = { "(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)" };
51 bool g_bCrossHairs = false;
56 bool g_bRogueClipMode;
61 CClipPoint *g_pMovingClip;
62 brush_t g_brFrontSplits;
63 brush_t g_brBackSplits;
65 brush_t g_brClipboard;
67 entity_t g_enClipboard;
69 idVec3 g_vRotateOrigin;
73 CClipPoint g_PathPoints[256];
74 CClipPoint *g_pMovingPath;
81 CClipPoint g_PointPoints[512];
82 CClipPoint *g_pMovingPoint;
86 const int XY_LEFT = 0x01;
87 const int XY_RIGHT = 0x02;
88 const int XY_UP = 0x04;
89 const int XY_DOWN = 0x08;
91 PFNPathCallback *g_pPathFunc = NULL;
92 void Select_Ungroup();
95 =======================================================================================================================
96 =======================================================================================================================
98 void AcquirePath(int nCount, PFNPathCallback *pFunc) {
100 g_nPathLimit = nCount;
105 CPtrArray g_ptrMenus;
107 CMemFile g_Clipboard(4096);
108 CMemFile g_PatchClipboard(4096);
114 =======================================================================================================================
115 =======================================================================================================================
117 float fDiff(float f1, float f2) {
126 #define MAX_DRAG_POINTS 128
128 CPtrArray dragPoints;
129 static CDragPoint *activeDrag = NULL;
130 static bool activeDragging = false;
133 =======================================================================================================================
134 =======================================================================================================================
136 bool CDragPoint::PointWithin(idVec3 p, int nView) {
138 if (fDiff(p[0], vec[0]) <= 3 && fDiff(p[1], vec[1]) <= 3 && fDiff(p[2], vec[2]) <= 3) {
143 int nDim1 = (nView == YZ) ? 1 : 0;
144 int nDim2 = (nView == XY) ? 1 : 2;
145 if (fDiff(p[nDim1], vec[nDim1]) <= 3 && fDiff(p[nDim2], vec[nDim2]) <= 3) {
154 =======================================================================================================================
155 =======================================================================================================================
157 CDragPoint *PointRay(const idVec3 &org, const idVec3 &dir, float *dist) {
161 CDragPoint *drag = NULL;
162 CDragPoint *priority = NULL;
164 // find the point closest to the ray
165 float scale = g_pParentWnd->ActiveXY()->Scale();
167 bestd = 12 / scale / 2;
169 int count = dragPoints.GetSize();
170 for (i = 0; i < count; i++) {
171 drag = reinterpret_cast < CDragPoint * > (dragPoints[i]);
172 temp = drag->vec - org;
174 temp = org + d * dir;
175 temp = drag->vec - temp;
180 if (priority == NULL) {
181 priority = reinterpret_cast < CDragPoint * > (dragPoints[besti]);
182 if (!priority->priority) {
193 drag = reinterpret_cast < CDragPoint * > (dragPoints[besti]);
194 if (priority && !drag->priority) {
202 =======================================================================================================================
203 =======================================================================================================================
205 void ClearSelectablePoints(brush_t *b) {
207 dragPoints.RemoveAll();
211 ptr.Copy(dragPoints);
212 dragPoints.RemoveAll();
214 int count = ptr.GetSize();
215 for (int i = 0; i < count; i++) {
216 if (b == reinterpret_cast < CDragPoint * > ( ptr.GetAt(i))->pBrush ) {
220 dragPoints.Add(ptr.GetAt(i));
227 =======================================================================================================================
228 =======================================================================================================================
230 void AddSelectablePoint(brush_t *b, idVec3 v, int type, bool priority) {
231 dragPoints.Add(new CDragPoint(b, v, type, priority));
235 =======================================================================================================================
236 =======================================================================================================================
238 void UpdateSelectablePoint(brush_t *b, idVec3 v, int type) {
239 int count = dragPoints.GetSize();
240 for (int i = 0; i < count; i++) {
241 CDragPoint *drag = reinterpret_cast < CDragPoint * > (dragPoints.GetAt(i));
242 if (b == drag->pBrush && type == drag->nType) {
243 VectorCopy(v, drag->vec);
250 =======================================================================================================================
251 =======================================================================================================================
253 void VectorToAngles(idVec3 vec, idVec3 angles) {
257 if ((vec[0] == 0) && (vec[1] == 0)) {
267 yaw = RAD2DEG( atan2(vec[1], vec[0]) );
272 forward = (float)idMath::Sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
273 pitch = RAD2DEG( atan2(vec[2], forward) );
285 =======================================================================================================================
286 RotateLight target is relative to the light origin up and right are relative to the target up and right are
287 perpendicular and are on a plane through the target with the target vector as normal delta is the movement of the
288 target relative to the light
289 =======================================================================================================================
291 void VectorSnapGrid(idVec3 &v) {
292 v.x = floor(v.x / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
293 v.y = floor(v.y / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
294 v.z = floor(v.z / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
298 =======================================================================================================================
299 =======================================================================================================================
301 static void RotateLight(idVec3 &target, idVec3 &up, idVec3 &right, const idVec3 &delta) {
302 idVec3 newtarget, cross, dst;
304 double angle, dist, d, len;
307 // calculate new target
308 newtarget = target + delta;
310 // get the up and right vector relative to the light origin
314 len = target.Length() * newtarget.Length();
317 // calculate the rotation angle between the vectors
318 double dp = target * newtarget;
319 double dv = dp / len;
321 angle = RAD2DEG( idMath::ACos( dv ) );
323 // get a vector orthogonal to the rotation plane
324 cross = target.Cross( newtarget );
327 if (cross[0] || cross[1] || cross[2]) {
328 // build the rotation matrix
329 rot = idRotation( vec3_origin, cross, angle ).ToMat3();
331 rot.ProjectVector(target, dst);
333 rot.ProjectVector( up, dst );
335 rot.ProjectVector( right, dst);
341 // project the up and right vectors onto a plane that goes through the target and
342 // has normal vector target.Normalize()
346 dist = normal * target;
348 d = (normal * up) - dist;
351 d = (normal * right) - dist;
355 // FIXME: maybe calculate the right vector with a cross product between the target
356 // and up vector, just to make sure the up and right vectors are perpendicular
357 // get the up and right vectors relative to the target
362 // move the target in the (target - light_origin) direction
364 VectorSnapGrid(target);
366 VectorSnapGrid(right);
370 =======================================================================================================================
371 =======================================================================================================================
373 extern idVec3 Brush_TransformedPoint(brush_t *b, const idVec3 &in);
374 extern idMat3 Brush_RotationMatrix(brush_t *b);
375 bool UpdateActiveDragPoint(const idVec3 &move) {
377 idMat3 mat = Brush_RotationMatrix(activeDrag->pBrush);
378 idMat3 invmat = mat.Transpose();
379 idVec3 target, up, right, start, end;
381 if (activeDrag->nType == LIGHT_TARGET) {
382 GetVectorForKey(activeDrag->pBrush->owner, "light_target", target);
383 GetVectorForKey(activeDrag->pBrush->owner, "light_up", up);
384 GetVectorForKey(activeDrag->pBrush->owner, "light_right", right);
388 RotateLight(target, up, right, move);
392 SetKeyVec3(activeDrag->pBrush->owner, "light_target", target);
393 SetKeyVec3(activeDrag->pBrush->owner, "light_up", up);
394 SetKeyVec3(activeDrag->pBrush->owner, "light_right", right);
395 target += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
396 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush, target), LIGHT_TARGET);
398 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,up), LIGHT_UP);
400 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,right), LIGHT_RIGHT);
402 else if (activeDrag->nType == LIGHT_UP) {
403 GetVectorForKey(activeDrag->pBrush->owner, "light_up", up);
407 SetKeyVec3(activeDrag->pBrush->owner, "light_up", up);
408 GetVectorForKey(activeDrag->pBrush->owner, "light_target", target);
409 target += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
411 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,up), LIGHT_UP);
413 else if (activeDrag->nType == LIGHT_RIGHT) {
414 GetVectorForKey(activeDrag->pBrush->owner, "light_right", right);
418 SetKeyVec3(activeDrag->pBrush->owner, "light_right", right);
419 GetVectorForKey(activeDrag->pBrush->owner, "light_target", target);
420 target += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
422 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,right), LIGHT_RIGHT);
424 else if (activeDrag->nType == LIGHT_START) {
425 GetVectorForKey(activeDrag->pBrush->owner, "light_start", start);
429 SetKeyVec3(activeDrag->pBrush->owner, "light_start", start);
430 start += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
431 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,start), LIGHT_START);
433 else if (activeDrag->nType == LIGHT_END) {
434 GetVectorForKey(activeDrag->pBrush->owner, "light_end", end);
438 SetKeyVec3(activeDrag->pBrush->owner, "light_end", end);
439 end += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
440 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,end), LIGHT_END);
442 else if (activeDrag->nType == LIGHT_CENTER) {
443 GetVectorForKey(activeDrag->pBrush->owner, "light_center", end);
447 SetKeyVec3(activeDrag->pBrush->owner, "light_center", end);
448 end += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
449 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush, end), LIGHT_CENTER);
452 // FIXME: just build the frustrum values
453 Brush_Build(activeDrag->pBrush);
461 =======================================================================================================================
462 =======================================================================================================================
464 bool SetDragPointCursor(idVec3 p, int nView) {
467 int numDragPoints = dragPoints.GetSize();
468 for (int i = 0; i < numDragPoints; i++) {
469 if (reinterpret_cast < CDragPoint * > (dragPoints[i])->PointWithin(p, nView)) {
470 activeDrag = reinterpret_cast < CDragPoint * > (dragPoints[i]);
479 =======================================================================================================================
480 =======================================================================================================================
482 void SetActiveDrag(CDragPoint *p) {
487 =======================================================================================================================
488 =======================================================================================================================
490 void ClearActiveDrag() {
495 IMPLEMENT_DYNCREATE(CXYWnd, CWnd);
498 =======================================================================================================================
499 =======================================================================================================================
502 g_brClipboard.next = &g_brClipboard;
503 g_brUndo.next = &g_brUndo;
505 g_bRotateMode = false;
507 g_bRogueClipMode = false;
509 g_pMovingClip = NULL;
510 g_pMovingPath = NULL;
511 g_brFrontSplits.next = &g_brFrontSplits;
512 g_brBackSplits.next = &g_brBackSplits;
515 m_bRButtonDown = false;
516 m_nUpdateBits = W_XY;
526 =======================================================================================================================
527 =======================================================================================================================
530 int nSize = g_ptrMenus.GetSize();
532 CMenu *pMenu = reinterpret_cast < CMenu * > (g_ptrMenus.GetAt(nSize - 1));
534 pMenu->DestroyMenu();
539 g_ptrMenus.RemoveAll();
540 m_mnuDrop.DestroyMenu();
543 BEGIN_MESSAGE_MAP(CXYWnd, CWnd)
544 //{{AFX_MSG_MAP(CXYWnd)
557 ON_COMMAND(ID_SELECT_MOUSEROTATE, OnSelectMouserotate)
566 ON_COMMAND(ID_DROP_NEWMODEL, OnDropNewmodel)
568 ON_COMMAND_RANGE(ID_ENTITY_START, ID_ENTITY_END, OnEntityCreate)
570 // CXYWnd message handlers
571 LONG WINAPI XYWndProc(HWND, UINT, WPARAM, LPARAM);
574 =======================================================================================================================
575 =======================================================================================================================
577 BOOL CXYWnd::PreCreateWindow(CREATESTRUCT &cs) {
579 HINSTANCE hInstance = AfxGetInstanceHandle();
580 if (::GetClassInfo(hInstance, XY_WINDOW_CLASS, &wc) == FALSE) {
581 // Register a new class
582 memset(&wc, 0, sizeof(wc));
583 wc.style = CS_NOCLOSE;
584 wc.lpszClassName = XY_WINDOW_CLASS;
585 wc.hCursor = NULL; // LoadCursor (NULL,IDC_ARROW);
586 wc.lpfnWndProc = ::DefWindowProc;
587 if (AfxRegisterClass(&wc) == FALSE) {
588 Error("CCamWnd RegisterClass: failed");
592 cs.lpszClass = XY_WINDOW_CLASS;
593 cs.lpszName = "VIEW";
594 if (cs.style != QE3_CHILDSTYLE) {
595 cs.style = QE3_SPLITTER_STYLE;
598 return CWnd::PreCreateWindow(cs);
604 static unsigned s_stipple[32] = {
640 =======================================================================================================================
642 =======================================================================================================================
644 LONG WINAPI XYWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
650 case WM_NCCALCSIZE: // don't let windows copy pixels
651 DefWindowProc(hWnd, uMsg, wParam, lParam);
656 SendMessage(hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0);
664 return DefWindowProc(hWnd, uMsg, wParam, lParam);
668 =======================================================================================================================
669 =======================================================================================================================
671 static void WXY_InitPixelFormat(PIXELFORMATDESCRIPTOR *pPFD) {
672 memset(pPFD, 0, sizeof(*pPFD));
674 pPFD->nSize = sizeof(PIXELFORMATDESCRIPTOR);
676 pPFD->dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
677 pPFD->iPixelType = PFD_TYPE_RGBA;
678 pPFD->cColorBits = 24;
679 pPFD->cDepthBits = 32;
680 pPFD->iLayerType = PFD_MAIN_PLANE;
684 =======================================================================================================================
685 =======================================================================================================================
687 void WXY_Print(void) {
692 /* initialize the PRINTDLG struct and execute it */
693 memset(&pd, 0, sizeof(pd));
694 pd.lStructSize = sizeof(pd);
695 pd.hwndOwner = g_pParentWnd->GetXYWnd()->GetSafeHwnd();
696 pd.Flags = PD_RETURNDC;
698 if (!PrintDlg(&pd) || !pd.hDC) {
699 g_pParentWnd->MessageBox("Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR);
704 memset(&di, 0, sizeof(di));
705 di.cbSize = sizeof(di);
706 di.lpszDocName = "QE4";
707 if (StartDoc(pd.hDC, &di) <= 0) {
708 g_pParentWnd->MessageBox("Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR);
713 if (StartPage(pd.hDC) <= 0) {
714 g_pParentWnd->MessageBox("Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR);
716 } { /* read pixels from the XY window */
717 int bmwidth = 320, bmheight = 320;
722 GetWindowRect(g_pParentWnd->GetXYWnd()->GetSafeHwnd(), &r);
724 bmwidth = r.right - r.left;
725 bmheight = r.bottom - r.top;
727 pwidth = GetDeviceCaps(pd.hDC, PHYSICALWIDTH) - GetDeviceCaps(pd.hDC, PHYSICALOFFSETX);
728 pheight = GetDeviceCaps(pd.hDC, PHYSICALHEIGHT) - GetDeviceCaps(pd.hDC, PHYSICALOFFSETY);
730 StretchBlt(pd.hDC, 0, 0, pwidth, pheight, s_hdcXY, 0, 0, bmwidth, bmheight, SRCCOPY);
733 /* EndPage and EndDoc */
734 if (EndPage(pd.hDC) <= 0) {
735 g_pParentWnd->MessageBox("QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR);
739 if (EndDoc(pd.hDC) <= 0) {
740 g_pParentWnd->MessageBox("QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR);
746 =======================================================================================================================
747 =======================================================================================================================
749 int CXYWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
750 if (CWnd::OnCreate(lpCreateStruct) == -1) {
754 s_hdcXY = ::GetDC(GetSafeHwnd());
755 QEW_SetupPixelFormat(s_hdcXY, false);
757 qglPolygonStipple((unsigned char *)s_stipple);
758 qglLineStipple(3, 0xaaaa);
763 =======================================================================================================================
764 =======================================================================================================================
766 float ptSum(idVec3 pt) {
767 return pt[0] + pt[1] + pt[2];
771 =======================================================================================================================
772 =======================================================================================================================
774 void CXYWnd::DropClipPoint(UINT nFlags, CPoint point) {
779 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, *g_pMovingClip);
783 if (g_Clip1.Set() == false) {
786 g_Clip1.m_ptScreen = point;
788 else if (g_Clip2.Set() == false) {
791 g_Clip2.m_ptScreen = point;
793 else if (g_Clip3.Set() == false) {
796 g_Clip3.m_ptScreen = point;
799 RetainClipMode(true);
802 g_Clip1.m_ptScreen = point;
805 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, *pPt);
807 // Put the off-viewaxis coordinate at the top or bottom of selected brushes
808 if ( GetAsyncKeyState(VK_CONTROL) & 0x8000 ) {
809 if ( selected_brushes.next != &selected_brushes ) {
811 Select_GetBounds( smins, smaxs );
813 if ( m_nViewType == XY ) {
814 if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
819 } else if ( m_nViewType == YZ ) {
820 if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
826 if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
836 Sys_UpdateWindows(XY | W_CAMERA_IFON);
840 =======================================================================================================================
841 =======================================================================================================================
843 void CXYWnd::DropPathPoint(UINT nFlags, CPoint point) {
848 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, *g_pMovingPath);
851 g_PathPoints[g_nPathCount].Set(true);
852 g_PathPoints[g_nPathCount].m_ptScreen = point;
853 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, g_PathPoints[g_nPathCount]);
855 if (g_nPathCount == g_nPathLimit) {
857 g_pPathFunc(true, g_nPathCount);
866 Sys_UpdateWindows(XY | W_CAMERA_IFON);
870 =======================================================================================================================
871 =======================================================================================================================
873 void CXYWnd::AddPointPoint(UINT nFlags, idVec3 *pVec) {
874 g_PointPoints[g_nPointCount].Set(true);
876 // g_PointPoints[g_nPointCount].m_ptScreen = point;
877 g_PointPoints[g_nPointCount].m_ptClip = *pVec;
878 g_PointPoints[g_nPointCount].SetPointPtr(pVec);
880 Sys_UpdateWindows(XY | W_CAMERA_IFON);
884 =======================================================================================================================
885 =======================================================================================================================
887 void CXYWnd::OnLButtonDown(UINT nFlags, CPoint point) {
888 g_pParentWnd->SetActiveXY(this);
891 if (g_pParentWnd->GetNurbMode()) {
892 int i, num = g_pParentWnd->GetNurb()->GetNumValues();
894 for (i = 0; i < num; i++) {
895 temp.Append(g_pParentWnd->GetNurb()->GetValue(i));
900 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, v3);
901 temp.Append(idVec2(v3.x, v3.y));
903 g_pParentWnd->GetNurb()->Clear();
904 for (i = 0; i < num; i++) {
905 g_pParentWnd->GetNurb()->AddValue((1000 * i)/num, temp[i]);
908 if (ClipMode() && !RogueClipMode()) {
909 DropClipPoint(nFlags, point);
911 else if (PathMode()) {
912 DropPathPoint(nFlags, point);
915 OriginalButtonDown(nFlags, point);
920 =======================================================================================================================
921 =======================================================================================================================
923 void CXYWnd::OnMButtonDown(UINT nFlags, CPoint point) {
924 OriginalButtonDown(nFlags, point);
928 =======================================================================================================================
929 =======================================================================================================================
931 float Betwixt(float f1, float f2) {
933 return f2 + ((f1 - f2) / 2);
936 return f1 + ((f2 - f1) / 2);
941 =======================================================================================================================
942 =======================================================================================================================
944 void CXYWnd::ProduceSplits(brush_t **pFront, brush_t **pBack) {
948 if (g_Clip1.Set() && g_Clip2.Set()) {
950 VectorCopy(g_Clip1.m_ptClip, face.planepts[0]);
951 VectorCopy(g_Clip2.m_ptClip, face.planepts[1]);
952 VectorCopy(g_Clip3.m_ptClip, face.planepts[2]);
953 if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes)) {
954 if (g_Clip3.Set() == false) {
955 if (m_nViewType == XY) {
956 face.planepts[0][2] = selected_brushes.next->mins[2];
957 face.planepts[1][2] = selected_brushes.next->mins[2];
958 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
959 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
960 face.planepts[2][2] = selected_brushes.next->maxs[2];
962 else if (m_nViewType == YZ) {
963 face.planepts[0][0] = selected_brushes.next->mins[0];
964 face.planepts[1][0] = selected_brushes.next->mins[0];
965 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
966 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
967 face.planepts[2][0] = selected_brushes.next->maxs[0];
970 face.planepts[0][1] = selected_brushes.next->mins[1];
971 face.planepts[1][1] = selected_brushes.next->mins[1];
972 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
973 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
974 face.planepts[2][1] = selected_brushes.next->maxs[1];
978 Brush_SplitBrushByFace(selected_brushes.next, &face, pFront, pBack);
985 =======================================================================================================================
986 =======================================================================================================================
988 void CleanList(brush_t *pList) {
989 brush_t *pBrush = pList->next;
990 while (pBrush != NULL && pBrush != pList) {
991 brush_t *pNext = pBrush->next;
998 =======================================================================================================================
999 =======================================================================================================================
1001 void CXYWnd::ProduceSplitLists() {
1002 if (AnyPatchesSelected()) {
1003 Sys_Status("Deslecting patches for clip operation.\n");
1006 for (brush_t * pb = selected_brushes.next; pb != &selected_brushes; pb = next) {
1009 Brush_RemoveFromList(pb);
1010 Brush_AddToList(pb, &active_brushes);
1011 UpdatePatchInspector();
1016 CleanList(&g_brFrontSplits);
1017 CleanList(&g_brBackSplits);
1018 g_brFrontSplits.next = &g_brFrontSplits;
1019 g_brBackSplits.next = &g_brBackSplits;
1022 for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next) {
1023 brush_t *pFront = NULL;
1024 brush_t *pBack = NULL;
1026 if (g_Clip1.Set() && g_Clip2.Set()) {
1028 VectorCopy(g_Clip1.m_ptClip, face.planepts[0]);
1029 VectorCopy(g_Clip2.m_ptClip, face.planepts[1]);
1030 VectorCopy(g_Clip3.m_ptClip, face.planepts[2]);
1031 if (g_Clip3.Set() == false) {
1032 if (g_pParentWnd->ActiveXY()->GetViewType() == XY) {
1033 face.planepts[0][2] = pBrush->mins[2];
1034 face.planepts[1][2] = pBrush->mins[2];
1035 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
1036 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
1037 face.planepts[2][2] = pBrush->maxs[2];
1039 else if (g_pParentWnd->ActiveXY()->GetViewType() == YZ) {
1040 face.planepts[0][0] = pBrush->mins[0];
1041 face.planepts[1][0] = pBrush->mins[0];
1042 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
1043 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
1044 face.planepts[2][0] = pBrush->maxs[0];
1047 face.planepts[0][1] = pBrush->mins[1];
1048 face.planepts[1][1] = pBrush->mins[1];
1049 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
1050 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
1051 face.planepts[2][1] = pBrush->maxs[1];
1055 Brush_SplitBrushByFace(pBrush, &face, &pFront, &pBack);
1057 Brush_AddToList(pBack, &g_brBackSplits);
1061 Brush_AddToList(pFront, &g_brFrontSplits);
1069 =======================================================================================================================
1070 =======================================================================================================================
1072 void Brush_CopyList(brush_t *pFrom, brush_t *pTo) {
1073 brush_t *pBrush = pFrom->next;
1074 while (pBrush != NULL && pBrush != pFrom) {
1075 brush_t *pNext = pBrush->next;
1076 Brush_RemoveFromList(pBrush);
1077 Brush_AddToList(pBrush, pTo);
1083 =======================================================================================================================
1084 =======================================================================================================================
1086 void CXYWnd::OnRButtonDown(UINT nFlags, CPoint point) {
1087 g_pParentWnd->SetActiveXY(this);
1089 m_bRButtonDown = true;
1091 if (g_PrefsDlg.m_nMouseButtons == 3) { // 3 button mouse
1092 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
1093 if (ClipMode()) { // already there?
1094 DropClipPoint(nFlags, point);
1098 g_bRogueClipMode = true;
1099 DropClipPoint(nFlags, point);
1106 OriginalButtonDown(nFlags, point);
1110 =======================================================================================================================
1111 =======================================================================================================================
1113 void CXYWnd::OnLButtonUp(UINT nFlags, CPoint point) {
1116 if (g_pMovingClip) {
1118 g_pMovingClip = NULL;
1122 OriginalButtonUp(nFlags, point);
1126 =======================================================================================================================
1127 =======================================================================================================================
1129 void CXYWnd::OnMButtonUp(UINT nFlags, CPoint point) {
1130 OriginalButtonUp(nFlags, point);
1134 =======================================================================================================================
1135 =======================================================================================================================
1137 void CXYWnd::OnRButtonUp(UINT nFlags, CPoint point) {
1138 m_bRButtonDown = false;
1139 if (point == m_ptDown) { // mouse didn't move
1141 if ((GetAsyncKeyState(VK_MENU) & 0x8000)) {
1145 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
1149 if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
1158 OriginalButtonUp(nFlags, point);
1162 =======================================================================================================================
1163 =======================================================================================================================
1165 void CXYWnd::OriginalButtonDown(UINT nFlags, CPoint point) {
1167 GetClientRect(rctZ);
1168 SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1169 if (g_pParentWnd->GetTopWindow() != this) {
1175 XY_MouseDown(point.x, rctZ.Height() - 1 - point.y, nFlags);
1176 m_nScrollFlags = nFlags;
1180 =======================================================================================================================
1181 =======================================================================================================================
1183 void CXYWnd::OriginalButtonUp(UINT nFlags, CPoint point) {
1185 GetClientRect(rctZ);
1186 XY_MouseUp(point.x, rctZ.Height() - 1 - point.y, nFlags);
1187 if (!(nFlags & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON))) {
1195 =======================================================================================================================
1196 =======================================================================================================================
1198 void CXYWnd::OnMouseMove(UINT nFlags, CPoint point) {
1205 g_PrefsDlg.m_bChaseMouse == TRUE &&
1206 (point.x < 0 || point.y < 0 || point.x > m_nWidth || point.y > m_nHeight) &&
1207 GetCapture() == this
1209 float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
1211 // m_ptDrag = point;
1215 m_ptDragAdj.x = -fAdjustment;
1217 else if (point.x > m_nWidth) {
1218 m_ptDragAdj.x = fAdjustment;
1222 m_ptDragAdj.y = -fAdjustment;
1224 else if (point.y > m_nHeight) {
1225 m_ptDragAdj.y = fAdjustment;
1228 if (m_nTimerID == -1) {
1229 m_nTimerID = SetTimer(100, 50, NULL);
1237 // else if (m_nTimerID != -1)
1238 if (m_nTimerID != -1) {
1239 KillTimer(m_nTimerID);
1240 pressx -= m_ptDragTotal.x;
1241 pressy += m_ptDragTotal.y;
1247 bool bCrossHair = false;
1248 if (!m_bRButtonDown) {
1249 tdp[0] = tdp[1] = tdp[2] = 0.0;
1250 SnapToPoint(point.x, m_nHeight - 1 - point.y, tdp);
1252 g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]);
1253 g_pParentWnd->SetStatusText(1, g_strStatus);
1256 // i need to generalize the point code.. having 3 flavors pretty much sucks.. once
1257 // the new curve stuff looks like it is going to stick i will rationalize this
1258 // down to a single interface..
1261 if (g_pMovingPoint && GetCapture() == this) {
1263 SnapToPoint(point.x, m_nHeight - 1 - point.y, g_pMovingPoint->m_ptClip);
1264 g_pMovingPoint->UpdatePointPtr();
1265 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1268 g_pMovingPoint = NULL;
1270 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1271 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1272 for (int n = 0; n < g_nPointCount; n++) {
1275 fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1276 fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3
1279 g_pMovingPoint = &g_PointPoints[n];
1284 else if (ClipMode()) {
1285 if (g_pMovingClip && GetCapture() == this) {
1287 SnapToPoint(point.x, m_nHeight - 1 - point.y, g_pMovingClip->m_ptClip);
1288 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1291 g_pMovingClip = NULL;
1293 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1294 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1295 if (g_Clip1.Set()) {
1298 fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1299 fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3
1302 g_pMovingClip = &g_Clip1;
1306 if (g_Clip2.Set()) {
1309 fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1310 fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3
1313 g_pMovingClip = &g_Clip2;
1317 if (g_Clip3.Set()) {
1320 fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1321 fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3
1324 g_pMovingClip = &g_Clip3;
1329 if (bCrossHair == false) {
1330 XY_MouseMoved(point.x, m_nHeight - 1 - point.y, nFlags);
1333 else if (PathMode()) {
1334 if (g_pMovingPath && GetCapture() == this) {
1336 SnapToPoint(point.x, m_nHeight - 1 - point.y, g_pMovingPath->m_ptClip);
1337 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1340 g_pMovingPath = NULL;
1342 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1343 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1344 for (int n = 0; n < g_nPathCount; n++) {
1347 fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1348 fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3
1351 g_pMovingPath = &g_PathPoints[n];
1357 bCrossHair = XY_MouseMoved(point.x, m_nHeight - 1 - point.y, nFlags);
1361 bCrossHair = XY_MouseMoved(point.x, m_nHeight - 1 - point.y, nFlags);
1365 SetCursor(::LoadCursor(NULL, IDC_CROSS));
1368 SetCursor(::LoadCursor(NULL, IDC_ARROW));
1371 /// If precision crosshair is active, force redraw of the 2d view on mouse move
1372 if( m_precisionCrosshairMode != PRECISION_CROSSHAIR_NONE )
1374 /// Force 2d view redraw (so that the precision cursor moves with the mouse)
1375 Sys_UpdateWindows( W_XY );
1380 =======================================================================================================================
1381 =======================================================================================================================
1383 void CXYWnd::RetainClipMode(bool bMode) {
1384 bool bSave = g_bRogueClipMode;
1386 if (bMode == true) {
1387 g_bRogueClipMode = bSave;
1390 g_bRogueClipMode = false;
1395 =======================================================================================================================
1396 =======================================================================================================================
1398 void CXYWnd::SetClipMode(bool bMode) {
1399 g_bClipMode = bMode;
1400 g_bRogueClipMode = false;
1405 CleanList(&g_brFrontSplits);
1406 CleanList(&g_brBackSplits);
1407 g_brFrontSplits.next = &g_brFrontSplits;
1408 g_brBackSplits.next = &g_brBackSplits;
1411 if (g_pMovingClip) {
1413 g_pMovingClip = NULL;
1416 CleanList(&g_brFrontSplits);
1417 CleanList(&g_brBackSplits);
1418 g_brFrontSplits.next = &g_brFrontSplits;
1419 g_brBackSplits.next = &g_brBackSplits;
1420 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1425 =======================================================================================================================
1426 =======================================================================================================================
1428 bool CXYWnd::ClipMode() {
1433 =======================================================================================================================
1434 =======================================================================================================================
1436 bool CXYWnd::RogueClipMode() {
1437 return g_bRogueClipMode;
1441 =======================================================================================================================
1442 =======================================================================================================================
1444 bool CXYWnd::PathMode() {
1449 =======================================================================================================================
1450 =======================================================================================================================
1452 bool CXYWnd::PointMode() {
1453 return g_bPointMode;
1457 =======================================================================================================================
1458 =======================================================================================================================
1460 void CXYWnd::SetPointMode(bool b) {
1468 =======================================================================================================================
1469 =======================================================================================================================
1471 void CXYWnd::OnPaint() {
1472 CPaintDC dc(this); // device context for painting
1474 if (!qwglMakeCurrent(dc.m_hDC, win32.hGLRC)) {
1475 common->Printf("ERROR: wglMakeCurrent failed.. Error:%i\n", qglGetError());
1476 common->Printf("Please restart Q3Radiant if the Map view is not working\n");
1481 QE_CheckOpenGLForErrors();
1483 QE_CheckOpenGLForErrors();
1485 if (m_nViewType != XY) {
1487 if (m_nViewType == YZ) {
1488 qglRotatef(-90, 0, 1, 0); // put Z going up
1491 qglRotatef(-90, 1, 0, 0); // put Z going up
1494 if ( g_bCrossHairs ) {
1495 qglColor4f( 0.2f, 0.9f, 0.2f, 0.8f );
1497 if (m_nViewType == XY) {
1498 qglVertex2f(-16384, tdp[1]);
1499 qglVertex2f(16384, tdp[1]);
1500 qglVertex2f(tdp[0], -16384);
1501 qglVertex2f(tdp[0], 16384);
1503 else if (m_nViewType == YZ) {
1504 qglVertex3f(tdp[0], -16384, tdp[2]);
1505 qglVertex3f(tdp[0], 16384, tdp[2]);
1506 qglVertex3f(tdp[0], tdp[1], -16384);
1507 qglVertex3f(tdp[0], tdp[1], 16384);
1510 qglVertex3f(-16384, tdp[1], tdp[2]);
1511 qglVertex3f(16384, tdp[1], tdp[2]);
1512 qglVertex3f(tdp[0], tdp[1], -16384);
1513 qglVertex3f(tdp[0], tdp[1], 16384);
1521 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER].ToFloatPtr());
1522 qglBegin(GL_POINTS);
1523 if (g_Clip1.Set()) {
1524 qglVertex3fv(g_Clip1);
1527 if (g_Clip2.Set()) {
1528 qglVertex3fv(g_Clip2);
1531 if (g_Clip3.Set()) {
1532 qglVertex3fv(g_Clip3);
1539 if (g_Clip1.Set()) {
1540 qglRasterPos3f(g_Clip1.m_ptClip[0] + 2, g_Clip1.m_ptClip[1] + 2, g_Clip1.m_ptClip[2] + 2);
1543 // strMsg.Format("1 (%f, %f, %f)", g_Clip1[0], g_Clip1[1], g_Clip1[2]);
1544 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1547 if (g_Clip2.Set()) {
1548 qglRasterPos3f(g_Clip2.m_ptClip[0] + 2, g_Clip2.m_ptClip[1] + 2, g_Clip2.m_ptClip[2] + 2);
1551 // strMsg.Format("2 (%f, %f, %f)", g_Clip2[0], g_Clip2[1], g_Clip2[2]);
1552 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1555 if (g_Clip3.Set()) {
1556 qglRasterPos3f(g_Clip3.m_ptClip[0] + 2, g_Clip3.m_ptClip[1] + 2, g_Clip3.m_ptClip[2] + 2);
1559 // strMsg.Format("3 (%f, %f, %f)", g_Clip3[0], g_Clip3[1], g_Clip3[2]);
1560 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1563 if (g_Clip1.Set() && g_Clip2.Set() && selected_brushes.next != &selected_brushes) {
1564 ProduceSplitLists();
1567 brush_t *pList = ((m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
1568 for (pBrush = pList->next; pBrush != NULL && pBrush != pList; pBrush = pBrush->next) {
1569 qglColor3f(1, 1, 0);
1573 for (face = pBrush->brush_faces, order = 0; face; face = face->next, order++) {
1574 idWinding *w = face->face_winding;
1580 qglBegin(GL_LINE_LOOP);
1581 for (int i = 0; i < w->GetNumPoints(); i++) {
1582 qglVertex3fv( (*w)[i].ToFloatPtr() );
1593 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER].ToFloatPtr());
1594 qglBegin(GL_POINTS);
1597 for ( n = 0; n < g_nPathCount; n++) {
1598 qglVertex3fv(g_PathPoints[n]);
1605 for (n = 0; n < g_nPathCount; n++) {
1608 g_PathPoints[n].m_ptClip[0] + 2,
1609 g_PathPoints[n].m_ptClip[1] + 2,
1610 g_PathPoints[n].m_ptClip[2] + 2
1612 strMsg.Format("%i", n + 1);
1613 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1617 if (m_nViewType != XY) {
1621 qwglSwapBuffers(dc.m_hDC);
1622 TRACE("XY Paint\n");
1627 =======================================================================================================================
1628 =======================================================================================================================
1630 void CXYWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
1631 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
1635 // =======================================================================================================================
1636 // FIXME: the brush_t *pBrush is never used. ( Entity_Create uses selected_brushes )
1637 // =======================================================================================================================
1639 void CreateEntityFromName(char *pName, brush_t *pBrush, bool forceFixed, idVec3 min, idVec3 max, idVec3 org) {
1642 if (stricmp(pName, "worldspawn") == 0) {
1643 g_pParentWnd->MessageBox("Can't create an entity with worldspawn.", "info", 0);
1647 pecNew = Eclass_ForName(pName, false);
1649 if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
1654 petNew = Entity_Create(pecNew, forceFixed);
1656 if (petNew && idStr::Icmp(pName, "light") == 0 ) {
1657 idVec3 rad = max - min;
1659 if (rad.x != 0 && rad.y != 0 && rad.z != 0) {
1660 SetKeyValue(petNew, "light_radius", va("%g %g %g", idMath::Fabs(rad.x), idMath::Fabs(rad.y), idMath::Fabs(rad.z)));
1661 DeleteKey(petNew, "light");
1666 if (petNew == NULL) {
1667 if (!((selected_brushes.next == &selected_brushes) || (selected_brushes.next->next != &selected_brushes))) {
1668 brush_t *b = selected_brushes.next;
1669 if (b->owner != world_entity && ((b->owner->eclass->fixedsize && pecNew->fixedsize) || forceFixed)) {
1672 for (int i = 0; i < 3; i++) {
1673 origin[i] = b->mins[i] - pecNew->mins[i];
1676 VectorAdd(pecNew->mins, origin, mins);
1677 VectorAdd(pecNew->maxs, origin, maxs);
1679 brush_t *nb = Brush_Create(mins, maxs, &pecNew->texdef);
1680 Entity_LinkBrush(b->owner, nb);
1681 nb->owner->eclass = pecNew;
1682 SetKeyValue(nb->owner, "classname", pName);
1685 Brush_AddToList(nb, &active_brushes);
1691 g_pParentWnd->MessageBox("Failed to create entity.", "info", 0);
1698 // entity_t* pEntity = world_entity; if (selected_brushes.next !=
1699 // &selected_brushes) pEntity = selected_brushes.next->owner;
1701 Select_Brush(petNew->brushes.onext);
1702 Brush_Build(petNew->brushes.onext);
1707 =======================================================================================================================
1708 =======================================================================================================================
1710 brush_t *CreateEntityBrush(int x, int y, CXYWnd *pWnd) {
1716 pWnd->SnapToPoint(x, y, mins);
1719 pWnd->SnapToPoint(x, y, maxs);
1721 int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
1722 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom[nDim] / g_qeglobals.d_gridsize));
1723 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top[nDim] / g_qeglobals.d_gridsize));
1725 if (maxs[nDim] <= mins[nDim]) {
1726 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
1729 for (i = 0; i < 3; i++) {
1730 if (mins[i] == maxs[i]) {
1731 maxs[i] += 16; // don't create a degenerate brush
1734 if (mins[i] > maxs[i]) {
1741 n = Brush_Create(mins, maxs, &g_qeglobals.d_texturewin.texdef);
1746 Brush_AddToList(n, &selected_brushes);
1747 Entity_LinkBrush(world_entity, n);
1753 =======================================================================================================================
1754 =======================================================================================================================
1756 void CreateRightClickEntity(CXYWnd *pWnd, int x, int y, char *pName) {
1757 idVec3 min, max, org;
1758 Select_GetBounds(min, max);
1762 pWnd->GetClientRect(rctZ);
1765 if (selected_brushes.next == &selected_brushes) {
1766 pBrush = CreateEntityBrush(x, rctZ.Height() - 1 - y, pWnd);
1769 CreateEntityFromName(pName, pBrush, true, min, max, org);
1772 pBrush = selected_brushes.next;
1773 CreateEntityFromName(pName, pBrush, false, min, max, org);
1778 =======================================================================================================================
1779 =======================================================================================================================
1781 brush_t *CreateSmartBrush(idVec3 v) {
1786 for (i = 0; i < 3; i++) {
1787 mins[i] = v[i] - 16;
1788 maxs[i] = v[i] + 16;
1791 n = Brush_Create(mins, maxs, &g_qeglobals.d_texturewin.texdef);
1796 Brush_AddToList(n, &selected_brushes);
1798 // Entity_LinkBrush(world_entity, n);
1803 CString g_strSmartEntity;
1806 bool g_bSmartWaiting;
1809 =======================================================================================================================
1810 =======================================================================================================================
1812 void _SmartPointDone(bool b, int n) {
1813 g_bSmartWaiting = false;
1817 =======================================================================================================================
1818 =======================================================================================================================
1820 void CreateSmartEntity(CXYWnd *pWnd, int x, int y, const char *pName) {
1823 g_strSmartEntity = pName;
1824 if (g_strSmartEntity.Find("Smart_Train") >= 0) {
1825 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");
1831 else if (g_strSmartEntity.Find("Smart_Monster...") >= 0) {
1836 else if (g_strSmartEntity.Find("Smart_Rotating") >= 0) {
1837 g_bSmartWaiting = true;
1838 ShowInfoDialog("Left click to specify the rotation origin");
1839 AcquirePath(1, &_SmartPointDone);
1840 while (g_bSmartWaiting) {
1842 if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1843 TranslateMessage(&msg);
1844 DispatchMessage(&msg);
1851 g_bScreenUpdates = false;
1852 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
1853 array.Add(reinterpret_cast < void * > (selected_brushes.next));
1856 brush_t *pBrush = CreateSmartBrush(g_PathPoints[0]);
1859 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(0)));
1860 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(1)));
1862 g_bScreenUpdates = true;
1867 =======================================================================================================================
1868 =======================================================================================================================
1870 void FinishSmartCreation() {
1874 brush_t *pEntities = NULL;
1875 if (g_strSmartEntity.Find("Smart_Train") >= 0) {
1876 g_bScreenUpdates = false;
1877 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
1878 array.Add(reinterpret_cast < void * > (selected_brushes.next));
1880 for (n = 0; n < g_nPathCount; n++) {
1882 CreateRightClickEntity
1884 g_pParentWnd->ActiveXY(),
1885 g_PathPoints[n].m_ptScreen.x,
1886 g_PathPoints[n].m_ptScreen.y,
1889 array.Add(reinterpret_cast < void * > (selected_brushes.next));
1892 for (n = 0; n < g_nPathCount; n++) {
1894 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(n)));
1895 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(n + 1)));
1899 g_bScreenUpdates = true;
1903 g_bPathMode = false;
1904 Sys_UpdateWindows(W_ALL);
1908 =======================================================================================================================
1909 =======================================================================================================================
1911 void CXYWnd::KillPathMode() {
1913 g_bPathMode = false;
1915 g_pPathFunc(false, g_nPathCount);
1920 Sys_UpdateWindows(W_ALL);
1924 // =======================================================================================================================
1925 // gets called for drop down menu messages TIP: it's not always about EntityCreate
1926 // =======================================================================================================================
1928 void CXYWnd::OnEntityCreate(unsigned int nID) {
1929 if (m_mnuDrop.GetSafeHmenu()) {
1931 m_mnuDrop.GetMenuString(nID, strItem, MF_BYCOMMAND);
1933 if (strItem.CompareNoCase("Add to...") == 0) {
1935 // ++timo TODO: fill the menu with current groups? this one is for adding to
1936 // existing groups only
1938 common->Printf("TODO: Add to... in CXYWnd::OnEntityCreate\n");
1940 else if (strItem.CompareNoCase("Remove") == 0) {
1941 // remove selected brushes from their current group
1943 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1947 // ++timo FIXME: remove when all hooks are in
1950 strItem.CompareNoCase("Add to...") == 0 ||
1951 strItem.CompareNoCase("Remove") == 0 ||
1952 strItem.CompareNoCase("Name...") == 0 ||
1953 strItem.CompareNoCase("New group...") == 0
1955 common->Printf("TODO: hook drop down group menu\n");
1959 if (strItem.Find("Smart_") >= 0) {
1960 CreateSmartEntity(this, m_ptDown.x, m_ptDown.y, strItem);
1963 CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, strItem.GetBuffer(0));
1966 Sys_UpdateWindows(W_ALL);
1968 // OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
1972 BOOL CXYWnd::OnCmdMsg( UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo )
1974 if ( CWnd::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ) ) {
1977 return AfxGetMainWnd()->OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
1980 bool MergeMenu(CMenu * pMenuDestination, const CMenu * pMenuAdd, bool bTopLevel /*=false*/)
1982 // get the number menu items in the menus
1983 int iMenuAddItemCount = pMenuAdd->GetMenuItemCount();
1984 int iMenuDestItemCount = pMenuDestination->GetMenuItemCount();
1986 // if there are no items return
1987 if (iMenuAddItemCount == 0)
1990 // if we are not at top level and the destination menu is not empty
1991 // -> we append a seperator
1992 if (!bTopLevel && iMenuDestItemCount > 0)
1993 pMenuDestination->AppendMenu(MF_SEPARATOR);
1995 // iterate through the top level of <pMenuAdd>
1996 for(int iLoop = 0; iLoop < iMenuAddItemCount; iLoop++)
1998 // get the menu string from the add menu
1999 CString sMenuAddString;
2000 pMenuAdd->GetMenuString(iLoop, sMenuAddString, MF_BYPOSITION);
2002 // try to get the submenu of the current menu item
2003 CMenu* pSubMenu = pMenuAdd->GetSubMenu(iLoop);
2005 // check if we have a sub menu
2009 // read the source and append at the destination
2010 UINT nState = pMenuAdd->GetMenuState(iLoop, MF_BYPOSITION);
2011 UINT nItemID = pMenuAdd->GetMenuItemID(iLoop);
2012 if (pMenuDestination->AppendMenu(nState, nItemID, sMenuAddString))
2014 // menu item added, don't forget to correct the item count
2015 iMenuDestItemCount++;
2019 TRACE("MergeMenu: AppendMenu failed!\n");
2025 // create or insert a new popup menu item
2027 // default insert pos is like ap
2028 int iInsertPosDefault = -1;
2030 // if we are at top level merge into existing popups rather than
2031 // creating new ones
2034 ASSERT(sMenuAddString != "&?" && sMenuAddString !=
2036 CString csAdd(sMenuAddString);
2037 csAdd.Remove('&'); // for comparison of menu items supress '&'
2038 bool bAdded = false;
2040 // try to find existing popup
2041 for( int iLoop1 = 0; iLoop1 < iMenuDestItemCount; iLoop1++ )
2043 // get the menu string from the destination menu
2045 pMenuDestination->GetMenuString(iLoop1, sDest, MF_BYPOSITION);
2046 sDest.Remove('&'); // for a better compare (s.a.)
2050 // we got a hit -> merge the two popups
2051 // try to get the submenu of the desired destination menu item
2052 CMenu* pSubMenuDest =
2053 pMenuDestination->GetSubMenu(iLoop1);
2057 // merge the popup recursivly and continue with outer for loop
2058 if (!MergeMenu(pSubMenuDest, pSubMenu, false))
2065 // alternativ insert before <Window> or <Help>
2066 if (iInsertPosDefault == -1 && (sDest == "Window"
2067 || sDest == "?" || sDest == "Help"))
2069 iInsertPosDefault = iLoop1;
2074 // menu added, so go on with loop over pMenuAdd's top level
2079 // if the top level search did not find a position append the menu
2080 if( iInsertPosDefault == -1 )
2082 iInsertPosDefault = pMenuDestination->GetMenuItemCount();
2085 // create a new popup and insert before <Window> or <Help>
2087 if (!NewPopupMenu.CreatePopupMenu())
2089 TRACE("MergeMenu: CreatePopupMenu failed!\n");
2093 // merge the new popup recursivly
2094 if (!MergeMenu(&NewPopupMenu, pSubMenu, false))
2097 // insert the new popup menu into the destination menu
2098 HMENU hNewMenu = NewPopupMenu.GetSafeHmenu();
2099 if (pMenuDestination->InsertMenu(iInsertPosDefault,
2100 MF_BYPOSITION | MF_POPUP | MF_ENABLED,
2101 (UINT)hNewMenu, sMenuAddString ))
2103 // don't forget to correct the item count
2104 iMenuDestItemCount++;
2108 TRACE("MergeMenu: InsertMenu failed!\n");
2112 // don't destroy the new menu
2113 NewPopupMenu.Detach();
2123 =======================================================================================================================
2124 =======================================================================================================================
2126 void CXYWnd::HandleDrop() {
2127 if (g_PrefsDlg.m_bRightClick == false) {
2131 if (!m_mnuDrop.GetSafeHmenu()) { // first time, load it up
2132 m_mnuDrop.CreatePopupMenu();
2134 CMenu *drop = new CMenu;
2135 drop->LoadMenu( IDR_MENU_DROP );
2137 MergeMenu( &m_mnuDrop, drop, false );
2139 int nID = ID_ENTITY_START;
2141 CMenu *pMakeEntityPop = &m_mnuDrop;
2143 // Todo: Make this a config option maybe?
2144 const int entitiesOnSubMenu = false;
2145 if ( entitiesOnSubMenu ) {
2146 pMakeEntityPop = new CMenu;
2147 pMakeEntityPop->CreateMenu();
2150 CMenu *pChild = NULL;
2156 for (e = eclass; e; e = e->next) {
2160 int n_ = strName.Find("_");
2162 CString strLeft = strName.Left(n_);
2163 CString strRight = strName.Right(strName.GetLength() - n_ - 1);
2164 if (strLeft == strActive) { // this is a child
2166 pChild->AppendMenu(MF_STRING, nID++, strName);
2170 pMakeEntityPop->AppendMenu (
2172 reinterpret_cast < unsigned int > (pChild->GetSafeHmenu()),
2175 g_ptrMenus.Add(pChild);
2177 // pChild->DestroyMenu(); delete pChild;
2181 strActive = strLeft;
2183 pChild->CreateMenu();
2184 pChild->AppendMenu(MF_STRING, nID++, strName);
2189 pMakeEntityPop->AppendMenu (
2191 reinterpret_cast < unsigned int > (pChild->GetSafeHmenu()),
2194 g_ptrMenus.Add(pChild);
2196 // pChild->DestroyMenu(); delete pChild;
2201 pMakeEntityPop->AppendMenu(MF_STRING, nID++, strName);
2204 if ( pMakeEntityPop != &m_mnuDrop ) {
2205 m_mnuDrop.AppendMenu (
2207 reinterpret_cast < unsigned int > (pMakeEntityPop->GetSafeHmenu()),
2214 GetCursorPos(&ptMouse);
2215 m_mnuDrop.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, this);
2219 =======================================================================================================================
2220 =======================================================================================================================
2222 void CXYWnd::XY_Init() {
2227 m_precisionCrosshairMode = PRECISION_CROSSHAIR_NONE;
2231 =======================================================================================================================
2232 =======================================================================================================================
2234 void CXYWnd::SnapToPoint(int x, int y, idVec3 &point) {
2235 if (g_PrefsDlg.m_bNoClamp) {
2236 XY_ToPoint(x, y, point);
2239 XY_ToGridPoint(x, y, point);
2242 // -- else -- XY_ToPoint(x, y, point); -- //XY_ToPoint(x, y, point);
2246 =======================================================================================================================
2247 =======================================================================================================================
2249 void CXYWnd::XY_ToPoint(int x, int y, idVec3 &point) {
2252 float fw = m_nWidth;
2253 float fh = m_nHeight;
2254 if (m_nViewType == XY) {
2255 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2256 point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
2260 else if (m_nViewType == YZ) {
2262 // //point[0] = 0; point[1] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; point[2] =
2263 // m_vOrigin[1] + (fy - fh / 2 ) / m_fScale;
2265 point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
2266 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
2270 // point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; /point[1] = 0; point[2] =
2271 // m_vOrigin[1] + (fy - fh / 2) / m_fScale;
2273 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2276 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
2281 =======================================================================================================================
2282 =======================================================================================================================
2284 void CXYWnd::XY_ToGridPoint(int x, int y, idVec3 &point) {
2285 if (m_nViewType == XY) {
2286 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2287 point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2290 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2291 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2293 else if (m_nViewType == YZ) {
2295 // point[0] = 0; point[1] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; point[2]
2296 // = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2298 point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
2299 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2300 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2301 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2305 // point[1] = 0; point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; point[2]
2306 // = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2308 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2309 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2310 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2311 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2316 =======================================================================================================================
2317 =======================================================================================================================
2324 void CXYWnd::XY_MouseDown(int x, int y, int buttons) {
2325 idVec3 point,center;
2326 idVec3 origin, dir, right, up;
2328 m_nButtonstate = buttons;
2331 VectorCopy(vec3_origin, m_vPressdelta);
2335 XY_ToPoint(x, y, point);
2337 VectorCopy(point, origin);
2340 if (m_nViewType == XY) {
2341 origin[2] = HUGE_DISTANCE;
2343 right[0] = 1 / m_fScale;
2347 up[1] = 1 / m_fScale;
2349 point[2] = g_pParentWnd->GetCamera()->Camera().origin[2];
2351 else if (m_nViewType == YZ) {
2352 origin[0] = HUGE_DISTANCE;
2354 right[1] = 1 / m_fScale;
2358 up[2] = 1 / m_fScale;
2360 point[0] = g_pParentWnd->GetCamera()->Camera().origin[0];
2363 origin[1] = HUGE_DISTANCE;
2365 right[0] = 1 / m_fScale;
2369 up[2] = 1 / m_fScale;
2371 point[1] = g_pParentWnd->GetCamera()->Camera().origin[1];
2374 dragOrigin = m_vOrigin;
2379 m_bPress_selection = (selected_brushes.next != &selected_brushes);
2381 GetCursorPos(&m_ptCursor);
2383 // Sys_GetCursorPos (&m_ptCursor.x, &m_ptCursor.y);
2384 if (buttons == MK_LBUTTON && activeDrag) {
2385 activeDragging = true;
2388 activeDragging = false;
2391 // lbutton = manipulate selection shift-LBUTTON = select
2394 (buttons == MK_LBUTTON) ||
2395 (buttons == (MK_LBUTTON | MK_SHIFT)) ||
2396 (buttons == (MK_LBUTTON | MK_CONTROL)) ||
2397 (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT))
2399 if (g_qeglobals.d_select_mode == sel_addpoint) {
2400 XY_ToGridPoint(x, y, point);
2401 if (g_qeglobals.selectObject) {
2402 g_qeglobals.selectObject->addPoint(point);
2408 Patch_SetView((m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
2409 Drag_Begin(x, y, buttons, right, up, origin, dir);
2413 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
2415 // control mbutton = move camera
2416 if (m_nButtonstate == (MK_CONTROL | nMouseButton)) {
2417 VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
2418 Sys_UpdateWindows(W_CAMERA | W_XY_OVERLAY);
2421 // mbutton = angle camera
2424 (g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
2425 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT | MK_CONTROL | MK_RBUTTON))
2427 VectorSubtract(point, g_pParentWnd->GetCamera()->Camera().origin, point);
2429 int n1 = (m_nViewType == XY) ? 1 : 2;
2430 int n2 = (m_nViewType == YZ) ? 1 : 0;
2431 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
2432 if (point[n1] || point[n2]) {
2433 g_pParentWnd->GetCamera()->Camera().angles[nAngle] = RAD2DEG( atan2(point[n1], point[n2]) );
2434 Sys_UpdateWindows(W_CAMERA_IFON | W_XY_OVERLAY);
2438 // shift mbutton = move z checker
2439 if (m_nButtonstate == (MK_SHIFT | nMouseButton)) {
2440 if (RotateMode() || g_bPatchBendMode) {
2441 SnapToPoint(x, y, point);
2442 VectorCopyXY(point, g_vRotateOrigin);
2443 if (g_bPatchBendMode) {
2444 VectorCopy(point, g_vBendOrigin);
2447 Sys_UpdateWindows(W_XY);
2451 SnapToPoint(x, y, point);
2452 if (m_nViewType == XY) {
2453 z.origin[0] = point[0];
2454 z.origin[1] = point[1];
2456 else if (m_nViewType == YZ) {
2457 z.origin[0] = point[1];
2458 z.origin[1] = point[2];
2461 z.origin[0] = point[0];
2462 z.origin[1] = point[2];
2465 Sys_UpdateWindows(W_XY_OVERLAY | W_Z);
2472 =======================================================================================================================
2473 =======================================================================================================================
2475 void CXYWnd::XY_MouseUp(int x, int y, int buttons) {
2476 activeDragging = false;
2477 Drag_MouseUp(buttons);
2478 if (!m_bPress_selection) {
2479 Sys_UpdateWindows(W_ALL);
2483 while (::ShowCursor(TRUE) < 0)
2488 =======================================================================================================================
2489 =======================================================================================================================
2491 bool CXYWnd::DragDelta(int x, int y, idVec3 &move) {
2492 idVec3 xvec, yvec, delta;
2495 xvec[0] = 1 / m_fScale;
2496 xvec[1] = xvec[2] = 0;
2497 yvec[1] = 1 / m_fScale;
2498 yvec[0] = yvec[2] = 0;
2500 for (i = 0; i < 3; i++) {
2501 delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
2502 if (!g_PrefsDlg.m_bNoClamp) {
2503 delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2507 VectorSubtract(delta, m_vPressdelta, move);
2508 VectorCopy(delta, m_vPressdelta);
2511 if (move[0] || move[1] || move[2]) {
2519 =======================================================================================================================
2521 =======================================================================================================================
2523 void CXYWnd::NewBrushDrag(int x, int y) {
2524 idVec3 mins, maxs, junk;
2529 if ( radiant_entityMode.GetBool() ) {
2533 if (!DragDelta(x, y, junk)) {
2537 // delete the current selection
2538 if (selected_brushes.next != &selected_brushes) {
2539 Brush_Free(selected_brushes.next);
2542 SnapToPoint(m_nPressx, m_nPressy, mins);
2544 int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
2546 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom[nDim] / g_qeglobals.d_gridsize));
2547 SnapToPoint(x, y, maxs);
2548 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top[nDim] / g_qeglobals.d_gridsize));
2549 if (maxs[nDim] <= mins[nDim]) {
2550 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
2553 for (i = 0; i < 3; i++) {
2554 if (mins[i] == maxs[i]) {
2555 return; // don't create a degenerate brush
2558 if (mins[i] > maxs[i]) {
2565 n = Brush_Create(mins, maxs, &g_qeglobals.d_texturewin.texdef);
2571 VectorSubtract(maxs, mins, vSize);
2572 g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
2573 g_pParentWnd->SetStatusText(2, g_strStatus);
2575 Brush_AddToList(n, &selected_brushes);
2577 Entity_LinkBrush(world_entity, n);
2581 // Sys_UpdateWindows (W_ALL);
2582 Sys_UpdateWindows(W_XY | W_CAMERA);
2586 =======================================================================================================================
2588 =======================================================================================================================
2590 bool CXYWnd::XY_MouseMoved(int x, int y, int buttons) {
2593 if (!m_nButtonstate) {
2594 if (g_bCrossHairs) {
2595 ::ShowCursor(FALSE);
2596 Sys_UpdateWindows(W_XY | W_XY_OVERLAY);
2604 // lbutton without selection = drag new brush if (m_nButtonstate == MK_LBUTTON &&
2605 // !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint &&
2606 // g_qeglobals.d_select_mode != sel_splineedit)
2608 if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode == sel_brush) {
2613 // lbutton (possibly with control and or shift) with selection = drag selection
2614 if (m_nButtonstate & MK_LBUTTON) {
2615 Drag_MouseMoved(x, y, buttons);
2616 Sys_UpdateWindows(W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
2620 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
2622 // control mbutton = move camera
2623 if (m_nButtonstate == (MK_CONTROL | nMouseButton)) {
2624 SnapToPoint(x, y, point);
2625 VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
2626 Sys_UpdateWindows(W_XY_OVERLAY | W_CAMERA);
2630 // shift mbutton = move z checker
2631 if (m_nButtonstate == (MK_SHIFT | nMouseButton)) {
2632 if (RotateMode() || g_bPatchBendMode) {
2633 SnapToPoint(x, y, point);
2634 VectorCopyXY(point, g_vRotateOrigin);
2635 if (g_bPatchBendMode) {
2636 VectorCopy(point, g_vBendOrigin);
2639 Sys_UpdateWindows(W_XY);
2643 SnapToPoint(x, y, point);
2644 if (m_nViewType == XY) {
2645 z.origin[0] = point[0];
2646 z.origin[1] = point[1];
2648 else if (m_nViewType == YZ) {
2649 z.origin[0] = point[1];
2650 z.origin[1] = point[2];
2653 z.origin[0] = point[0];
2654 z.origin[1] = point[2];
2658 Sys_UpdateWindows(W_XY_OVERLAY | W_Z);
2662 // mbutton = angle camera
2665 (g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
2666 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT | MK_CONTROL | MK_RBUTTON))
2668 SnapToPoint(x, y, point);
2669 VectorSubtract(point, g_pParentWnd->GetCamera()->Camera().origin, point);
2671 int n1 = (m_nViewType == XY) ? 1 : 2;
2672 int n2 = (m_nViewType == YZ) ? 1 : 0;
2673 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
2674 if (point[n1] || point[n2]) {
2675 g_pParentWnd->GetCamera()->Camera().angles[nAngle] = RAD2DEG( atan2(point[n1], point[n2]) );
2676 Sys_UpdateWindows(W_CAMERA_IFON | W_XY_OVERLAY);
2682 // rbutton = drag xy origin
2683 if (m_nButtonstate == MK_RBUTTON) {
2684 Sys_GetCursorPos(&x, &y);
2686 if (x != m_ptCursor.x || y != m_ptCursor.y) {
2687 if ((GetAsyncKeyState(VK_MENU) & 0x8000)) {
2689 long *px2 = &m_ptCursor.x;
2691 if (fDiff(y, m_ptCursor.y) > fDiff(x, m_ptCursor.x)) {
2693 px2 = &m_ptCursor.y;
2698 SetScale( Scale() * 1.1f );
2699 if ( Scale() < 0.1f ) {
2703 else if (*px < *px2) {
2705 SetScale( Scale() * 0.9f );
2706 if ( Scale() > 16.0f ) {
2712 Sys_UpdateWindows(W_XY | W_XY_OVERLAY);
2715 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2716 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2717 m_vOrigin[nDim1] -= (x - m_ptCursor.x) / m_fScale;
2718 m_vOrigin[nDim2] += (y - m_ptCursor.y) / m_fScale;
2719 SetCursorPos(m_ptCursor.x, m_ptCursor.y);
2720 ::ShowCursor(FALSE);
2722 // XY_Draw(); RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
2723 Sys_UpdateWindows(W_XY | W_XY_OVERLAY);
2725 // ::ShowCursor(TRUE);
2736 =======================================================================================================================
2739 =======================================================================================================================
2741 void CXYWnd::XY_DrawGrid() {
2742 float x, y, xb, xe, yb, ye;
2746 int startPos = max ( 64 , g_qeglobals.d_gridsize );
2748 w = m_nWidth / 2 / m_fScale;
2749 h = m_nHeight / 2 / m_fScale;
2751 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2752 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2754 // int nDim1 = 0; int nDim2 = 1;
2755 xb = m_vOrigin[nDim1] - w;
2756 if (xb < region_mins[nDim1]) {
2757 xb = region_mins[nDim1];
2760 xb = startPos * floor(xb / startPos);
2762 xe = m_vOrigin[nDim1] + w;
2763 if (xe > region_maxs[nDim1]) {
2764 xe = region_maxs[nDim1];
2767 xe = startPos * ceil(xe / startPos);
2769 yb = m_vOrigin[nDim2] - h;
2770 if (yb < region_mins[nDim2]) {
2771 yb = region_mins[nDim2];
2774 yb = startPos * floor(yb / startPos);
2776 ye = m_vOrigin[nDim2] + h;
2777 if (ye > region_maxs[nDim2]) {
2778 ye = region_maxs[nDim2];
2781 ye = startPos * ceil(ye / startPos);
2783 // draw major blocks
2784 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR].ToFloatPtr());
2786 int stepSize = 64 * 0.1 / m_fScale;
2787 if (stepSize < 64) {
2788 stepSize = max ( 64 , g_qeglobals.d_gridsize );
2792 for (i = 1; i < stepSize; i <<= 1) {
2798 if (g_qeglobals.d_showgrid) {
2801 for (x = xb; x <= xe; x += stepSize) {
2806 for (y = yb; y <= ye; y += stepSize) {
2814 // draw minor blocks
2815 if ( m_fScale > .1 &&
2816 g_qeglobals.d_showgrid &&
2817 g_qeglobals.d_gridsize * m_fScale >= 4 &&
2818 !g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR].Compare( g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK] ) ) {
2820 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR].ToFloatPtr());
2823 for (x = xb; x < xe; x += g_qeglobals.d_gridsize) {
2824 if (!((int)x & (startPos - 1))) {
2832 for (y = yb; y < ye; y += g_qeglobals.d_gridsize) {
2833 if (!((int)y & (startPos - 1))) {
2845 // draw ZClip boundaries (if applicable)...
2847 if (m_nViewType == XZ || m_nViewType == YZ)
2849 if (g_pParentWnd->GetZWnd()->m_pZClip) // should always be the case at this point I think, but this is safer
2851 if (g_pParentWnd->GetZWnd()->m_pZClip->IsEnabled())
2853 qglColor3f(ZCLIP_COLOUR);
2855 qglBegin (GL_LINES);
2857 qglVertex2f (xb, g_pParentWnd->GetZWnd()->m_pZClip->GetTop());
2858 qglVertex2f (xe, g_pParentWnd->GetZWnd()->m_pZClip->GetTop());
2860 qglVertex2f (xb, g_pParentWnd->GetZWnd()->m_pZClip->GetBottom());
2861 qglVertex2f (xe, g_pParentWnd->GetZWnd()->m_pZClip->GetBottom());
2872 // draw coordinate text if needed
2873 if (g_qeglobals.d_savedinfo.show_coordinates) {
2874 // glColor4f(0, 0, 0, 0);
2875 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT].ToFloatPtr());
2877 float lastRaster = xb;
2879 for (x = xb; x < xe; x += stepSize) {
2880 qglRasterPos2f(x, m_vOrigin[nDim2] + h - 10 / m_fScale);
2881 sprintf(text, "%i", (int)x);
2882 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
2885 for (y = yb; y < ye; y += stepSize) {
2886 qglRasterPos2f(m_vOrigin[nDim1] - w + 1, y);
2887 sprintf(text, "%i", (int)y);
2888 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
2892 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME].ToFloatPtr());
2895 qglRasterPos2f(m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale);
2898 if (m_nViewType == XY) {
2899 strcpy(cView, "XY Top");
2901 else if (m_nViewType == XZ) {
2902 strcpy(cView, "XZ Front");
2905 strcpy(cView, "YZ Side");
2908 qglCallLists(strlen(cView), GL_UNSIGNED_BYTE, cView);
2912 * if (true) { qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
2913 * qglBegin (GL_LINES); qglVertex2f (x, yb); qglVertex2f (x, ye); qglEnd(); }
2918 =======================================================================================================================
2920 =======================================================================================================================
2922 void CXYWnd::XY_DrawBlockGrid() {
2923 float x, y, xb, xe, yb, ye;
2927 w = m_nWidth / 2 / m_fScale;
2928 h = m_nHeight / 2 / m_fScale;
2930 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2931 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2933 xb = m_vOrigin[nDim1] - w;
2934 if (xb < region_mins[nDim1]) {
2935 xb = region_mins[nDim1];
2938 xb = 1024 * floor(xb / 1024);
2940 xe = m_vOrigin[nDim1] + w;
2941 if (xe > region_maxs[nDim1]) {
2942 xe = region_maxs[nDim1];
2945 xe = 1024 * ceil(xe / 1024);
2947 yb = m_vOrigin[nDim2] - h;
2948 if (yb < region_mins[nDim2]) {
2949 yb = region_mins[nDim2];
2952 yb = 1024 * floor(yb / 1024);
2954 ye = m_vOrigin[nDim2] + h;
2955 if (ye > region_maxs[nDim2]) {
2956 ye = region_maxs[nDim2];
2959 ye = 1024 * ceil(ye / 1024);
2961 // draw major blocks
2962 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK].ToFloatPtr());
2967 for (x = xb; x <= xe; x += 1024) {
2972 for (y = yb; y <= ye; y += 1024) {
2980 // draw coordinate text if needed
2981 for (x = xb; x < xe; x += 1024) {
2982 for (y = yb; y < ye; y += 1024) {
2983 qglRasterPos2f(x + 512, y + 512);
2984 sprintf(text, "%i,%i", (int)floor(x / 1024), (int)floor(y / 1024));
2985 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
2989 qglColor4f(0, 0, 0, 0);
2992 void GLColoredBoxWithLabel(float x, float y, float size, idVec4 color, const char *text, idVec4 textColor, float xofs, float yofs, float lineSize) {
2993 globalImages->BindNull();
2994 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2995 qglDisable(GL_CULL_FACE);
2996 qglDisable(GL_BLEND);
2997 qglColor4f(color[0], color[1], color[2], color[3]);
2999 qglVertex3f(x - size, y - size, 0);
3000 qglVertex3f(x + size, y - size, 0);
3001 qglVertex3f(x + size, y + size, 0);
3002 qglVertex3f(x - size, y + size, 0);
3005 qglColor4f(textColor[0], textColor[1], textColor[2], textColor[3]);
3006 qglLineWidth(lineSize);
3007 qglRasterPos2f(x + xofs, y + yofs);
3008 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
3012 =======================================================================================================================
3013 =======================================================================================================================
3015 void CXYWnd::DrawRotateIcon() {
3018 if (m_nViewType == XY) {
3019 x = g_vRotateOrigin[0];
3020 y = g_vRotateOrigin[1];
3022 else if (m_nViewType == YZ) {
3023 x = g_vRotateOrigin[1];
3024 y = g_vRotateOrigin[2];
3027 x = g_vRotateOrigin[0];
3028 y = g_vRotateOrigin[2];
3031 qglEnable(GL_BLEND);
3032 globalImages->BindNull();
3033 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3034 qglDisable(GL_CULL_FACE);
3035 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3036 qglColor4f( 0.8f, 0.1f, 0.9f, 0.25f );
3039 qglVertex3f(x - 4, y - 4, 0);
3040 qglVertex3f(x + 4, y - 4, 0);
3041 qglVertex3f(x + 4, y + 4, 0);
3042 qglVertex3f(x - 4, y + 4, 0);
3044 qglDisable(GL_BLEND);
3046 qglColor4f( 1.0f, 0.2f, 1.0f, 1.0f );
3047 qglBegin(GL_POINTS);
3048 qglVertex3f(x, y, 0);
3052 int w = m_nWidth / 2 / m_fScale;
3053 int h = m_nHeight / 2 / m_fScale;
3054 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
3055 int nDim2 = (m_nViewType == XY) ? 1 : 2;
3056 x = m_vOrigin[nDim1] - w + 35 / m_fScale;
3057 y = m_vOrigin[nDim2] + h - 40 / m_fScale;
3058 const char *p = "Rotate Z Axis";
3059 if (g_qeglobals.rotateAxis == 1) {
3060 p = "Rotate Y Axis";
3061 } else if (g_qeglobals.rotateAxis == 0) {
3062 p = "Rotate X Axis";
3065 if (g_qeglobals.flatRotation) {
3066 str += g_qeglobals.flatRotation == 2 ? " Flat [center] " : " Flat [ rot origin ] ";
3068 qglRasterPos2f(x, y);
3069 qglCallLists(str.Length(), GL_UNSIGNED_BYTE, str.c_str());
3073 =======================================================================================================================
3074 =======================================================================================================================
3076 void CXYWnd::DrawCameraIcon() {
3079 if (m_nViewType == XY) {
3080 x = g_pParentWnd->GetCamera()->Camera().origin[0];
3081 y = g_pParentWnd->GetCamera()->Camera().origin[1];
3082 a = g_pParentWnd->GetCamera()->Camera().angles[YAW] * idMath::M_DEG2RAD;
3084 else if (m_nViewType == YZ) {
3085 x = g_pParentWnd->GetCamera()->Camera().origin[1];
3086 y = g_pParentWnd->GetCamera()->Camera().origin[2];
3087 a = g_pParentWnd->GetCamera()->Camera().angles[PITCH] * idMath::M_DEG2RAD;
3090 x = g_pParentWnd->GetCamera()->Camera().origin[0];
3091 y = g_pParentWnd->GetCamera()->Camera().origin[2];
3092 a = g_pParentWnd->GetCamera()->Camera().angles[PITCH] * idMath::M_DEG2RAD;
3095 float scale = 1.0/m_fScale; //jhefty - keep the camera icon proportionally the same size
3097 qglColor3f(0.0, 0.0, 1.0);
3098 qglBegin(GL_LINE_STRIP);
3099 qglVertex3f(x - 16*scale, y, 0);
3100 qglVertex3f(x, y + 8*scale, 0);
3101 qglVertex3f(x + 16*scale, y, 0);
3102 qglVertex3f(x, y - 8*scale, 0);
3103 qglVertex3f(x - 16*scale, y, 0);
3104 qglVertex3f(x + 16*scale, y, 0);
3107 qglBegin(GL_LINE_STRIP);
3108 qglVertex3f(x + (48 * cos( a + idMath::PI * 0.25f )*scale), y + (48 * sin( a + idMath::PI * 0.25f )*scale), 0);
3109 qglVertex3f(x, y, 0);
3110 qglVertex3f(x + (48 * cos( a - idMath::PI * 0.25f )*scale), y + (48 * sin( a - idMath::PI * 0.25f )*scale), 0);
3116 qglRasterPos2f(x + 64, y + 64);
3117 sprintf(text, "%f", g_pParentWnd->GetCamera()->Camera().angles[YAW]);
3118 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
3123 =======================================================================================================================
3124 =======================================================================================================================
3126 void CXYWnd::DrawZIcon(void) {
3127 if (m_nViewType == XY) {
3128 float x = z.origin[0];
3129 float y = z.origin[1];
3130 qglEnable(GL_BLEND);
3131 globalImages->BindNull();
3132 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3133 qglDisable(GL_CULL_FACE);
3134 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3135 qglColor4f(0.0, 0.0, 1.0, 0.25);
3137 qglVertex3f(x - 8, y - 8, 0);
3138 qglVertex3f(x + 8, y - 8, 0);
3139 qglVertex3f(x + 8, y + 8, 0);
3140 qglVertex3f(x - 8, y + 8, 0);
3142 qglDisable(GL_BLEND);
3144 qglColor4f(0.0, 0.0, 1.0, 1);
3146 qglBegin(GL_LINE_LOOP);
3147 qglVertex3f(x - 8, y - 8, 0);
3148 qglVertex3f(x + 8, y - 8, 0);
3149 qglVertex3f(x + 8, y + 8, 0);
3150 qglVertex3f(x - 8, y + 8, 0);
3153 qglBegin(GL_LINE_STRIP);
3154 qglVertex3f(x - 4, y + 4, 0);
3155 qglVertex3f(x + 4, y + 4, 0);
3156 qglVertex3f(x - 4, y - 4, 0);
3157 qglVertex3f(x + 4, y - 4, 0);
3163 =======================================================================================================================
3165 =======================================================================================================================
3167 bool FilterBrush(brush_t *pb) {
3170 return false; // during construction
3173 if (pb->hiddenBrush) {
3177 if ( pb->forceVisibile ) {
3181 if (g_pParentWnd->GetZWnd()->m_pZClip) // ZClip class up and running? (and hence Z window built)
3183 if (g_pParentWnd->GetZWnd()->m_pZClip->IsEnabled())
3185 // ZClipping active...
3187 if (pb->mins[2] > g_pParentWnd->GetZWnd()->m_pZClip->GetTop() // brush bottom edge is above clip top
3189 pb->maxs[2] < g_pParentWnd->GetZWnd()->m_pZClip->GetBottom()// brush top edge is below clip bottom
3197 if (g_qeglobals.d_savedinfo.exclude & (EXCLUDE_CAULK | EXCLUDE_VISPORTALS)) {
3199 // filter out the brush only if all faces are caulk if not don't hide the whole
3200 // brush, proceed on a per-face basis (Cam_Draw) ++timo TODO: set this as a
3201 // preference .. show caulk: hide any brush with caulk // don't draw caulk faces
3204 f = pb->brush_faces;
3206 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) {
3207 if (!strstr(f->texdef.name, "caulk")) {
3211 if (strstr(f->texdef.name, "visportal")) {
3219 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) {
3225 // ++timo FIXME: .. same deal here?
3226 if (strstr(pb->brush_faces->texdef.name, "donotenter")) {
3231 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT) {
3232 if (strstr(pb->brush_faces->texdef.name, "hint")) {
3237 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP) {
3238 if (strstr(pb->brush_faces->texdef.name, "clip")) {
3243 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_TRIGGERS) {
3244 if (strstr(pb->brush_faces->texdef.name, "trig")) {
3249 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_NODRAW) {
3250 if (strstr(pb->brush_faces->texdef.name, "nodraw")) {
3256 if (strstr(pb->brush_faces->texdef.name, "skip")) {
3260 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DYNAMICS) {
3261 if (pb->modelHandle > 0) {
3262 idRenderModel *model = pb->modelHandle;
3263 if ( dynamic_cast<idRenderModelLiquid*>(model) ) {
3269 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CURVES) {
3275 if (pb->owner == world_entity) {
3276 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD) {
3283 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT ) {
3284 return ( idStr::Cmpn( pb->owner->eclass->name, "func_static", 10 ) != 0 );
3288 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS && pb->owner->eclass->nShowFlags & ECLASS_LIGHT ) {
3292 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_COMBATNODES && pb->owner->eclass->nShowFlags & ECLASS_COMBATNODE ) {
3296 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS && pb->owner->eclass->nShowFlags & ECLASS_PATH) {
3300 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_MODELS && ( pb->owner->eclass->entityModel != NULL || pb->modelHandle > 0 ) ) {
3308 =======================================================================================================================
3310 DrawPathLines Draws connections between entities. Needs to consider all entities, not just ones on screen, because
3311 the lines can be visible when neither end is. Called for both camera view and xy view.
3312 =======================================================================================================================
3314 void DrawPathLines(void) {
3324 const char *ent_target[MAX_MAP_ENTITIES];
3325 entity_t *ent_entity[MAX_MAP_ENTITIES];
3327 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS) {
3332 for (te = entities.next; te != &entities && num_entities != MAX_MAP_ENTITIES; te = te->next) {
3333 for (int i = 0; i < 2048; i++) {
3335 ent_target[num_entities] = ValueForKey(te, "target");
3337 ent_target[num_entities] = ValueForKey(te, va("target%i", i));
3339 if (ent_target[num_entities][0]) {
3340 ent_entity[num_entities] = te;
3342 } else if (i > 16) {
3348 for (se = entities.next; se != &entities; se = se->next) {
3349 psz = ValueForKey(se, "name");
3351 if (psz == NULL || psz[0] == '\0') {
3355 sb = se->brushes.onext;
3356 if (sb == &se->brushes) {
3360 for (k = 0; k < num_entities; k++) {
3361 if (strcmp(ent_target[k], psz)) {
3366 tb = te->brushes.onext;
3367 if (tb == &te->brushes) {
3371 mid = sb->owner->origin;
3372 mid1 = tb->owner->origin;
3374 VectorSubtract(mid1, mid, dir);
3375 len = dir.Normalize();
3376 s1[0] = -dir[1] * 8 + dir[0] * 8;
3377 s2[0] = dir[1] * 8 + dir[0] * 8;
3378 s1[1] = dir[0] * 8 + dir[1] * 8;
3379 s2[1] = -dir[0] * 8 + dir[1] * 8;
3381 qglColor3f(se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
3384 qglVertex3fv(mid.ToFloatPtr());
3385 qglVertex3fv(mid1.ToFloatPtr());
3387 arrows = (int)(len / 256) + 1;
3389 for (i = 0; i < arrows; i++) {
3390 f = len * (i + 0.5) / arrows;
3392 mid1 = mid + (f * dir);
3394 qglVertex3fv(mid1.ToFloatPtr());
3395 qglVertex3f(mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
3396 qglVertex3fv(mid1.ToFloatPtr());
3397 qglVertex3f(mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
3408 // =======================================================================================================================
3409 // can be greatly simplified but per usual i am in a hurry which is not an excuse, just a fact
3410 // =======================================================================================================================
3412 void CXYWnd::PaintSizeInfo(int nDim1, int nDim2, idVec3 vMinBounds, idVec3 vMaxBounds) {
3414 VectorSubtract(vMaxBounds, vMinBounds, vSize);
3418 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
3419 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
3420 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65
3423 if (m_nViewType == XY) {
3426 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
3427 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3429 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3430 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3432 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
3433 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3435 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
3436 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
3438 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
3439 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
3441 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
3442 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
3446 qglRasterPos3f(Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
3447 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
3448 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3450 qglRasterPos3f(vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
3451 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
3452 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3454 qglRasterPos3f(vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
3455 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
3456 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3458 else if (m_nViewType == XZ) {
3461 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
3462 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3464 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3465 qglVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3467 qglVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
3468 qglVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3470 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0, vMinBounds[nDim2]);
3471 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMinBounds[nDim2]);
3473 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMinBounds[nDim2]);
3474 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMaxBounds[nDim2]);
3476 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0, vMaxBounds[nDim2]);
3477 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMaxBounds[nDim2]);
3481 qglRasterPos3f(Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
3482 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
3483 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3485 qglRasterPos3f(vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
3486 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
3487 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3489 qglRasterPos3f(vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
3490 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
3491 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3496 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
3497 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3499 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3500 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3502 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
3503 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3505 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
3506 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
3508 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
3509 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
3511 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
3512 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
3516 qglRasterPos3f(0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
3517 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
3518 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3520 qglRasterPos3f(0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
3521 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
3522 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3524 qglRasterPos3f(0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
3525 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
3526 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3533 extern void DrawBrushEntityName(brush_t *b);
3536 =======================================================================================================================
3537 =======================================================================================================================
3539 void CXYWnd::XY_Draw() {
3547 if (!active_brushes.next) {
3548 return; // not valid yet
3554 GL_State( GLS_DEFAULT );
3555 qglViewport(0, 0, m_nWidth, m_nHeight);
3556 qglScissor(0, 0, m_nWidth, m_nHeight);
3559 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
3560 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
3561 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],
3565 qglDisable(GL_DEPTH_TEST);
3566 qglDisable(GL_CULL_FACE);
3567 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3570 qglMatrixMode(GL_PROJECTION);
3573 w = m_nWidth / 2 / m_fScale;
3574 h = m_nHeight / 2 / m_fScale;
3576 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
3577 int nDim2 = (m_nViewType == XY) ? 1 : 2;
3578 mins[0] = m_vOrigin[nDim1] - w;
3579 maxs[0] = m_vOrigin[nDim1] + w;
3580 mins[1] = m_vOrigin[nDim2] - h;
3581 maxs[1] = m_vOrigin[nDim2] + h;
3583 idBounds viewBounds( mins, maxs );
3584 viewBounds[0].z = -99999;
3585 viewBounds[1].z = 99999;
3587 qglOrtho(mins[0], maxs[0], mins[1], maxs[1], MIN_WORLD_COORD, MAX_WORLD_COORD);
3590 globalImages->BindNull();
3591 // now draw the grid
3598 if (m_nViewType != XY) {
3600 if (m_nViewType == YZ) {
3601 qglRotatef(-90, 0, 1, 0); // put Z going up
3605 qglRotatef(-90, 1, 0, 0); // put Z going up
3610 for ( brush = active_brushes.next; brush != &active_brushes; brush = brush->next ) {
3611 if ( brush->forceVisibile || ( brush->owner->eclass->nShowFlags & ( ECLASS_LIGHT | ECLASS_PROJECTEDLIGHT ) ) ) {
3612 } else if ( brush->mins[nDim1] > maxs[0] || brush->mins[nDim2] > maxs[1] || brush->maxs[nDim1] < mins[0] || brush->maxs[nDim2] < mins[1] ) {
3614 continue; // off screen
3617 if ( FilterBrush(brush) ) {
3623 if (brush->owner != e && brush->owner) {
3624 qglColor3fv(brush->owner->eclass->color.ToFloatPtr());
3627 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES].ToFloatPtr());
3630 Brush_DrawXY( brush, m_nViewType );
3636 if (g_qeglobals.d_pointfile_display_list) {
3637 qglCallList(g_qeglobals.d_pointfile_display_list);
3640 if (!(m_nViewType == XY)) {
3645 if (g_qeglobals.show_blocks) {
3649 // now draw selected brushes
3650 if (m_nViewType != XY) {
3652 if (m_nViewType == YZ) {
3653 qglRotatef(-90, 0, 1, 0); // put Z going up
3657 qglRotatef(-90, 1, 0, 0); // put Z going up
3663 g_qeglobals.d_select_translate[0],
3664 g_qeglobals.d_select_translate[1],
3665 g_qeglobals.d_select_translate[2]
3669 qglColor3f( 0.8f, 0.1f, 0.9f );
3671 else if (ScaleMode()) {
3672 qglColor3f( 0.1f, 0.8f, 0.1f );
3675 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr());
3678 if (g_PrefsDlg.m_bNoStipple == FALSE) {
3679 qglEnable(GL_LINE_STIPPLE);
3680 qglLineStipple(3, 0xaaaa);
3687 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = 999999.9f;
3688 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = -999999.9f;
3690 int nSaveDrawn = drawn;
3691 bool bFixedSize = false;
3692 for (brush = selected_brushes.next; brush != &selected_brushes; brush = brush->next) {
3694 Brush_DrawXY(brush, m_nViewType, true);
3697 if (brush->owner->eclass->fixedsize) {
3701 if (g_PrefsDlg.m_bSizePaint) {
3702 for (i = 0; i < 3; i++) {
3703 if (brush->mins[i] < vMinBounds[i]) {
3704 vMinBounds[i] = brush->mins[i];
3707 if (brush->maxs[i] > vMaxBounds[i]) {
3708 vMaxBounds[i] = brush->maxs[i];
3715 if (g_PrefsDlg.m_bNoStipple == FALSE) {
3716 qglDisable(GL_LINE_STIPPLE);
3721 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint) {
3722 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
3725 // edge / vertex flags
3726 if (g_qeglobals.d_select_mode == sel_vertex) {
3728 qglColor3f(0, 1, 0);
3729 qglBegin(GL_POINTS);
3730 for (i = 0; i < g_qeglobals.d_numpoints; i++) {
3731 qglVertex3fv(g_qeglobals.d_points[i].ToFloatPtr());
3737 else if (g_qeglobals.d_select_mode == sel_edge) {
3741 qglColor3f(0, 0, 1);
3742 qglBegin(GL_POINTS);
3743 for (i = 0; i < g_qeglobals.d_numedges; i++) {
3744 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1].ToFloatPtr();
3745 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2].ToFloatPtr();
3746 qglVertex3f((v1[0] + v2[0]) * 0.5, (v1[1] + v2[1]) * 0.5, (v1[2] + v2[2]) * 0.5);
3753 g_splineList->draw (static_cast<bool>(g_qeglobals.d_select_mode == sel_editpoint || g_qeglobals.d_select_mode == sel_addpoint));
3755 if (g_pParentWnd->GetNurbMode() && g_pParentWnd->GetNurb()->GetNumValues()) {
3756 int maxage = g_pParentWnd->GetNurb()->GetNumValues();
3758 qglColor3f(0, 0, 1);
3760 qglBegin(GL_POINTS);
3761 g_pParentWnd->GetNurb()->SetOrder(3);
3762 for (i = 0; i < 100; i++) {
3763 idVec2 v = g_pParentWnd->GetNurb()->GetCurrentValue(time);
3764 qglVertex3f(v.x, v.y, 0.0f);
3769 qglColor3f(0, 0, 1);
3770 qglBegin(GL_POINTS);
3771 for (i = 0; i < maxage; i++) {
3772 idVec2 v = g_pParentWnd->GetNurb()->GetValue(i);
3773 qglVertex3f(v.x, v.y, 0.0f);
3783 -g_qeglobals.d_select_translate[0],
3784 -g_qeglobals.d_select_translate[1],
3785 -g_qeglobals.d_select_translate[2]
3788 if (!(m_nViewType == XY)) {
3792 // area selection hack
3793 if (g_qeglobals.d_select_mode == sel_area) {
3794 qglEnable(GL_BLEND);
3795 qglPolygonMode ( GL_FRONT_AND_BACK , GL_FILL );
3796 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3797 qglColor4f(0.0, 0.0, 1.0, 0.25);
3800 g_qeglobals.d_vAreaTL[nDim1],
3801 g_qeglobals.d_vAreaTL[nDim2],
3802 g_qeglobals.d_vAreaBR[nDim1],
3803 g_qeglobals.d_vAreaBR[nDim2]
3805 qglDisable(GL_BLEND);
3806 qglPolygonMode ( GL_FRONT_AND_BACK , GL_LINE );
3807 qglColor3f(1.0f, 1.0f, 1.0f);
3810 g_qeglobals.d_vAreaTL[nDim1],
3811 g_qeglobals.d_vAreaTL[nDim2],
3812 g_qeglobals.d_vAreaBR[nDim1],
3813 g_qeglobals.d_vAreaBR[nDim2]
3818 // now draw camera point
3826 /// Draw a "precision crosshair" if enabled
3827 if( m_precisionCrosshairMode != PRECISION_CROSSHAIR_NONE )
3828 DrawPrecisionCrosshair();
3832 // QE_CheckOpenGLForErrors();
3837 =======================================================================================================================
3838 =======================================================================================================================
3840 idVec3 &CXYWnd::GetOrigin() {
3845 =======================================================================================================================
3846 =======================================================================================================================
3848 void CXYWnd::SetOrigin(idVec3 org) {
3849 m_vOrigin[0] = org[0];
3850 m_vOrigin[1] = org[1];
3851 m_vOrigin[2] = org[2];
3855 =======================================================================================================================
3856 =======================================================================================================================
3858 void CXYWnd::OnSize(UINT nType, int cx, int cy) {
3859 CWnd::OnSize(nType, cx, cy);
3862 GetClientRect(rect);
3863 m_nWidth = rect.Width();
3864 m_nHeight = rect.Height();
3865 InvalidateRect(NULL, false);
3868 brush_t hold_brushes;
3871 =======================================================================================================================
3872 =======================================================================================================================
3874 void CXYWnd::Clip() {
3876 hold_brushes.next = &hold_brushes;
3877 ProduceSplitLists();
3879 // brush_t* pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
3881 if (g_PrefsDlg.m_bSwitchClip) {
3882 pList = ((m_nViewType == XZ) ? g_bSwitch : !g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
3885 pList = ((m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
3888 if (pList->next != pList) {
3889 Brush_CopyList(pList, &hold_brushes);
3890 CleanList(&g_brFrontSplits);
3891 CleanList(&g_brBackSplits);
3893 Brush_CopyList(&hold_brushes, &selected_brushes);
3894 if (RogueClipMode()) {
3895 RetainClipMode(false);
3898 RetainClipMode(true);
3901 Sys_UpdateWindows(W_ALL);
3904 else if (PathMode()) {
3905 FinishSmartCreation();
3907 g_pPathFunc(true, g_nPathCount);
3912 g_bPathMode = false;
3917 =======================================================================================================================
3918 =======================================================================================================================
3920 void CXYWnd::SplitClip() {
3921 ProduceSplitLists();
3922 if ((g_brFrontSplits.next != &g_brFrontSplits) && (g_brBackSplits.next != &g_brBackSplits)) {
3924 Brush_CopyList(&g_brFrontSplits, &selected_brushes);
3925 Brush_CopyList(&g_brBackSplits, &selected_brushes);
3926 CleanList(&g_brFrontSplits);
3927 CleanList(&g_brBackSplits);
3928 if (RogueClipMode()) {
3929 RetainClipMode(false);
3932 RetainClipMode(true);
3938 =======================================================================================================================
3939 =======================================================================================================================
3941 void CXYWnd::FlipClip() {
3942 g_bSwitch = !g_bSwitch;
3943 Sys_UpdateWindows(XY | W_CAMERA_IFON);
3947 // =======================================================================================================================
3948 // makes sure the selected brush or camera is in view
3949 // =======================================================================================================================
3951 void CXYWnd::PositionView() {
3952 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
3953 int nDim2 = (m_nViewType == XY) ? 1 : 2;
3954 brush_t *b = selected_brushes.next;
3955 if (b && b->next != b) {
3956 m_vOrigin[nDim1] = b->mins[nDim1];
3957 m_vOrigin[nDim2] = b->mins[nDim2];
3960 m_vOrigin[nDim1] = g_pParentWnd->GetCamera()->Camera().origin[nDim1];
3961 m_vOrigin[nDim2] = g_pParentWnd->GetCamera()->Camera().origin[nDim2];
3966 =======================================================================================================================
3967 =======================================================================================================================
3969 void CXYWnd::VectorCopyXY(const idVec3 &in, idVec3 &out) {
3970 if (m_nViewType == XY) {
3974 else if (m_nViewType == XZ) {
3985 =======================================================================================================================
3986 =======================================================================================================================
3988 void CXYWnd::OnDestroy() {
3995 =======================================================================================================================
3996 =======================================================================================================================
3998 void CXYWnd::SetViewType(int n) {
4000 char *p = "YZ Side";
4001 if (m_nViewType == XY) {
4003 } else if (m_nViewType == XZ) {
4010 =======================================================================================================================
4011 =======================================================================================================================
4013 void CXYWnd::Redraw(unsigned int nBits) {
4014 m_nUpdateBits = nBits;
4015 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
4016 m_nUpdateBits = W_XY;
4020 =======================================================================================================================
4021 =======================================================================================================================
4023 bool CXYWnd::RotateMode() {
4024 return g_bRotateMode;
4028 =======================================================================================================================
4029 =======================================================================================================================
4031 bool CXYWnd::ScaleMode() {
4032 return g_bScaleMode;
4036 =======================================================================================================================
4037 =======================================================================================================================
4039 extern bool Select_OnlyModelsSelected();
4040 bool CXYWnd::SetRotateMode(bool bMode) {
4041 if (bMode && selected_brushes.next != &selected_brushes) {
4042 g_bRotateMode = true;
4043 if (Select_OnlyModelsSelected()) {
4044 Select_GetTrueMid(g_vRotateOrigin);
4046 Select_GetMid(g_vRotateOrigin);
4049 Select_InitializeRotation();
4053 Sys_Status("Need a brush selected to turn on Mouse Rotation mode\n");
4056 g_bRotateMode = false;
4057 Select_FinalizeRotation();
4061 return g_bRotateMode;
4065 =======================================================================================================================
4066 =======================================================================================================================
4068 void CXYWnd::SetScaleMode(bool bMode) {
4069 g_bScaleMode = bMode;
4074 // =======================================================================================================================
4075 // xy - z xz - y yz - x
4076 // =======================================================================================================================
4078 void CXYWnd::OnSelectMouserotate() {
4079 // TODO: Add your command handler code here
4083 =======================================================================================================================
4084 =======================================================================================================================
4086 void CleanCopyEntities() {
4087 entity_t *pe = g_enClipboard.next;
4088 while (pe != NULL && pe != &g_enClipboard) {
4089 entity_t *next = pe->next;
4096 g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
4100 =======================================================================================================================
4101 =======================================================================================================================
4103 entity_t *Entity_CopyClone(entity_t *e) {
4107 n->brushes.onext = n->brushes.oprev = &n->brushes;
4108 n->eclass = e->eclass;
4109 n->rotation = e->rotation;
4111 // add the entity to the entity list
4112 n->next = g_enClipboard.next;
4113 g_enClipboard.next = n;
4115 n->prev = &g_enClipboard;
4117 n->epairs = e->epairs;
4123 =======================================================================================================================
4124 =======================================================================================================================
4126 bool OnList(entity_t *pFind, CPtrArray *pList) {
4127 int nSize = pList->GetSize();
4128 while (nSize-- > 0) {
4129 entity_t *pEntity = reinterpret_cast < entity_t * > (pList->GetAt(nSize));
4130 if (pEntity == pFind) {
4139 =======================================================================================================================
4140 =======================================================================================================================
4145 CWaitCursor WaitCursor;
4146 g_Clipboard.SetLength(0);
4147 g_PatchClipboard.SetLength(0);
4149 Map_SaveSelected(&g_Clipboard, &g_PatchClipboard);
4151 bool bClipped = false;
4152 UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
4153 if (nClipboard > 0) {
4154 if (OpenClipboard()) {
4157 long lSize = g_Clipboard.GetLength();
4158 HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, lSize + sizeof (long));
4160 unsigned char *cp = reinterpret_cast < unsigned char * > (::GlobalLock(h));
4161 memcpy(cp, &lSize, sizeof (long));
4162 cp += sizeof (long);
4163 g_Clipboard.SeekToBegin();
4164 g_Clipboard.Read(cp, lSize);
4166 ::SetClipboardData(nClipboard, h);
4174 common->Printf("Unable to register Windows clipboard formats, copy/paste between editors will not be possible");
4178 * CString strOut; ::GetTempPath(1024, strOut.GetBuffer(1024));
4179 * strOut.ReleaseBuffer(); AddSlash(strOut); strOut += "RadiantClipboard.$$$";
4180 * Map_SaveSelected(strOut.GetBuffer(0));
4183 CPtrArray holdArray;
4184 CleanList(&g_brClipboard);
4185 CleanCopyEntities();
4186 for (brush_t * pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next) {
4187 if (pBrush->owner == world_entity) {
4188 brush_t *pClone = Brush_Clone(pBrush);
4189 pClone->owner = NULL;
4190 Brush_AddToList(pClone, &g_brClipboard);
4193 if (!OnList(pBrush->owner, &holdArray)) {
4194 entity_t *e = pBrush->owner;
4195 holdArray.Add(reinterpret_cast < void * > (e));
4197 entity_t *pEClone = Entity_CopyClone(e);
4198 for (brush_t * pEB = e->brushes.onext; pEB != &e->brushes; pEB = pEB->onext) {
4199 brush_t *pClone = Brush_Clone(pEB);
4201 // Brush_AddToList (pClone, &g_brClipboard);
4202 Entity_LinkBrush(pEClone, pClone);
4203 Brush_Build(pClone);
4212 =======================================================================================================================
4213 =======================================================================================================================
4215 void CXYWnd::Undo() {
4217 * if (g_brUndo.next != &g_brUndo) { g_bScreenUpdates = false; Select_Delete();
4218 * for (brush_t* pBrush = g_brUndo.next ; pBrush != NULL && pBrush != &g_brUndo ;
4219 * pBrush=pBrush->next) { brush_t* pClone = Brush_Clone(pBrush); Brush_AddToList
4220 * (pClone, &active_brushes); Entity_LinkBrush (pBrush->pUndoOwner, pClone);
4221 * Brush_Build(pClone); Select_Brush(pClone); } CleanList(&g_brUndo);
4222 * g_bScreenUpdates = true; Sys_UpdateWindows(W_ALL); } else common->Printf("Nothing
4228 =======================================================================================================================
4229 =======================================================================================================================
4231 void CXYWnd::UndoClear() {
4232 /* CleanList(&g_brUndo); */
4236 =======================================================================================================================
4237 =======================================================================================================================
4239 void CXYWnd::UndoCopy() {
4241 * CleanList(&g_brUndo); for (brush_t* pBrush = selected_brushes.next ; pBrush !=
4242 * NULL && pBrush != &selected_brushes ; pBrush=pBrush->next) { brush_t* pClone =
4243 * Brush_Clone(pBrush); pClone->pUndoOwner = pBrush->owner; Brush_AddToList
4244 * (pClone, &g_brUndo); }
4249 =======================================================================================================================
4250 =======================================================================================================================
4252 bool CXYWnd::UndoAvailable() {
4253 return(g_brUndo.next != &g_brUndo);
4257 =======================================================================================================================
4258 =======================================================================================================================
4260 void CXYWnd::Paste()
4264 CWaitCursor WaitCursor;
4265 bool bPasted = false;
4266 UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
4267 if (nClipboard > 0 && OpenClipboard() && ::IsClipboardFormatAvailable(nClipboard)) {
4268 HANDLE h = ::GetClipboardData(nClipboard);
4270 g_Clipboard.SetLength(0);
4272 unsigned char *cp = reinterpret_cast < unsigned char * > (::GlobalLock(h));
4274 memcpy(&lSize, cp, sizeof (long));
4275 cp += sizeof (long);
4276 g_Clipboard.Write(cp, lSize);
4283 if (g_Clipboard.GetLength() > 0) {
4284 g_Clipboard.SeekToBegin();
4286 int nLen = g_Clipboard.GetLength();
4287 char *pBuffer = new char[nLen + 1];
4288 memset(pBuffer, 0, sizeof(pBuffer));
4289 g_Clipboard.Read(pBuffer, nLen);
4290 pBuffer[nLen] = '\0';
4291 Map_ImportBuffer(pBuffer, !(GetAsyncKeyState(VK_SHIFT) & 0x8000));
4296 if (g_PatchClipboard.GetLength() > 0) {
4297 g_PatchClipboard.SeekToBegin();
4299 int nLen = g_PatchClipboard.GetLength();
4300 char *pBuffer = new char[nLen + 1];
4301 g_PatchClipboard.Read(pBuffer, nLen);
4302 pBuffer[nLen] = '\0';
4303 Patch_ReadBuffer(pBuffer, true);
4308 if (g_brClipboard.next != &g_brClipboard || g_enClipboard.next != &g_enClipboard) {
4311 for (brush_t * pBrush = g_brClipboard.next; pBrush != NULL && pBrush != &g_brClipboard; pBrush = pBrush->next) {
4312 brush_t *pClone = Brush_Clone(pBrush);
4314 // pClone->owner = pBrush->owner;
4315 if (pClone->owner == NULL) {
4316 Entity_LinkBrush(world_entity, pClone);
4319 Brush_AddToList(pClone, &selected_brushes);
4320 Brush_Build(pClone);
4325 entity_t * pEntity = g_enClipboard.next;
4326 pEntity != NULL && pEntity != &g_enClipboard;
4327 pEntity = pEntity->next
4329 entity_t *pEClone = Entity_Clone(pEntity);
4330 for (brush_t * pEB = pEntity->brushes.onext; pEB != &pEntity->brushes; pEB = pEB->onext) {
4331 brush_t *pClone = Brush_Clone(pEB);
4332 Brush_AddToList(pClone, &selected_brushes);
4333 Entity_LinkBrush(pEClone, pClone);
4334 Brush_Build(pClone);
4335 if (pClone->owner && pClone->owner != world_entity) {
4336 g_Inspectors->UpdateEntitySel(pClone->owner->eclass);
4341 Sys_UpdateWindows(W_ALL);
4344 common->Printf("Nothing to paste.../n");
4350 =======================================================================================================================
4351 =======================================================================================================================
4353 idVec3 &CXYWnd::Rotation() {
4358 =======================================================================================================================
4359 =======================================================================================================================
4361 idVec3 &CXYWnd::RotateOrigin() {
4362 return g_vRotateOrigin;
4366 =======================================================================================================================
4367 =======================================================================================================================
4369 void CXYWnd::OnTimer(UINT nIDEvent) {
4370 if (nIDEvent == 100) {
4371 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
4372 int nDim2 = (m_nViewType == XY) ? 1 : 2;
4373 m_vOrigin[nDim1] += m_ptDragAdj.x / m_fScale;
4374 m_vOrigin[nDim2] -= m_ptDragAdj.y / m_fScale;
4375 Sys_UpdateWindows(W_XY | W_CAMERA);
4377 // int nH = (m_ptDrag.y == 0) ? -1 : m_ptDrag.y;
4378 m_ptDrag += m_ptDragAdj;
4379 m_ptDragTotal += m_ptDragAdj;
4380 XY_MouseMoved(m_ptDrag.x, m_nHeight - 1 - m_ptDrag.y, m_nScrollFlags);
4383 // m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale; m_vOrigin[nDim1] -= m_ptDrag.x /
4390 =======================================================================================================================
4391 =======================================================================================================================
4393 void CXYWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
4394 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
4396 // CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
4400 =======================================================================================================================
4401 =======================================================================================================================
4403 void CXYWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR *lpncsp) {
4404 CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
4408 =======================================================================================================================
4409 =======================================================================================================================
4411 void CXYWnd::OnKillFocus(CWnd *pNewWnd) {
4412 CWnd::OnKillFocus(pNewWnd);
4413 SendMessage(WM_NCACTIVATE, FALSE, 0);
4417 =======================================================================================================================
4418 =======================================================================================================================
4420 void CXYWnd::OnSetFocus(CWnd *pOldWnd) {
4421 CWnd::OnSetFocus(pOldWnd);
4422 SendMessage(WM_NCACTIVATE, TRUE, 0);
4426 =======================================================================================================================
4427 =======================================================================================================================
4429 void CXYWnd::OnClose() {
4434 // =======================================================================================================================
4435 // should be static as should be the rotate scale stuff
4436 // =======================================================================================================================
4438 bool CXYWnd::AreaSelectOK() {
4439 return RotateMode() ? false : ScaleMode() ? false : true;
4443 =======================================================================================================================
4444 =======================================================================================================================
4446 BOOL CXYWnd::OnEraseBkgnd(CDC *pDC) {
4449 // return CWnd::OnEraseBkgnd(pDC);
4452 extern void AssignModel();
4453 void CXYWnd::OnDropNewmodel()
4456 GetCursorPos(&point);
4457 CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, "func_static");
4458 g_Inspectors->SetMode(W_ENTITY);
4459 g_Inspectors->AssignModel();
4462 BOOL CXYWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
4465 g_pParentWnd->OnViewZoomin();
4467 g_pParentWnd->OnViewZoomout();
4475 //---------------------------------------------------------------------------
4476 // CyclePrecisionCrosshairMode
4478 // Called when the user presses the "cycle precision cursor mode" key.
4479 // Cycles the precision cursor among the following three modes:
4480 // PRECISION_CURSOR_NONE
4481 // PRECISION_CURSOR_SNAP
4482 // PRECISION_CURSOR_FREE
4483 //---------------------------------------------------------------------------
4484 void CXYWnd::CyclePrecisionCrosshairMode( void )
4486 common->Printf("TODO: Make DrawPrecisionCrosshair work..." );
4488 /// Cycle to next mode, wrap if necessary
4489 m_precisionCrosshairMode ++;
4490 if( m_precisionCrosshairMode >= PRECISION_CROSSHAIR_MAX )
4491 m_precisionCrosshairMode = PRECISION_CROSSHAIR_NONE;
4492 Sys_UpdateWindows( W_XY );
4495 //---------------------------------------------------------------------------
4496 // DrawPrecisionCrosshair
4498 // Draws a precision crosshair beneath the cursor in the 2d (XY) view,
4499 // depending on one of the following values for m_precisionCrosshairMode:
4501 // PRECISION_CROSSHAIR_NONE No crosshair is drawn. Do not force refresh of XY view.
4502 // PRECISION_CROSSHAIR_SNAP Crosshair snaps to grid size. Force refresh of XY view.
4503 // PRECISION_CROSSHAIR_FREE Crosshair does not snap to grid. Force refresh of XY view.
4504 //---------------------------------------------------------------------------
4505 void CXYWnd::DrawPrecisionCrosshair( void )
4507 // FIXME: m_mouseX, m_mouseY, m_axisHoriz, m_axisVert, etc... are never set
4510 idVec3 mouse3dPos (0.0f, 0.0f, 0.0f);
4512 idVec4 crossEndColor (1.0f, 0.0f, 1.0f, 1.0f); // the RGBA color of the precision crosshair at its ends
4513 idVec4 crossMidColor; // the RGBA color of the precision crosshair at the crossing point
4515 /// Transform the mouse coordinates into axis-correct map-coordinates
4516 if( m_precisionCrosshairMode == PRECISION_CROSSHAIR_SNAP )
4517 SnapToPoint( m_mouseX, m_mouseY, mouse3dPos );
4519 XY_ToPoint( m_mouseX, m_mouseY, mouse3dPos );
4520 x = mouse3dPos[ m_axisHoriz ];
4521 y = mouse3dPos[ m_axisVert ];
4523 /// Use the color specified by the user
4525 crossEndColor[0] = g_qeglobals.d_savedinfo.colors[ COLOR_PRECISION_CROSSHAIR ][0];
4526 crossEndColor[1] = g_qeglobals.d_savedinfo.colors[ COLOR_PRECISION_CROSSHAIR ][1];
4527 crossEndColor[2] = g_qeglobals.d_savedinfo.colors[ COLOR_PRECISION_CROSSHAIR ][2];
4528 crossEndColor[3] = 1.0f;
4530 crossMidColor = crossEndColor;
4532 if( m_precisionCrosshairMode == PRECISION_CROSSHAIR_FREE )
4533 crossMidColor[ 3 ] = 0.0f; // intersection-color is 100% transparent (alpha = 0.0f)
4535 /// Set up OpenGL states (for drawing smooth-shaded plain-colored lines)
4536 qglEnable( GL_BLEND );
4537 qglDisable( GL_TEXTURE_2D );
4538 qglShadeModel( GL_SMOOTH );
4539 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
4541 /// Draw a fullscreen-sized crosshair over the cursor
4542 qglBegin( GL_LINES );
4544 /// Draw the horizontal precision line (in two pieces)
4545 qglColor4fv( crossEndColor.ToFloatPtr() );
4546 qglVertex2f( m_mcLeft, y );
4547 qglColor4fv( crossMidColor.ToFloatPtr() );
4548 qglVertex2f( x, y );
4549 qglColor4fv( crossMidColor.ToFloatPtr() );
4550 qglVertex2f( x, y );
4551 qglColor4fv( crossEndColor.ToFloatPtr() );
4552 qglVertex2f( m_mcRight, y );
4554 /// Draw the vertical precision line (in two pieces)
4555 qglColor4fv( crossEndColor.ToFloatPtr() );
4556 qglVertex2f( x, m_mcTop );
4557 qglColor4fv( crossMidColor.ToFloatPtr() );
4558 qglVertex2f( x, y );
4559 qglColor4fv( crossMidColor.ToFloatPtr() );
4560 qglVertex2f( x, y );
4561 qglColor4fv( crossEndColor.ToFloatPtr() );
4562 qglVertex2f( x, m_mcBottom );
4564 qglEnd(); // GL_LINES
4566 // Radiant was in opaque, flat-shaded mode by default; restore this to prevent possible slowdown
4567 qglShadeModel( GL_FLAT );
4568 qglDisable( GL_BLEND );