XYWnd.cpp (89114B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 // XYWnd.cpp : implementation file 23 // 24 // QERadiant 25 // 26 // 27 28 #include "stdafx.h" 29 #include "Radiant.h" 30 #include "XYWnd.h" 31 #include "qe3.h" 32 #include "PrefsDlg.h" 33 #include "DialogInfo.h" 34 #include "splines/splines.h" 35 36 #ifdef _DEBUG 37 #define new DEBUG_NEW 38 #undef THIS_FILE 39 static char THIS_FILE[] = __FILE__; 40 #endif 41 42 #define PAGEFLIPS 2 43 44 45 const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"}; 46 const char* g_pOrgStrings[] = {"(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)"}; 47 CString g_strDim; 48 CString g_strStatus; 49 50 bool g_bCrossHairs = false; 51 bool g_bScaleMode; 52 int g_nScaleHow; 53 bool g_bRotateMode; 54 bool g_bClipMode; 55 bool g_bRogueClipMode; 56 bool g_bSwitch; 57 CClipPoint g_Clip1; 58 CClipPoint g_Clip2; 59 CClipPoint g_Clip3; 60 CClipPoint* g_pMovingClip; 61 brush_t g_brFrontSplits; 62 brush_t g_brBackSplits; 63 64 brush_t g_brClipboard; 65 brush_t g_brUndo; 66 entity_t g_enClipboard; 67 68 vec3_t g_vRotateOrigin; 69 vec3_t g_vRotation; 70 71 bool g_bPathMode; 72 CClipPoint g_PathPoints[256]; 73 CClipPoint* g_pMovingPath; 74 int g_nPathCount; 75 int g_nPathLimit; 76 77 bool g_bSmartGo; 78 79 bool g_bPointMode; 80 CClipPoint g_PointPoints[512]; 81 CClipPoint* g_pMovingPoint; 82 int g_nPointCount; 83 int g_nPointLimit; 84 85 86 const int XY_LEFT = 0x01; 87 const int XY_RIGHT = 0x02; 88 const int XY_UP = 0x04; 89 const int XY_DOWN = 0x08; 90 91 PFNPathCallback* g_pPathFunc = NULL; 92 93 void AcquirePath(int nCount, PFNPathCallback* pFunc) 94 { 95 g_nPathCount = 0; 96 g_nPathLimit = nCount; 97 g_pPathFunc = pFunc; 98 g_bPathMode = true; 99 } 100 101 102 CPtrArray g_ptrMenus; 103 104 CMemFile g_Clipboard(4096); 105 CMemFile g_PatchClipboard(4096); 106 107 extern int pressx; 108 extern int pressy; 109 110 111 ///////////////////////////////////////////////////////////////////////////// 112 // CXYWnd 113 114 IMPLEMENT_DYNCREATE(CXYWnd, CWnd); 115 116 CXYWnd::CXYWnd() 117 { 118 g_brClipboard.next = &g_brClipboard; 119 g_brUndo.next = &g_brUndo; 120 g_nScaleHow = 0; 121 g_bRotateMode = false; 122 g_bClipMode = false; 123 g_bRogueClipMode = false; 124 g_bSwitch = true; 125 g_pMovingClip = NULL; 126 g_pMovingPath = NULL; 127 g_brFrontSplits.next = &g_brFrontSplits; 128 g_brBackSplits.next = &g_brBackSplits; 129 m_bActive = false; 130 //m_bTiming = true; 131 m_bTiming = false; 132 m_bRButtonDown = false; 133 m_nUpdateBits = W_XY; 134 g_bPathMode = false; 135 g_nPathCount = 0; 136 g_nPathLimit = 0; 137 m_nTimerID = -1; 138 XY_Init(); 139 } 140 141 CXYWnd::~CXYWnd() 142 { 143 int nSize = g_ptrMenus.GetSize(); 144 while (nSize > 0) 145 { 146 CMenu* pMenu = reinterpret_cast<CMenu*>(g_ptrMenus.GetAt(nSize-1)); 147 ASSERT(pMenu); 148 pMenu->DestroyMenu(); 149 delete pMenu; 150 nSize--; 151 } 152 g_ptrMenus.RemoveAll(); 153 m_mnuDrop.DestroyMenu(); 154 } 155 156 157 BEGIN_MESSAGE_MAP(CXYWnd, CWnd) 158 //{{AFX_MSG_MAP(CXYWnd) 159 ON_WM_CREATE() 160 ON_WM_LBUTTONDOWN() 161 ON_WM_MBUTTONDOWN() 162 ON_WM_RBUTTONDOWN() 163 ON_WM_LBUTTONUP() 164 ON_WM_MBUTTONUP() 165 ON_WM_RBUTTONUP() 166 ON_WM_MOUSEMOVE() 167 ON_WM_PAINT() 168 ON_WM_KEYDOWN() 169 ON_WM_SIZE() 170 ON_WM_DESTROY() 171 ON_COMMAND(ID_SELECT_MOUSEROTATE, OnSelectMouserotate) 172 ON_WM_TIMER() 173 ON_WM_KEYUP() 174 ON_WM_NCCALCSIZE() 175 ON_WM_KILLFOCUS() 176 ON_WM_SETFOCUS() 177 ON_WM_CLOSE() 178 ON_COMMAND(ID_SELECTION_MAKE_DETAIL, CMainFrame::OnSelectionMakeDetail) 179 ON_COMMAND(ID_SELECTION_MAKE_STRUCTURAL, CMainFrame::OnSelectionMakeStructural) 180 ON_COMMAND(ID_SELECTION_SELECTCOMPLETETALL, CMainFrame::OnSelectionSelectcompletetall) 181 ON_COMMAND(ID_SELECTION_SELECTINSIDE, CMainFrame::OnSelectionSelectinside) 182 ON_COMMAND(ID_SELECTION_SELECTPARTIALTALL, CMainFrame::OnSelectionSelectpartialtall) 183 ON_COMMAND(ID_SELECTION_SELECTTOUCHING, CMainFrame::OnSelectionSelecttouching) 184 ON_COMMAND(ID_SELECTION_UNGROUPENTITY, CMainFrame::OnSelectionUngroupentity) 185 //}}AFX_MSG_MAP 186 ON_COMMAND_RANGE(ID_ENTITY_START, ID_ENTITY_END, OnEntityCreate) 187 END_MESSAGE_MAP() 188 189 190 ///////////////////////////////////////////////////////////////////////////// 191 // CXYWnd message handlers 192 LONG WINAPI XYWndProc(HWND, UINT, WPARAM, LPARAM); 193 BOOL CXYWnd::PreCreateWindow(CREATESTRUCT& cs) 194 { 195 WNDCLASS wc; 196 HINSTANCE hInstance = AfxGetInstanceHandle(); 197 if (::GetClassInfo(hInstance, XY_WINDOW_CLASS, &wc) == FALSE) 198 { 199 // Register a new class 200 memset (&wc, 0, sizeof(wc)); 201 wc.style = CS_NOCLOSE | CS_OWNDC; 202 wc.lpszClassName = XY_WINDOW_CLASS; 203 wc.hCursor = NULL; //LoadCursor (NULL,IDC_ARROW); 204 wc.lpfnWndProc = ::DefWindowProc; 205 if (AfxRegisterClass(&wc) == FALSE) 206 Error ("CCamWnd RegisterClass: failed"); 207 } 208 209 cs.lpszClass = XY_WINDOW_CLASS; 210 cs.lpszName = "VIEW"; 211 if (cs.style != QE3_CHILDSTYLE) 212 cs.style = QE3_SPLITTER_STYLE; 213 214 return CWnd::PreCreateWindow(cs); 215 } 216 217 HDC s_hdcXY; 218 HGLRC s_hglrcXY; 219 220 static unsigned s_stipple[32] = 221 { 222 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 223 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 224 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 225 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 226 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 227 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 228 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 229 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555, 230 }; 231 232 /* 233 ============ 234 WXY_WndProc 235 ============ 236 */ 237 LONG WINAPI XYWndProc ( 238 HWND hWnd, 239 UINT uMsg, 240 WPARAM wParam, 241 LPARAM lParam) 242 { 243 switch (uMsg) 244 { 245 case WM_DESTROY: 246 QEW_StopGL( hWnd, s_hglrcXY, s_hdcXY ); 247 return 0; 248 249 case WM_NCCALCSIZE:// don't let windows copy pixels 250 DefWindowProc (hWnd, uMsg, wParam, lParam); 251 return WVR_REDRAW; 252 253 case WM_KILLFOCUS: 254 case WM_SETFOCUS: 255 SendMessage( hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0 ); 256 return 0; 257 258 case WM_CLOSE: 259 DestroyWindow (hWnd); 260 return 0; 261 } 262 263 return DefWindowProc (hWnd, uMsg, wParam, lParam); 264 } 265 266 267 static void WXY_InitPixelFormat( PIXELFORMATDESCRIPTOR *pPFD ) 268 { 269 memset( pPFD, 0, sizeof( *pPFD ) ); 270 271 pPFD->nSize = sizeof( PIXELFORMATDESCRIPTOR ); 272 pPFD->nVersion = 1; 273 pPFD->dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; 274 pPFD->iPixelType = PFD_TYPE_RGBA; 275 pPFD->cColorBits = 24; 276 pPFD->cDepthBits = 32; 277 pPFD->iLayerType = PFD_MAIN_PLANE; 278 279 } 280 281 void WXY_Print( void ) 282 { 283 DOCINFO di; 284 285 PRINTDLG pd; 286 287 /* 288 ** initialize the PRINTDLG struct and execute it 289 */ 290 memset( &pd, 0, sizeof( pd ) ); 291 pd.lStructSize = sizeof( pd ); 292 pd.hwndOwner = g_qeglobals.d_hwndXY; 293 pd.Flags = PD_RETURNDC; 294 pd.hInstance = 0; 295 if ( !PrintDlg( &pd ) || !pd.hDC ) 296 { 297 MessageBox( g_qeglobals.d_hwndMain, "Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR ); 298 return; 299 } 300 301 /* 302 ** StartDoc 303 */ 304 memset( &di, 0, sizeof( di ) ); 305 di.cbSize = sizeof( di ); 306 di.lpszDocName = "QE4"; 307 if ( StartDoc( pd.hDC, &di ) <= 0 ) 308 { 309 MessageBox( g_qeglobals.d_hwndMain, "Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR ); 310 return; 311 } 312 313 /* 314 ** StartPage 315 */ 316 if ( StartPage( pd.hDC ) <= 0 ) 317 { 318 MessageBox( g_qeglobals.d_hwndMain, "Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR ); 319 return; 320 } 321 322 /* 323 ** read pixels from the XY window 324 */ 325 { 326 int bmwidth = 320, bmheight = 320; 327 int pwidth, pheight; 328 329 RECT r; 330 331 GetWindowRect( g_qeglobals.d_hwndXY, &r ); 332 333 bmwidth = r.right - r.left; 334 bmheight = r.bottom - r.top; 335 336 pwidth = GetDeviceCaps( pd.hDC, PHYSICALWIDTH ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETX ); 337 pheight = GetDeviceCaps( pd.hDC, PHYSICALHEIGHT ) - GetDeviceCaps( pd.hDC, PHYSICALOFFSETY ); 338 339 StretchBlt( pd.hDC, 340 0, 0, 341 pwidth, pheight, 342 s_hdcXY, 343 0, 0, 344 bmwidth, bmheight, 345 SRCCOPY ); 346 } 347 348 /* 349 ** EndPage and EndDoc 350 */ 351 if ( EndPage( pd.hDC ) <= 0 ) 352 { 353 MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR ); 354 return; 355 } 356 357 if ( EndDoc( pd.hDC ) <= 0 ) 358 { 359 MessageBox( g_qeglobals.d_hwndMain, "QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR ); 360 return; 361 } 362 } 363 364 int CXYWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 365 { 366 if (CWnd::OnCreate(lpCreateStruct) == -1) 367 return -1; 368 369 s_hdcXY = ::GetDC(GetSafeHwnd()); 370 QEW_SetupPixelFormat(s_hdcXY, false); 371 if ( ( s_hglrcXY = qwglCreateContext( s_hdcXY ) ) == 0 ) 372 Error( "wglCreateContext in WXY_WndProc failed" ); 373 374 if (!qwglShareLists( g_qeglobals.d_hglrcBase, s_hglrcXY ) ) 375 Error( "wglShareLists in WXY_WndProc failed" ); 376 377 if (!qwglMakeCurrent( s_hdcXY, s_hglrcXY )) 378 Error ("wglMakeCurrent failed"); 379 380 qglPolygonStipple ((unsigned char *)s_stipple); 381 qglLineStipple (3, 0xaaaa); 382 g_qeglobals.d_hwndXY = GetSafeHwnd(); 383 return 0; 384 } 385 386 float ptSum(vec3_t pt) 387 { 388 return pt[0] + pt[1] + pt[2]; 389 } 390 391 void CXYWnd::DropClipPoint(UINT nFlags, CPoint point) 392 { 393 CRect rctZ; 394 GetClientRect(rctZ); 395 if (g_pMovingClip) 396 { 397 SetCapture(); 398 SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *g_pMovingClip); 399 } 400 else 401 { 402 vec3_t* pPt = NULL; 403 if (g_Clip1.Set() == false) 404 { 405 pPt = g_Clip1; 406 g_Clip1.Set(true); 407 g_Clip1.m_ptScreen = point; 408 } 409 else 410 if (g_Clip2.Set() == false) 411 { 412 pPt = g_Clip2; 413 g_Clip2.Set(true); 414 g_Clip2.m_ptScreen = point; 415 } 416 else 417 if (g_Clip3.Set() == false) 418 { 419 pPt = g_Clip3; 420 g_Clip3.Set(true); 421 g_Clip3.m_ptScreen = point; 422 } 423 else 424 { 425 RetainClipMode(true); 426 pPt = g_Clip1; 427 g_Clip1.Set(true); 428 g_Clip1.m_ptScreen = point; 429 } 430 SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *pPt); 431 } 432 Sys_UpdateWindows(XY | W_CAMERA_IFON); 433 } 434 435 436 void CXYWnd::DropPathPoint(UINT nFlags, CPoint point) 437 { 438 CRect rctZ; 439 GetClientRect(rctZ); 440 if (g_pMovingPath) 441 { 442 SetCapture(); 443 SnapToPoint (point.x, rctZ.Height() - 1 - point.y , *g_pMovingPath); 444 } 445 else 446 { 447 g_PathPoints[g_nPathCount].Set(true); 448 g_PathPoints[g_nPathCount].m_ptScreen = point; 449 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, g_PathPoints[g_nPathCount]); 450 g_nPathCount++; 451 if (g_nPathCount == g_nPathLimit) 452 { 453 if (g_pPathFunc) 454 g_pPathFunc(true, g_nPathCount); 455 g_nPathCount = 0; 456 g_bPathMode = false; 457 g_pPathFunc = NULL; 458 } 459 } 460 Sys_UpdateWindows(XY | W_CAMERA_IFON); 461 } 462 463 void CXYWnd::AddPointPoint(UINT nFlags, vec3_t* pVec) 464 { 465 g_PointPoints[g_nPointCount].Set(true); 466 //g_PointPoints[g_nPointCount].m_ptScreen = point; 467 _VectorCopy(*pVec, g_PointPoints[g_nPointCount]); 468 g_PointPoints[g_nPointCount].SetPointPtr(pVec); 469 g_nPointCount++; 470 Sys_UpdateWindows(XY | W_CAMERA_IFON); 471 } 472 473 474 void CXYWnd::OnLButtonDown(UINT nFlags, CPoint point) 475 { 476 g_pParentWnd->SetActiveXY(this); 477 UndoCopy(); 478 479 // plugin entities 480 if (DispatchOnLButtonDown(nFlags, point.x, point.y )) 481 return; 482 483 if (ClipMode() && !RogueClipMode()) 484 { 485 DropClipPoint(nFlags, point); 486 } 487 else if (PathMode()) 488 { 489 DropPathPoint(nFlags, point); 490 } 491 else OriginalButtonDown(nFlags, point); 492 } 493 494 void CXYWnd::OnMButtonDown(UINT nFlags, CPoint point) 495 { 496 OriginalButtonDown(nFlags, point); 497 } 498 499 500 float Betwixt(float f1, float f2) 501 { 502 if (f1 > f2) 503 return f2 + ((f1 - f2) / 2); 504 else 505 return f1 + ((f2 - f1) / 2); 506 } 507 508 void CXYWnd::ProduceSplits(brush_t** pFront, brush_t** pBack) 509 { 510 *pFront = NULL; 511 *pBack = NULL; 512 if (ClipMode()) 513 { 514 if (g_Clip1.Set() && g_Clip2.Set()) 515 { 516 face_t face; 517 VectorCopy(g_Clip1.m_ptClip,face.planepts[0]); 518 VectorCopy(g_Clip2.m_ptClip,face.planepts[1]); 519 VectorCopy(g_Clip3.m_ptClip,face.planepts[2]); 520 if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes)) 521 { 522 if (g_Clip3.Set() == false) 523 { 524 if (m_nViewType == XY) 525 { 526 face.planepts[0][2] = selected_brushes.next->mins[2]; 527 face.planepts[1][2] = selected_brushes.next->mins[2]; 528 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]); 529 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]); 530 face.planepts[2][2] = selected_brushes.next->maxs[2]; 531 } 532 else if (m_nViewType == YZ) 533 { 534 face.planepts[0][0] = selected_brushes.next->mins[0]; 535 face.planepts[1][0] = selected_brushes.next->mins[0]; 536 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]); 537 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]); 538 face.planepts[2][0] = selected_brushes.next->maxs[0]; 539 } 540 else 541 { 542 face.planepts[0][1] = selected_brushes.next->mins[1]; 543 face.planepts[1][1] = selected_brushes.next->mins[1]; 544 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]); 545 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]); 546 face.planepts[2][1] = selected_brushes.next->maxs[1]; 547 } 548 } 549 550 Brush_SplitBrushByFace (selected_brushes.next, &face, pFront, pBack); 551 } 552 553 } 554 } 555 } 556 557 void CleanList(brush_t* pList) 558 { 559 brush_t* pBrush = pList->next; 560 while (pBrush != NULL && pBrush != pList) 561 { 562 brush_t* pNext = pBrush->next; 563 Brush_Free(pBrush); 564 pBrush = pNext; 565 } 566 } 567 568 void CXYWnd::ProduceSplitLists() 569 { 570 if (AnyPatchesSelected()) 571 { 572 Sys_Printf("Deslecting patches for clip operation.\n"); 573 brush_t *next; 574 for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = next) 575 { 576 next = pb->next; 577 if (pb->patchBrush) 578 { 579 Brush_RemoveFromList (pb); 580 Brush_AddToList (pb, &active_brushes); 581 UpdatePatchInspector(); 582 } 583 if (pb->terrainBrush) 584 { 585 Brush_RemoveFromList (pb); 586 Brush_AddToList (pb, &active_brushes); 587 UpdateTerrainInspector(); 588 } 589 } 590 } 591 592 CleanList(&g_brFrontSplits); 593 CleanList(&g_brBackSplits); 594 g_brFrontSplits.next = &g_brFrontSplits; 595 g_brBackSplits.next = &g_brBackSplits; 596 brush_t* pBrush; 597 for (pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next) 598 { 599 brush_t* pFront = NULL; 600 brush_t* pBack = NULL; 601 if (ClipMode()) 602 { 603 if (g_Clip1.Set() && g_Clip2.Set()) 604 { 605 face_t face; 606 VectorCopy(g_Clip1.m_ptClip,face.planepts[0]); 607 VectorCopy(g_Clip2.m_ptClip,face.planepts[1]); 608 VectorCopy(g_Clip3.m_ptClip,face.planepts[2]); 609 if (g_Clip3.Set() == false) 610 { 611 if (g_pParentWnd->ActiveXY()->GetViewType() == XY) 612 { 613 face.planepts[0][2] = pBrush->mins[2]; 614 face.planepts[1][2] = pBrush->mins[2]; 615 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]); 616 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]); 617 face.planepts[2][2] = pBrush->maxs[2]; 618 } 619 else if (g_pParentWnd->ActiveXY()->GetViewType() == YZ) 620 { 621 face.planepts[0][0] = pBrush->mins[0]; 622 face.planepts[1][0] = pBrush->mins[0]; 623 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]); 624 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]); 625 face.planepts[2][0] = pBrush->maxs[0]; 626 } 627 else 628 { 629 face.planepts[0][1] = pBrush->mins[1]; 630 face.planepts[1][1] = pBrush->mins[1]; 631 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]); 632 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]); 633 face.planepts[2][1] = pBrush->maxs[1]; 634 } 635 } 636 Brush_SplitBrushByFace (pBrush, &face, &pFront, &pBack); 637 if (pBack) 638 Brush_AddToList(pBack, &g_brBackSplits); 639 if (pFront) 640 Brush_AddToList(pFront, &g_brFrontSplits); 641 } 642 } 643 } 644 } 645 646 void Brush_CopyList (brush_t* pFrom, brush_t* pTo) 647 { 648 brush_t* pBrush = pFrom->next; 649 while (pBrush != NULL && pBrush != pFrom) 650 { 651 brush_t* pNext = pBrush->next; 652 Brush_RemoveFromList(pBrush); 653 Brush_AddToList(pBrush, pTo); 654 pBrush = pNext; 655 } 656 } 657 658 void CXYWnd::OnRButtonDown(UINT nFlags, CPoint point) 659 { 660 g_pParentWnd->SetActiveXY(this); 661 m_ptDown = point; 662 m_bRButtonDown = true; 663 664 if (g_PrefsDlg.m_nMouseButtons == 3) // 3 button mouse 665 { 666 if ((GetKeyState(VK_CONTROL) & 0x8000)) 667 { 668 if (ClipMode()) // already there? 669 DropClipPoint(nFlags, point); 670 else 671 { 672 SetClipMode(true); 673 g_bRogueClipMode = true; 674 DropClipPoint(nFlags, point); 675 } 676 return; 677 } 678 } 679 OriginalButtonDown(nFlags, point); 680 } 681 682 void CXYWnd::OnLButtonUp(UINT nFlags, CPoint point) 683 { 684 // plugin entities 685 if (DispatchOnLButtonUp(nFlags, point.x, point.y )) 686 return; 687 688 if (ClipMode()) 689 { 690 if (g_pMovingClip) 691 { 692 ReleaseCapture(); 693 g_pMovingClip = NULL; 694 } 695 } 696 OriginalButtonUp(nFlags, point); 697 } 698 699 void CXYWnd::OnMButtonUp(UINT nFlags, CPoint point) 700 { 701 OriginalButtonUp(nFlags, point); 702 } 703 704 void CXYWnd::OnRButtonUp(UINT nFlags, CPoint point) 705 { 706 m_bRButtonDown = false; 707 if (point == m_ptDown) // mouse didn't move 708 { 709 bool bGo = true; 710 if ((GetKeyState(VK_MENU) & 0x8000)) 711 bGo = false; 712 if ((GetKeyState(VK_CONTROL) & 0x8000)) 713 bGo = false; 714 if ((GetKeyState(VK_SHIFT) & 0x8000)) 715 bGo = false; 716 if (bGo) 717 HandleDrop(); 718 } 719 OriginalButtonUp(nFlags, point); 720 } 721 722 void CXYWnd::OriginalButtonDown(UINT nFlags, CPoint point) 723 { 724 CRect rctZ; 725 GetClientRect(rctZ); 726 SetWindowPos(&wndTop, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); 727 if (::GetTopWindow( g_qeglobals.d_hwndMain ) != GetSafeHwnd()) 728 ::BringWindowToTop(GetSafeHwnd()); 729 SetFocus(); 730 SetCapture(); 731 XY_MouseDown (point.x, rctZ.Height() - 1 - point.y , nFlags); 732 m_nScrollFlags = nFlags; 733 } 734 735 void CXYWnd::OriginalButtonUp(UINT nFlags, CPoint point) 736 { 737 CRect rctZ; 738 GetClientRect(rctZ); 739 XY_MouseUp (point.x, rctZ.Height() - 1 - point.y , nFlags); 740 if (! (nFlags & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON))) 741 ReleaseCapture (); 742 } 743 744 745 float fDiff(float f1, float f2) 746 { 747 if (f1 > f2) 748 return f1 - f2; 749 else 750 return f2 - f1; 751 } 752 753 754 vec3_t tdp; 755 void CXYWnd::OnMouseMove(UINT nFlags, CPoint point) 756 { 757 // plugin entities 758 //++timo TODO: handle return code 759 DispatchOnMouseMove( nFlags, point.x, point.y ); 760 761 m_ptDown.x = 0; 762 m_ptDown.y = 0; 763 764 if ( g_PrefsDlg.m_bChaseMouse == TRUE && 765 (point.x < 0 || point.y < 0 || 766 point.x > m_nWidth || point.y > m_nHeight) && 767 GetCapture() == this) 768 { 769 float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale; 770 //m_ptDrag = point; 771 m_ptDragAdj.x = 0; 772 m_ptDragAdj.y = 0; 773 if (point.x < 0) 774 { 775 m_ptDragAdj.x = -fAdjustment; 776 } 777 else 778 if (point.x > m_nWidth) 779 { 780 m_ptDragAdj.x = fAdjustment; 781 } 782 if (point.y < 0) 783 { 784 m_ptDragAdj.y = -fAdjustment; 785 } 786 else 787 if (point.y > m_nHeight) 788 { 789 m_ptDragAdj.y = fAdjustment; 790 } 791 if (m_nTimerID == -1) 792 { 793 m_nTimerID = SetTimer(100, 50, NULL); 794 m_ptDrag = point; 795 m_ptDragTotal = 0; 796 } 797 return; 798 } 799 //else if (m_nTimerID != -1) 800 if (m_nTimerID != -1) 801 { 802 KillTimer(m_nTimerID); 803 pressx -= m_ptDragTotal.x; 804 pressy += m_ptDragTotal.y; 805 m_nTimerID = -1; 806 //return; 807 } 808 809 bool bCrossHair = false; 810 if (!m_bRButtonDown) 811 { 812 tdp[0] = tdp[1] = tdp[2] = 0.0; 813 SnapToPoint (point.x, m_nHeight - 1 - point.y , tdp); 814 815 g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]); 816 g_pParentWnd->SetStatusText(1, g_strStatus); 817 818 // i need to generalize the point code.. having 3 flavors pretty much sucks.. 819 // once the new curve stuff looks like it is going to stick i will 820 // rationalize this down to a single interface.. 821 if (PointMode()) 822 { 823 if (g_pMovingPoint && GetCapture() == this) 824 { 825 bCrossHair = true; 826 SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingPoint->m_ptClip); 827 g_pMovingPoint->UpdatePointPtr(); 828 Sys_UpdateWindows(XY | W_CAMERA_IFON); 829 } 830 else 831 { 832 g_pMovingPoint = NULL; 833 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 834 int nDim2 = (m_nViewType == XY) ? 1 : 2; 835 for (int n = 0; n < g_nPointCount; n++) 836 { 837 if ( fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 && 838 fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 ) 839 { 840 bCrossHair = true; 841 g_pMovingPoint = &g_PointPoints[n]; 842 } 843 } 844 } 845 } 846 else if (ClipMode()) 847 { 848 if (g_pMovingClip && GetCapture() == this) 849 { 850 bCrossHair = true; 851 SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingClip->m_ptClip); 852 Sys_UpdateWindows(XY | W_CAMERA_IFON); 853 } 854 else 855 { 856 g_pMovingClip = NULL; 857 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 858 int nDim2 = (m_nViewType == XY) ? 1 : 2; 859 if (g_Clip1.Set()) 860 { 861 if ( fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 && 862 fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3 ) 863 { 864 bCrossHair = true; 865 g_pMovingClip = &g_Clip1; 866 } 867 } 868 if (g_Clip2.Set()) 869 { 870 if ( fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 && 871 fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3 ) 872 { 873 bCrossHair = true; 874 g_pMovingClip = &g_Clip2; 875 } 876 } 877 if (g_Clip3.Set()) 878 { 879 if ( fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 && 880 fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3 ) 881 { 882 bCrossHair = true; 883 g_pMovingClip = &g_Clip3; 884 } 885 } 886 } 887 if (bCrossHair == false) 888 XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags); 889 } 890 else if (PathMode()) 891 { 892 if (g_pMovingPath && GetCapture() == this) 893 { 894 bCrossHair = true; 895 SnapToPoint (point.x, m_nHeight - 1 - point.y , g_pMovingPath->m_ptClip); 896 Sys_UpdateWindows(XY | W_CAMERA_IFON); 897 } 898 else 899 { 900 g_pMovingPath = NULL; 901 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 902 int nDim2 = (m_nViewType == XY) ? 1 : 2; 903 for (int n = 0; n < g_nPathCount; n++) 904 { 905 if ( fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 && 906 fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 ) 907 { 908 bCrossHair = true; 909 g_pMovingPath = &g_PathPoints[n]; 910 } 911 } 912 } 913 } 914 else 915 { 916 XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags); 917 } 918 } 919 else 920 { 921 XY_MouseMoved (point.x, m_nHeight - 1 - point.y , nFlags); 922 } 923 if (bCrossHair) 924 SetCursor(::LoadCursor(NULL, IDC_CROSS)); 925 else 926 SetCursor(::LoadCursor(NULL, IDC_ARROW)); 927 } 928 929 void CXYWnd::RetainClipMode(bool bMode) 930 { 931 bool bSave = g_bRogueClipMode; 932 SetClipMode(bMode); 933 if (bMode == true) 934 g_bRogueClipMode = bSave; 935 else 936 g_bRogueClipMode = false; 937 } 938 939 void CXYWnd::SetClipMode(bool bMode) 940 { 941 g_bClipMode = bMode; 942 g_bRogueClipMode = false; 943 if (bMode) 944 { 945 g_Clip1.Reset(); 946 g_Clip2.Reset(); 947 g_Clip3.Reset(); 948 CleanList(&g_brFrontSplits); 949 CleanList(&g_brBackSplits); 950 g_brFrontSplits.next = &g_brFrontSplits; 951 g_brBackSplits.next = &g_brBackSplits; 952 } 953 else 954 { 955 if (g_pMovingClip) 956 { 957 ReleaseCapture(); 958 g_pMovingClip = NULL; 959 } 960 CleanList(&g_brFrontSplits); 961 CleanList(&g_brBackSplits); 962 g_brFrontSplits.next = &g_brFrontSplits; 963 g_brBackSplits.next = &g_brBackSplits; 964 Sys_UpdateWindows(XY | W_CAMERA_IFON); 965 } 966 } 967 968 bool CXYWnd::ClipMode() 969 { 970 return g_bClipMode; 971 } 972 973 bool CXYWnd::RogueClipMode() 974 { 975 return g_bRogueClipMode; 976 } 977 978 bool CXYWnd::PathMode() 979 { 980 return g_bPathMode; 981 } 982 983 984 bool CXYWnd::PointMode() 985 { 986 return g_bPointMode; 987 } 988 989 void CXYWnd::SetPointMode(bool b) 990 { 991 g_bPointMode = b; 992 if (!b) 993 g_nPointCount = 0; 994 } 995 996 997 void CXYWnd::OnPaint() 998 { 999 CPaintDC dc(this); // device context for painting 1000 bool bPaint = true; 1001 if (!qwglMakeCurrent(dc.m_hDC, s_hglrcXY)) 1002 { 1003 Sys_Printf("ERROR: wglMakeCurrent failed.. Error:%i\n",qglGetError()); 1004 Sys_Printf("Please restart Q3Radiant if the Map view is not working\n"); 1005 bPaint = false; 1006 } 1007 if (bPaint) 1008 { 1009 QE_CheckOpenGLForErrors(); 1010 XY_Draw (); 1011 QE_CheckOpenGLForErrors(); 1012 1013 if (m_nViewType != XY) 1014 { 1015 qglPushMatrix(); 1016 if (m_nViewType == YZ) 1017 qglRotatef (-90, 0, 1, 0); // put Z going up 1018 qglRotatef (-90, 1, 0, 0); // put Z going up 1019 } 1020 1021 if (g_bCrossHairs) 1022 { 1023 qglColor4f(0.2, 0.9, 0.2, 0.8); 1024 qglBegin (GL_LINES); 1025 if (m_nViewType == XY) 1026 { 1027 qglVertex2f(-16384, tdp[1]); 1028 qglVertex2f(16384, tdp[1]); 1029 qglVertex2f(tdp[0], -16384); 1030 qglVertex2f(tdp[0], 16384); 1031 } 1032 else if (m_nViewType == YZ) 1033 { 1034 qglVertex3f(tdp[0], -16384, tdp[2]); 1035 qglVertex3f(tdp[0], 16384, tdp[2]); 1036 qglVertex3f(tdp[0], tdp[1], -16384); 1037 qglVertex3f(tdp[0], tdp[1], 16384); 1038 } 1039 else 1040 { 1041 qglVertex3f(-16384, tdp[1], tdp[2]); 1042 qglVertex3f( 16384, tdp[1], tdp[2]); 1043 qglVertex3f(tdp[0], tdp[1], -16384); 1044 qglVertex3f(tdp[0], tdp[1], 16384); 1045 } 1046 qglEnd(); 1047 } 1048 1049 if (ClipMode()) 1050 { 1051 qglPointSize (4); 1052 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]); 1053 qglBegin (GL_POINTS); 1054 if (g_Clip1.Set()) 1055 qglVertex3fv (g_Clip1); 1056 if (g_Clip2.Set()) 1057 qglVertex3fv (g_Clip2); 1058 if (g_Clip3.Set()) 1059 qglVertex3fv (g_Clip3); 1060 qglEnd (); 1061 qglPointSize (1); 1062 1063 CString strMsg; 1064 if (g_Clip1.Set()) 1065 { 1066 qglRasterPos3f (g_Clip1.m_ptClip[0]+2, g_Clip1.m_ptClip[1]+2, g_Clip1.m_ptClip[2]+2); 1067 strMsg = "1"; 1068 //strMsg.Format("1 (%f, %f, %f)", g_Clip1[0], g_Clip1[1], g_Clip1[2]); 1069 qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg); 1070 } 1071 if (g_Clip2.Set()) 1072 { 1073 qglRasterPos3f (g_Clip2.m_ptClip[0]+2, g_Clip2.m_ptClip[1]+2, g_Clip2.m_ptClip[2]+2); 1074 strMsg = "2"; 1075 //strMsg.Format("2 (%f, %f, %f)", g_Clip2[0], g_Clip2[1], g_Clip2[2]); 1076 qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg); 1077 } 1078 if (g_Clip3.Set()) 1079 { 1080 qglRasterPos3f (g_Clip3.m_ptClip[0]+2, g_Clip3.m_ptClip[1]+2, g_Clip3.m_ptClip[2]+2); 1081 strMsg = "3"; 1082 //strMsg.Format("3 (%f, %f, %f)", g_Clip3[0], g_Clip3[1], g_Clip3[2]); 1083 qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg); 1084 } 1085 if (g_Clip1.Set() && g_Clip2.Set()) 1086 { 1087 ProduceSplitLists(); 1088 brush_t* pBrush; 1089 brush_t* pList = ( (m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits; 1090 for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next) 1091 { 1092 qglColor3f (1,1,0); 1093 face_t *face; 1094 int order; 1095 for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++) 1096 { 1097 winding_t* w = face->face_winding; 1098 if (!w) 1099 continue; 1100 // draw the polygon 1101 qglBegin(GL_LINE_LOOP); 1102 for (int i=0 ; i<w->numpoints ; i++) 1103 qglVertex3fv(w->points[i]); 1104 qglEnd(); 1105 } 1106 } 1107 } 1108 1109 } 1110 1111 1112 1113 if (PathMode()) 1114 { 1115 qglPointSize (4); 1116 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]); 1117 qglBegin (GL_POINTS); 1118 1119 for (int n = 0; n < g_nPathCount; n++) 1120 qglVertex3fv(g_PathPoints[n]); 1121 qglEnd (); 1122 qglPointSize (1); 1123 1124 CString strMsg; 1125 for (n = 0; n < g_nPathCount; n++) 1126 { 1127 qglRasterPos3f (g_PathPoints[n].m_ptClip[0]+2, g_PathPoints[n].m_ptClip[1]+2, g_PathPoints[n].m_ptClip[2]+2); 1128 strMsg.Format("%i", n+1); 1129 qglCallLists (strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg); 1130 } 1131 1132 } 1133 if (m_nViewType != XY) 1134 qglPopMatrix(); 1135 1136 qwglSwapBuffers(dc.m_hDC); 1137 TRACE("XY Paint\n"); 1138 } 1139 } 1140 1141 void CXYWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 1142 { 1143 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags); 1144 } 1145 1146 1147 1148 // FIXME: the brush_t *pBrush is never used. ( Entity_Create uses selected_brushes ) 1149 void CreateEntityFromName(char* pName, brush_t* pBrush) 1150 { 1151 eclass_t *pecNew; 1152 entity_t *petNew; 1153 if (stricmp(pName, "worldspawn") == 0) 1154 { 1155 MessageBox(g_qeglobals.d_hwndMain, "Can't create an entity with worldspawn.", "info", 0); 1156 return; 1157 } 1158 1159 pecNew = Eclass_ForName(pName, false); 1160 1161 // create it 1162 petNew = Entity_Create(pecNew); 1163 if (petNew == NULL) 1164 { 1165 if (!((selected_brushes.next == &selected_brushes)||(selected_brushes.next->next != &selected_brushes))) 1166 { 1167 brush_t* b = selected_brushes.next; 1168 if (b->owner != world_entity && b->owner->eclass->fixedsize && pecNew->fixedsize) 1169 { 1170 vec3_t mins, maxs; 1171 vec3_t origin; 1172 for (int i=0 ; i<3 ; i++) 1173 origin[i] = b->mins[i] - pecNew->mins[i]; 1174 1175 VectorAdd (pecNew->mins, origin, mins); 1176 VectorAdd (pecNew->maxs, origin, maxs); 1177 brush_t* nb = Brush_Create (mins, maxs, &pecNew->texdef); 1178 Entity_LinkBrush (b->owner, nb); 1179 nb->owner->eclass = pecNew; 1180 SetKeyValue (nb->owner, "classname", pName); 1181 Brush_Free(b); 1182 Brush_Build(nb); 1183 Brush_AddToList (nb, &active_brushes); 1184 Select_Brush(nb); 1185 return; 1186 } 1187 } 1188 MessageBox(g_qeglobals.d_hwndMain, "Failed to create entity.", "info", 0); 1189 return; 1190 } 1191 1192 Select_Deselect (); 1193 //entity_t* pEntity = world_entity; 1194 //if (selected_brushes.next != &selected_brushes) 1195 // pEntity = selected_brushes.next->owner; 1196 Select_Brush (petNew->brushes.onext); 1197 1198 if (stricmp(pName, "misc_model") == 0) 1199 { 1200 SetInspectorMode(W_ENTITY); 1201 PostMessage(g_qeglobals.d_hwndEntity, WM_COMMAND, IDC_BTN_ASSIGNMODEL, 0); 1202 } 1203 1204 } 1205 1206 1207 brush_t* CreateEntityBrush(int x, int y, CXYWnd* pWnd) 1208 { 1209 vec3_t mins, maxs; 1210 int i; 1211 float temp; 1212 brush_t *n; 1213 1214 pWnd->SnapToPoint (x, y, mins); 1215 x += 32; 1216 y += 32; 1217 pWnd->SnapToPoint (x, y, maxs); 1218 1219 int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1; 1220 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize)); 1221 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize)); 1222 1223 if (maxs[nDim] <= mins[nDim]) 1224 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize; 1225 1226 for (i=0 ; i<3 ; i++) 1227 { 1228 if (mins[i] == maxs[i]) 1229 maxs[i] += 16; // don't create a degenerate brush 1230 if (mins[i] > maxs[i]) 1231 { 1232 temp = mins[i]; 1233 mins[i] = maxs[i]; 1234 maxs[i] = temp; 1235 } 1236 } 1237 1238 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef); 1239 if (!n) 1240 return NULL; 1241 1242 Brush_AddToList (n, &selected_brushes); 1243 Entity_LinkBrush (world_entity, n); 1244 Brush_Build( n ); 1245 return n; 1246 } 1247 1248 void CreateRightClickEntity(CXYWnd* pWnd, int x, int y, char* pName) 1249 { 1250 CRect rctZ; 1251 pWnd->GetClientRect(rctZ); 1252 brush_t* pBrush = (selected_brushes.next == &selected_brushes) ? CreateEntityBrush(x, rctZ.Height() - 1 - y, pWnd) : selected_brushes.next; 1253 CreateEntityFromName(pName, pBrush); 1254 //Select_Brush(pBrush); 1255 } 1256 1257 brush_t* CreateSmartBrush(vec3_t v) 1258 { 1259 vec3_t mins, maxs; 1260 int i; 1261 brush_t *n; 1262 1263 for (i=0 ; i<3 ; i++) 1264 { 1265 mins[i] = v[i] - 16; 1266 maxs[i] = v[i] + 16; 1267 } 1268 1269 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef); 1270 if (!n) 1271 return NULL; 1272 1273 Brush_AddToList(n, &selected_brushes); 1274 //Entity_LinkBrush(world_entity, n); 1275 Brush_Build(n); 1276 return n; 1277 } 1278 1279 1280 1281 1282 CString g_strSmartEntity; 1283 int g_nSmartX; 1284 int g_nSmartY; 1285 bool g_bSmartWaiting; 1286 void _SmartPointDone(bool b, int n) 1287 { 1288 g_bSmartWaiting = false; 1289 } 1290 1291 void CreateSmartEntity(CXYWnd* pWnd, int x, int y, const char* pName) 1292 { 1293 g_nSmartX = x; 1294 g_nSmartY = y; 1295 g_strSmartEntity = pName; 1296 if (g_strSmartEntity.Find("Smart_Train") >= 0) 1297 { 1298 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"); 1299 g_bPathMode = true; 1300 g_nPathLimit = 0; 1301 g_nPathCount = 0; 1302 g_bSmartGo = true; 1303 } 1304 else 1305 if (g_strSmartEntity.Find("Smart_Monster...") >= 0) 1306 { 1307 g_bPathMode = true; 1308 g_nPathLimit = 0; 1309 g_nPathCount = 0; 1310 } 1311 else 1312 if (g_strSmartEntity.Find("Smart_Rotating") >= 0) 1313 { 1314 g_bSmartWaiting = true; 1315 ShowInfoDialog("Left click to specify the rotation origin"); 1316 AcquirePath(1, &_SmartPointDone); 1317 while (g_bSmartWaiting) 1318 { 1319 MSG msg; 1320 if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE )) 1321 { 1322 TranslateMessage(&msg); 1323 DispatchMessage(&msg); 1324 } 1325 } 1326 HideInfoDialog(); 1327 CPtrArray array; 1328 g_bScreenUpdates = false; 1329 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating"); 1330 array.Add(reinterpret_cast<void*>(selected_brushes.next)); 1331 Select_Deselect(); 1332 brush_t* pBrush = CreateSmartBrush(g_PathPoints[0]); 1333 array.Add(pBrush); 1334 Select_Deselect(); 1335 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(0))); 1336 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(1))); 1337 ConnectEntities(); 1338 g_bScreenUpdates = true; 1339 } 1340 } 1341 1342 1343 void FinishSmartCreation() 1344 { 1345 CPtrArray array; 1346 HideInfoDialog(); 1347 brush_t* pEntities = NULL; 1348 if (g_strSmartEntity.Find("Smart_Train") >= 0) 1349 { 1350 g_bScreenUpdates = false; 1351 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train"); 1352 array.Add(reinterpret_cast<void*>(selected_brushes.next)); 1353 for (int n = 0; n < g_nPathCount; n++) 1354 { 1355 Select_Deselect(); 1356 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_PathPoints[n].m_ptScreen.x,g_PathPoints[n].m_ptScreen.y, "path_corner"); 1357 array.Add(reinterpret_cast<void*>(selected_brushes.next)); 1358 } 1359 1360 for (n = 0; n < g_nPathCount; n++) 1361 { 1362 Select_Deselect(); 1363 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n))); 1364 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n+1))); 1365 ConnectEntities(); 1366 } 1367 g_bScreenUpdates = true; 1368 1369 } 1370 g_nPathCount = 0; 1371 g_bPathMode = false; 1372 Sys_UpdateWindows(W_ALL); 1373 } 1374 1375 void CXYWnd::KillPathMode() 1376 { 1377 g_bSmartGo = false; 1378 g_bPathMode = false; 1379 if (g_pPathFunc) 1380 g_pPathFunc(false, g_nPathCount); 1381 g_nPathCount = 0; 1382 g_pPathFunc = NULL; 1383 Sys_UpdateWindows(W_ALL); 1384 } 1385 1386 // gets called for drop down menu messages 1387 // TIP: it's not always about EntityCreate 1388 void CXYWnd::OnEntityCreate(unsigned int nID) 1389 { 1390 if (m_mnuDrop.GetSafeHmenu()) 1391 { 1392 CString strItem; 1393 m_mnuDrop.GetMenuString(nID, strItem, MF_BYCOMMAND); 1394 1395 if (strItem.CompareNoCase("Add to...") == 0) 1396 { 1397 //++timo TODO: fill the menu with current groups? 1398 // this one is for adding to existing groups only 1399 Sys_Printf("TODO: Add to... in CXYWnd::OnEntityCreate\n"); 1400 } 1401 else if (strItem.CompareNoCase("Remove") == 0) 1402 { 1403 // remove selected brushes from their current group 1404 brush_t *b; 1405 for( b = selected_brushes.next; b != &selected_brushes; b = b->next ) 1406 { 1407 1408 } 1409 } 1410 1411 //++timo FIXME: remove when all hooks are in 1412 if (strItem.CompareNoCase("Add to...") == 0 1413 || strItem.CompareNoCase("Remove") == 0 1414 || strItem.CompareNoCase("Name...") == 0 1415 || strItem.CompareNoCase("New group...") == 0) 1416 { 1417 Sys_Printf("TODO: hook drop down group menu\n"); 1418 return; 1419 } 1420 1421 if (strItem.Find("Smart_") >= 0) 1422 { 1423 CreateSmartEntity(this, m_ptDown.x, m_ptDown.y, strItem); 1424 } 1425 else 1426 { 1427 CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, strItem.GetBuffer(0)); 1428 } 1429 1430 Sys_UpdateWindows(W_ALL); 1431 //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2)); 1432 } 1433 } 1434 1435 1436 void CXYWnd::HandleDrop() 1437 { 1438 if (g_PrefsDlg.m_bRightClick == false) 1439 return; 1440 if (!m_mnuDrop.GetSafeHmenu()) // first time, load it up 1441 { 1442 m_mnuDrop.CreatePopupMenu(); 1443 int nID = ID_ENTITY_START; 1444 1445 CMenu* pChild2 = new CMenu; 1446 pChild2->CreateMenu(); 1447 pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTCOMPLETETALL, "Select Complete Tall"); 1448 pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTTOUCHING, "Select Touching"); 1449 pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTPARTIALTALL, "Select Partial Tall"); 1450 pChild2->AppendMenu(MF_STRING, ID_SELECTION_SELECTINSIDE, "Select Inside"); 1451 m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild2->GetSafeHmenu()), "Select"); 1452 m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, ""); 1453 1454 CMenu* pChild3 = new CMenu; 1455 pChild3->CreateMenu(); 1456 pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_ADDTO, "Add to..."); 1457 pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_REMOVE, "Remove"); 1458 pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_NAME, "Name..."); 1459 pChild3->AppendMenu(MF_SEPARATOR, nID++, ""); 1460 pChild3->AppendMenu(MF_STRING, ID_DROP_GROUP_NEWGROUP, "New Group..."); 1461 m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild3->GetSafeHmenu()), "Group"); 1462 m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, ""); 1463 1464 m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_UNGROUPENTITY, "Ungroup Entity"); 1465 m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_MAKE_DETAIL, "Make Detail"); 1466 m_mnuDrop.AppendMenu(MF_STRING, ID_SELECTION_MAKE_STRUCTURAL, "Make Structural"); 1467 m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, ""); 1468 1469 CMenu* pChild = new CMenu; 1470 pChild->CreateMenu(); 1471 pChild->AppendMenu(MF_STRING, nID++, "Smart_Train"); 1472 //pChild->AppendMenu(MF_STRING, nID++, "Smart_Rotating"); 1473 m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), "Smart Entities"); 1474 m_mnuDrop.AppendMenu(MF_SEPARATOR, nID++, ""); 1475 1476 pChild = NULL; 1477 eclass_t *e; 1478 CString strActive; 1479 CString strLast; 1480 CString strName; 1481 for (e=eclass ; e ; e=e->next) 1482 { 1483 strLast = strName; 1484 strName = e->name; 1485 int n_ = strName.Find("_"); 1486 if (n_ > 0) 1487 { 1488 CString strLeft = strName.Left(n_); 1489 CString strRight = strName.Right(strName.GetLength() - n_ - 1); 1490 if (strLeft == strActive) // this is a child 1491 { 1492 ASSERT(pChild); 1493 pChild->AppendMenu(MF_STRING, nID++, strName); 1494 } 1495 else 1496 { 1497 if (pChild) 1498 { 1499 m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), strActive); 1500 g_ptrMenus.Add(pChild); 1501 //pChild->DestroyMenu(); 1502 //delete pChild; 1503 pChild = NULL; 1504 } 1505 strActive = strLeft; 1506 pChild = new CMenu; 1507 pChild->CreateMenu(); 1508 pChild->AppendMenu(MF_STRING, nID++, strName); 1509 } 1510 } 1511 else 1512 { 1513 if (pChild) 1514 { 1515 m_mnuDrop.AppendMenu(MF_POPUP, reinterpret_cast<unsigned int>(pChild->GetSafeHmenu()), strActive); 1516 g_ptrMenus.Add(pChild); 1517 //pChild->DestroyMenu(); 1518 //delete pChild; 1519 pChild = NULL; 1520 } 1521 strActive = ""; 1522 m_mnuDrop.AppendMenu(MF_STRING, nID++, strName); 1523 } 1524 } 1525 } 1526 1527 CPoint ptMouse; 1528 GetCursorPos(&ptMouse); 1529 m_mnuDrop.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, this); 1530 } 1531 1532 void CXYWnd::XY_Init() 1533 { 1534 m_vOrigin[0] = 0; 1535 m_vOrigin[1] = 20; 1536 m_vOrigin[2] = 46; 1537 m_fScale = 1; 1538 } 1539 1540 void CXYWnd::SnapToPoint (int x, int y, vec3_t point) 1541 { 1542 if (g_PrefsDlg.m_bNoClamp) 1543 { 1544 XY_ToPoint(x, y, point); 1545 } 1546 else 1547 { 1548 XY_ToGridPoint(x, y, point); 1549 } 1550 //-- else 1551 //-- XY_ToPoint(x, y, point); 1552 //-- //XY_ToPoint(x, y, point); 1553 } 1554 1555 1556 void CXYWnd::XY_ToPoint (int x, int y, vec3_t point) 1557 { 1558 float fx = x; 1559 float fy = y; 1560 float fw = m_nWidth; 1561 float fh = m_nHeight; 1562 if (m_nViewType == XY) 1563 { 1564 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; 1565 point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale; 1566 //point[2] = 0; 1567 } 1568 else if (m_nViewType == YZ) 1569 { 1570 ////point[0] = 0; 1571 //point[1] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; 1572 //point[2] = m_vOrigin[1] + (fy - fh / 2 ) / m_fScale; 1573 point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale; 1574 point[2] = m_vOrigin[2] + (fy - fh / 2 ) / m_fScale; 1575 } 1576 else 1577 { 1578 //point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; 1579 ////point[1] = 0; 1580 //point[2] = m_vOrigin[1] + (fy - fh / 2) / m_fScale; 1581 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; 1582 //point[1] = 0; 1583 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale; 1584 } 1585 } 1586 1587 1588 void CXYWnd::XY_ToGridPoint (int x, int y, vec3_t point) 1589 { 1590 if (m_nViewType == XY) 1591 { 1592 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; 1593 point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale; 1594 //point[2] = 0; 1595 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1596 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1597 } 1598 else if (m_nViewType == YZ) 1599 { 1600 //point[0] = 0; 1601 //point[1] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; 1602 //point[2] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale; 1603 point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale; 1604 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale; 1605 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1606 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1607 } 1608 else 1609 { 1610 //point[1] = 0; 1611 //point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; 1612 //point[2] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale; 1613 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; 1614 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale; 1615 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1616 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1617 } 1618 } 1619 1620 1621 void CXYWnd::XY_MouseDown (int x, int y, int buttons) 1622 { 1623 1624 vec3_t point; 1625 vec3_t origin, dir, right, up; 1626 1627 m_nButtonstate = buttons; 1628 m_nPressx = x; 1629 m_nPressy = y; 1630 VectorCopy (vec3_origin, m_vPressdelta); 1631 1632 XY_ToPoint (x, y, point); 1633 1634 VectorCopy (point, origin); 1635 1636 dir[0] = 0; dir[1] = 0; dir[2] = 0; 1637 if (m_nViewType == XY) 1638 { 1639 origin[2] = 8192; 1640 dir[2] = -1; 1641 right[0] = 1 / m_fScale; 1642 right[1] = 0; 1643 right[2] = 0; 1644 up[0] = 0; 1645 up[1] = 1 / m_fScale; 1646 up[2] = 0; 1647 } 1648 else if (m_nViewType == YZ) 1649 { 1650 origin[0] = 8192; 1651 dir[0] = -1; 1652 right[1] = 1 / m_fScale; 1653 right[2] = 0; 1654 right[0] = 0; 1655 up[0] = 0; 1656 up[2] = 1 / m_fScale; 1657 up[1] = 0; 1658 } 1659 else 1660 { 1661 origin[1] = 8192; 1662 dir[1] = -1; 1663 right[0] = 1 / m_fScale; 1664 right[2] = 0; 1665 right[1] = 0; 1666 up[0] = 0; 1667 up[2] = 1 / m_fScale; 1668 up[1] = 0; 1669 } 1670 1671 1672 m_bPress_selection = (selected_brushes.next != &selected_brushes); 1673 1674 GetCursorPos(&m_ptCursor); 1675 //Sys_GetCursorPos (&m_ptCursor.x, &m_ptCursor.y); 1676 1677 // lbutton = manipulate selection 1678 // shift-LBUTTON = select 1679 if ( (buttons == MK_LBUTTON) 1680 || (buttons == (MK_LBUTTON | MK_SHIFT)) 1681 || (buttons == (MK_LBUTTON | MK_CONTROL)) 1682 || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) ) 1683 { 1684 if (g_qeglobals.d_select_mode == sel_addpoint) { 1685 XY_ToGridPoint(x, y, point); 1686 if (g_qeglobals.selectObject) { 1687 g_qeglobals.selectObject->addPoint(point[0], point[1], point[2]); 1688 } 1689 return; 1690 } 1691 Patch_SetView( (m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ); 1692 Drag_Begin (x, y, buttons, right, up, origin, dir); 1693 return; 1694 } 1695 1696 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON; 1697 1698 // control mbutton = move camera 1699 if (m_nButtonstate == (MK_CONTROL|nMouseButton) ) 1700 { 1701 VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin); 1702 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY); 1703 } 1704 1705 // mbutton = angle camera 1706 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) || 1707 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON))) 1708 { 1709 VectorSubtract (point, g_pParentWnd->GetCamera()->Camera().origin, point); 1710 1711 int n1 = (m_nViewType == XY) ? 1 : 2; 1712 int n2 = (m_nViewType == YZ) ? 1 : 0; 1713 int nAngle = (m_nViewType == XY) ? YAW : PITCH; 1714 if (point[n1] || point[n2]) 1715 { 1716 g_pParentWnd->GetCamera()->Camera().angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]); 1717 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY); 1718 } 1719 } 1720 1721 // shift mbutton = move z checker 1722 if (m_nButtonstate == (MK_SHIFT | nMouseButton)) 1723 { 1724 if (RotateMode() || g_bPatchBendMode) 1725 { 1726 SnapToPoint (x, y, point); 1727 VectorCopyXY(point, g_vRotateOrigin); 1728 if (g_bPatchBendMode) 1729 { 1730 VectorCopy(point, g_vBendOrigin); 1731 } 1732 Sys_UpdateWindows (W_XY); 1733 return; 1734 } 1735 else 1736 { 1737 SnapToPoint (x, y, point); 1738 if (m_nViewType == XY) 1739 { 1740 z.origin[0] = point[0]; 1741 z.origin[1] = point[1]; 1742 } 1743 else if (m_nViewType == YZ) 1744 { 1745 z.origin[0] = point[1]; 1746 z.origin[1] = point[2]; 1747 } 1748 else 1749 { 1750 z.origin[0] = point[0]; 1751 z.origin[1] = point[2]; 1752 } 1753 Sys_UpdateWindows (W_XY_OVERLAY|W_Z); 1754 return; 1755 } 1756 } 1757 } 1758 1759 1760 void CXYWnd::XY_MouseUp(int x, int y, int buttons) 1761 { 1762 Drag_MouseUp (buttons); 1763 if (!m_bPress_selection) 1764 Sys_UpdateWindows (W_ALL); 1765 m_nButtonstate = 0; 1766 while (::ShowCursor(TRUE) < 0) 1767 ; 1768 } 1769 1770 qboolean CXYWnd::DragDelta (int x, int y, vec3_t move) 1771 { 1772 vec3_t xvec, yvec, delta; 1773 int i; 1774 1775 xvec[0] = 1 / m_fScale; 1776 xvec[1] = xvec[2] = 0; 1777 yvec[1] = 1 / m_fScale; 1778 yvec[0] = yvec[2] = 0; 1779 1780 for (i=0 ; i<3 ; i++) 1781 { 1782 delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy); 1783 if (!g_PrefsDlg.m_bNoClamp) 1784 { 1785 delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; 1786 } 1787 } 1788 VectorSubtract (delta, m_vPressdelta, move); 1789 VectorCopy (delta, m_vPressdelta); 1790 1791 if (move[0] || move[1] || move[2]) 1792 return true; 1793 return false; 1794 } 1795 1796 1797 /* 1798 ============== 1799 NewBrushDrag 1800 ============== 1801 */ 1802 void CXYWnd::NewBrushDrag (int x, int y) 1803 { 1804 vec3_t mins, maxs, junk; 1805 int i; 1806 float temp; 1807 brush_t *n; 1808 1809 if (!DragDelta (x,y, junk)) 1810 return; 1811 1812 // delete the current selection 1813 if (selected_brushes.next != &selected_brushes) 1814 Brush_Free (selected_brushes.next); 1815 1816 SnapToPoint (m_nPressx, m_nPressy, mins); 1817 1818 int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1; 1819 1820 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z / g_qeglobals.d_gridsize)); 1821 SnapToPoint (x, y, maxs); 1822 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z / g_qeglobals.d_gridsize)); 1823 if (maxs[nDim] <= mins[nDim]) 1824 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize; 1825 1826 for (i=0 ; i<3 ; i++) 1827 { 1828 if (mins[i] == maxs[i]) 1829 return; // don't create a degenerate brush 1830 if (mins[i] > maxs[i]) 1831 { 1832 temp = mins[i]; 1833 mins[i] = maxs[i]; 1834 maxs[i] = temp; 1835 } 1836 } 1837 1838 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef); 1839 if (!n) 1840 return; 1841 1842 vec3_t vSize; 1843 VectorSubtract(maxs, mins, vSize); 1844 g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]); 1845 g_pParentWnd->SetStatusText(2, g_strStatus); 1846 1847 Brush_AddToList (n, &selected_brushes); 1848 1849 Entity_LinkBrush (world_entity, n); 1850 1851 Brush_Build( n ); 1852 1853 // Sys_UpdateWindows (W_ALL); 1854 Sys_UpdateWindows (W_XY| W_CAMERA); 1855 1856 } 1857 1858 /* 1859 ============== 1860 XY_MouseMoved 1861 ============== 1862 */ 1863 void CXYWnd::XY_MouseMoved (int x, int y, int buttons) 1864 { 1865 vec3_t point; 1866 1867 1868 if (!m_nButtonstate) 1869 { 1870 if (g_bCrossHairs) 1871 { 1872 ::ShowCursor(FALSE); 1873 Sys_UpdateWindows (W_XY | W_XY_OVERLAY); 1874 ::ShowCursor(TRUE); 1875 } 1876 return; 1877 } 1878 1879 // lbutton without selection = drag new brush 1880 //if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint && g_qeglobals.d_select_mode != sel_splineedit) 1881 if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode == sel_brush) 1882 { 1883 NewBrushDrag (x, y); 1884 return; 1885 } 1886 1887 // lbutton (possibly with control and or shift) 1888 // with selection = drag selection 1889 if (m_nButtonstate & MK_LBUTTON) 1890 { 1891 Drag_MouseMoved (x, y, buttons); 1892 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA_IFON | W_Z); 1893 return; 1894 } 1895 1896 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON; 1897 // control mbutton = move camera 1898 if (m_nButtonstate == (MK_CONTROL|nMouseButton) ) 1899 { 1900 SnapToPoint (x, y, point); 1901 VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin); 1902 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA); 1903 return; 1904 } 1905 1906 // shift mbutton = move z checker 1907 if (m_nButtonstate == (MK_SHIFT|nMouseButton) ) 1908 { 1909 if (RotateMode() || g_bPatchBendMode) 1910 { 1911 SnapToPoint (x, y, point); 1912 VectorCopyXY(point, g_vRotateOrigin); 1913 if (g_bPatchBendMode) 1914 { 1915 VectorCopy(point, g_vBendOrigin); 1916 } 1917 Sys_UpdateWindows (W_XY); 1918 return; 1919 } 1920 else 1921 { 1922 SnapToPoint (x, y, point); 1923 if (m_nViewType == XY) 1924 { 1925 z.origin[0] = point[0]; 1926 z.origin[1] = point[1]; 1927 } 1928 else if (m_nViewType == YZ) 1929 { 1930 z.origin[0] = point[1]; 1931 z.origin[1] = point[2]; 1932 } 1933 else 1934 { 1935 z.origin[0] = point[0]; 1936 z.origin[1] = point[2]; 1937 } 1938 } 1939 Sys_UpdateWindows (W_XY_OVERLAY|W_Z); 1940 return; 1941 } 1942 1943 // mbutton = angle camera 1944 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) || 1945 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON))) 1946 { 1947 SnapToPoint (x, y, point); 1948 VectorSubtract (point, g_pParentWnd->GetCamera()->Camera().origin, point); 1949 1950 int n1 = (m_nViewType == XY) ? 1 : 2; 1951 int n2 = (m_nViewType == YZ) ? 1 : 0; 1952 int nAngle = (m_nViewType == XY) ? YAW : PITCH; 1953 if (point[n1] || point[n2]) 1954 { 1955 g_pParentWnd->GetCamera()->Camera().angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]); 1956 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY); 1957 } 1958 return; 1959 } 1960 1961 1962 // rbutton = drag xy origin 1963 if (m_nButtonstate == MK_RBUTTON) 1964 { 1965 Sys_GetCursorPos (&x, &y); 1966 if (x != m_ptCursor.x || y != m_ptCursor.y) 1967 { 1968 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 1969 int nDim2 = (m_nViewType == XY) ? 1 : 2; 1970 m_vOrigin[nDim1] -= (x - m_ptCursor.x) / m_fScale; 1971 m_vOrigin[nDim2] += (y - m_ptCursor.y) / m_fScale; 1972 SetCursorPos (m_ptCursor.x, m_ptCursor.y); 1973 ::ShowCursor(FALSE); 1974 //XY_Draw(); 1975 //RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 1976 Sys_UpdateWindows (W_XY | W_XY_OVERLAY); 1977 //::ShowCursor(TRUE); 1978 } 1979 return; 1980 } 1981 1982 } 1983 1984 1985 /* 1986 ============================================================================ 1987 1988 DRAWING 1989 1990 ============================================================================ 1991 */ 1992 1993 1994 /* 1995 ============== 1996 XY_DrawGrid 1997 ============== 1998 */ 1999 void CXYWnd::XY_DrawGrid() 2000 { 2001 float x, y, xb, xe, yb, ye; 2002 int w, h; 2003 char text[32]; 2004 2005 qglDisable(GL_TEXTURE_2D); 2006 qglDisable(GL_TEXTURE_1D); 2007 qglDisable(GL_DEPTH_TEST); 2008 qglDisable(GL_BLEND); 2009 2010 w = m_nWidth / 2 / m_fScale; 2011 h = m_nHeight / 2 / m_fScale; 2012 2013 2014 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 2015 int nDim2 = (m_nViewType == XY) ? 1 : 2; 2016 //int nDim1 = 0; 2017 //int nDim2 = 1; 2018 2019 2020 xb = m_vOrigin[nDim1] - w; 2021 if (xb < region_mins[nDim1]) 2022 xb = region_mins[nDim1]; 2023 xb = 64 * floor (xb/64); 2024 2025 xe = m_vOrigin[nDim1] + w; 2026 if (xe > region_maxs[nDim1]) 2027 xe = region_maxs[nDim1]; 2028 xe = 64 * ceil (xe/64); 2029 2030 yb = m_vOrigin[nDim2] - h; 2031 if (yb < region_mins[nDim2]) 2032 yb = region_mins[nDim2]; 2033 yb = 64 * floor (yb/64); 2034 2035 ye = m_vOrigin[nDim2] + h; 2036 if (ye > region_maxs[nDim2]) 2037 ye = region_maxs[nDim2]; 2038 ye = 64 * ceil (ye/64); 2039 2040 // draw major blocks 2041 2042 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR]); 2043 2044 int stepSize = 64 * 0.1 / m_fScale; 2045 if (stepSize < 64) { 2046 stepSize = 64; 2047 } else { 2048 int i; 2049 for (i = 1; i < stepSize; i <<= 1) { 2050 } 2051 stepSize = i; 2052 } 2053 2054 if ( g_qeglobals.d_showgrid ) 2055 { 2056 2057 qglBegin (GL_LINES); 2058 2059 for (x=xb ; x<=xe ; x+=stepSize) 2060 { 2061 qglVertex2f (x, yb); 2062 qglVertex2f (x, ye); 2063 } 2064 for (y=yb ; y<=ye ; y+=stepSize) 2065 { 2066 qglVertex2f (xb, y); 2067 qglVertex2f (xe, y); 2068 } 2069 2070 qglEnd (); 2071 2072 } 2073 2074 // draw minor blocks 2075 if ( m_fScale > .1 && g_qeglobals.d_showgrid && g_qeglobals.d_gridsize * m_fScale >= 4 && 2076 g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR] != g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK]) 2077 { 2078 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]); 2079 2080 qglBegin (GL_LINES); 2081 for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize) 2082 { 2083 if ( ! ((int)x & 63) ) 2084 continue; 2085 qglVertex2f (x, yb); 2086 qglVertex2f (x, ye); 2087 } 2088 for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize) 2089 { 2090 if ( ! ((int)y & 63) ) 2091 continue; 2092 qglVertex2f (xb, y); 2093 qglVertex2f (xe, y); 2094 } 2095 qglEnd (); 2096 } 2097 2098 // draw coordinate text if needed 2099 2100 if ( g_qeglobals.d_savedinfo.show_coordinates) 2101 { 2102 //glColor4f(0, 0, 0, 0); 2103 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]); 2104 2105 for (x=xb ; x<xe ; x+=stepSize) 2106 { 2107 qglRasterPos2f (x, m_vOrigin[nDim2] + h - 6 / m_fScale); 2108 sprintf (text, "%i",(int)x); 2109 qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text); 2110 } 2111 for (y=yb ; y<ye ; y+=stepSize) 2112 { 2113 qglRasterPos2f (m_vOrigin[nDim1] - w + 1, y); 2114 sprintf (text, "%i",(int)y); 2115 qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text); 2116 } 2117 2118 2119 if (Active()) 2120 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]); 2121 2122 qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale ); 2123 2124 char cView[20]; 2125 if (m_nViewType == XY) 2126 strcpy(cView, "XY Top"); 2127 else 2128 if (m_nViewType == XZ) 2129 strcpy(cView, "XZ Front"); 2130 else 2131 strcpy(cView, "YZ Side"); 2132 2133 qglCallLists (strlen(cView), GL_UNSIGNED_BYTE, cView); 2134 2135 2136 } 2137 2138 2139 /* 2140 if (true) 2141 { 2142 qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]); 2143 qglBegin (GL_LINES); 2144 qglVertex2f (x, yb); 2145 qglVertex2f (x, ye); 2146 qglEnd(); 2147 } 2148 */ 2149 2150 } 2151 2152 /* 2153 ============== 2154 XY_DrawBlockGrid 2155 ============== 2156 */ 2157 void CXYWnd::XY_DrawBlockGrid() 2158 { 2159 float x, y, xb, xe, yb, ye; 2160 int w, h; 2161 char text[32]; 2162 2163 qglDisable(GL_TEXTURE_2D); 2164 qglDisable(GL_TEXTURE_1D); 2165 qglDisable(GL_DEPTH_TEST); 2166 qglDisable(GL_BLEND); 2167 2168 w = m_nWidth / 2 / m_fScale; 2169 h = m_nHeight / 2 / m_fScale; 2170 2171 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 2172 int nDim2 = (m_nViewType == XY) ? 1 : 2; 2173 2174 xb = m_vOrigin[nDim1] - w; 2175 if (xb < region_mins[nDim1]) 2176 xb = region_mins[nDim1]; 2177 xb = 1024 * floor (xb/1024); 2178 2179 xe = m_vOrigin[nDim1] + w; 2180 if (xe > region_maxs[nDim1]) 2181 xe = region_maxs[nDim1]; 2182 xe = 1024 * ceil (xe/1024); 2183 2184 yb = m_vOrigin[nDim2] - h; 2185 if (yb < region_mins[nDim2]) 2186 yb = region_mins[nDim2]; 2187 yb = 1024 * floor (yb/1024); 2188 2189 ye = m_vOrigin[nDim2] + h; 2190 if (ye > region_maxs[nDim2]) 2191 ye = region_maxs[nDim2]; 2192 ye = 1024 * ceil (ye/1024); 2193 2194 // draw major blocks 2195 2196 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]); 2197 qglLineWidth (2); 2198 2199 qglBegin (GL_LINES); 2200 2201 for (x=xb ; x<=xe ; x+=1024) 2202 { 2203 qglVertex2f (x, yb); 2204 qglVertex2f (x, ye); 2205 } 2206 for (y=yb ; y<=ye ; y+=1024) 2207 { 2208 qglVertex2f (xb, y); 2209 qglVertex2f (xe, y); 2210 } 2211 2212 qglEnd (); 2213 qglLineWidth (1); 2214 2215 // draw coordinate text if needed 2216 2217 for (x=xb ; x<xe ; x+=1024) 2218 for (y=yb ; y<ye ; y+=1024) 2219 { 2220 qglRasterPos2f (x+512, y+512); 2221 sprintf (text, "%i,%i",(int)floor(x/1024), (int)floor(y/1024) ); 2222 qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text); 2223 } 2224 2225 qglColor4f(0, 0, 0, 0); 2226 } 2227 2228 void CXYWnd::DrawRotateIcon() 2229 { 2230 float x, y; 2231 2232 if (m_nViewType == XY) 2233 { 2234 x = g_vRotateOrigin[0]; 2235 y = g_vRotateOrigin[1]; 2236 } 2237 else if (m_nViewType == YZ) 2238 { 2239 x = g_vRotateOrigin[1]; 2240 y = g_vRotateOrigin[2]; 2241 } 2242 else 2243 { 2244 x = g_vRotateOrigin[0]; 2245 y = g_vRotateOrigin[2]; 2246 } 2247 2248 qglEnable (GL_BLEND); 2249 qglDisable (GL_TEXTURE_2D); 2250 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); 2251 qglDisable (GL_CULL_FACE); 2252 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2253 qglColor4f (0.8, 0.1, 0.9, 0.25); 2254 2255 qglBegin(GL_QUADS); 2256 qglVertex3f (x-4,y-4,0); 2257 qglVertex3f (x+4,y-4,0); 2258 qglVertex3f (x+4,y+4,0); 2259 qglVertex3f (x-4,y+4,0); 2260 qglEnd (); 2261 qglDisable (GL_BLEND); 2262 2263 qglColor4f (1.0, 0.2, 1.0, 1); 2264 qglBegin(GL_POINTS); 2265 qglVertex3f (x,y,0); 2266 qglEnd (); 2267 2268 #if 0 2269 qglBegin(GL_LINES); 2270 qglVertex3f (x-6,y+6,0); 2271 qglVertex3f (x+6,y+6,0); 2272 qglVertex3f (x-6,y-6,0); 2273 qglVertex3f (x+6,y-6,0); 2274 qglEnd (); 2275 #endif 2276 2277 } 2278 2279 void CXYWnd::DrawCameraIcon() 2280 { 2281 float x, y, a; 2282 2283 if (m_nViewType == XY) 2284 { 2285 x = g_pParentWnd->GetCamera()->Camera().origin[0]; 2286 y = g_pParentWnd->GetCamera()->Camera().origin[1]; 2287 a = g_pParentWnd->GetCamera()->Camera().angles[YAW]/180*Q_PI; 2288 } 2289 else if (m_nViewType == YZ) 2290 { 2291 x = g_pParentWnd->GetCamera()->Camera().origin[1]; 2292 y = g_pParentWnd->GetCamera()->Camera().origin[2]; 2293 a = g_pParentWnd->GetCamera()->Camera().angles[PITCH]/180*Q_PI; 2294 } 2295 else 2296 { 2297 x = g_pParentWnd->GetCamera()->Camera().origin[0]; 2298 y = g_pParentWnd->GetCamera()->Camera().origin[2]; 2299 a = g_pParentWnd->GetCamera()->Camera().angles[PITCH]/180*Q_PI; 2300 } 2301 2302 qglColor3f (0.0, 0.0, 1.0); 2303 qglBegin(GL_LINE_STRIP); 2304 qglVertex3f (x-16,y,0); 2305 qglVertex3f (x,y+8,0); 2306 qglVertex3f (x+16,y,0); 2307 qglVertex3f (x,y-8,0); 2308 qglVertex3f (x-16,y,0); 2309 qglVertex3f (x+16,y,0); 2310 qglEnd (); 2311 2312 qglBegin(GL_LINE_STRIP); 2313 qglVertex3f (x+48*cos(a+Q_PI/4), y+48*sin(a+Q_PI/4), 0); 2314 qglVertex3f (x, y, 0); 2315 qglVertex3f (x+48*cos(a-Q_PI/4), y+48*sin(a-Q_PI/4), 0); 2316 qglEnd (); 2317 2318 #if 0 2319 char text[128]; 2320 qglRasterPos2f (x+64, y+64); 2321 sprintf (text, "%f",g_pParentWnd->GetCamera()->Camera().angles[YAW]); 2322 qglCallLists (strlen(text), GL_UNSIGNED_BYTE, text); 2323 #endif 2324 2325 } 2326 2327 void CXYWnd::DrawZIcon (void) 2328 { 2329 if (m_nViewType == XY) 2330 { 2331 float x = z.origin[0]; 2332 float y = z.origin[1]; 2333 qglEnable (GL_BLEND); 2334 qglDisable (GL_TEXTURE_2D); 2335 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); 2336 qglDisable (GL_CULL_FACE); 2337 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2338 qglColor4f (0.0, 0.0, 1.0, 0.25); 2339 qglBegin(GL_QUADS); 2340 qglVertex3f (x-8,y-8,0); 2341 qglVertex3f (x+8,y-8,0); 2342 qglVertex3f (x+8,y+8,0); 2343 qglVertex3f (x-8,y+8,0); 2344 qglEnd (); 2345 qglDisable (GL_BLEND); 2346 2347 qglColor4f (0.0, 0.0, 1.0, 1); 2348 2349 qglBegin(GL_LINE_LOOP); 2350 qglVertex3f (x-8,y-8,0); 2351 qglVertex3f (x+8,y-8,0); 2352 qglVertex3f (x+8,y+8,0); 2353 qglVertex3f (x-8,y+8,0); 2354 qglEnd (); 2355 2356 qglBegin(GL_LINE_STRIP); 2357 qglVertex3f (x-4,y+4,0); 2358 qglVertex3f (x+4,y+4,0); 2359 qglVertex3f (x-4,y-4,0); 2360 qglVertex3f (x+4,y-4,0); 2361 qglEnd (); 2362 } 2363 } 2364 2365 2366 /* 2367 ================== 2368 FilterBrush 2369 ================== 2370 */ 2371 BOOL FilterBrush(brush_t *pb) 2372 { 2373 if (!pb->owner) 2374 return FALSE; // during construction 2375 2376 if (pb->hiddenBrush) 2377 { 2378 return TRUE; 2379 } 2380 2381 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) 2382 { 2383 // filter out the brush only if all faces are caulk 2384 // if not don't hide the whole brush, proceed on a per-face basis (Cam_Draw) 2385 //++timo TODO: set this as a preference .. show caulk: hide any brush with caulk // don't draw caulk faces 2386 face_t *f; 2387 f=pb->brush_faces; 2388 while (f) 2389 { 2390 if (!strstr(f->texdef.name, "caulk")) 2391 break; 2392 f = f->next; 2393 } 2394 if (!f) 2395 return TRUE; 2396 2397 #if 0 2398 if (strstr(pb->brush_faces->texdef.name, "caulk")) 2399 return TRUE; 2400 #endif 2401 2402 //++timo FIXME: .. same deal here? 2403 if (strstr(pb->brush_faces->texdef.name, "donotenter")) 2404 return TRUE; 2405 } 2406 2407 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT) 2408 { 2409 if (strstr(pb->brush_faces->texdef.name, "hint")) 2410 return TRUE; 2411 } 2412 2413 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP) 2414 { 2415 if (strstr(pb->brush_faces->texdef.name, "clip")) 2416 return TRUE; 2417 2418 if (strstr(pb->brush_faces->texdef.name, "skip")) 2419 return TRUE; 2420 2421 //if (!strncmp(pb->brush_faces->texdef.name, "clip", 4)) 2422 // return TRUE; 2423 } 2424 2425 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WATER) 2426 { 2427 for (face_t* f = pb->brush_faces ; f ; f=f->next) 2428 { 2429 if (f->texdef.contents & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA)) 2430 return TRUE; 2431 } 2432 } 2433 2434 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DETAIL) 2435 { 2436 if (pb->brush_faces->texdef.contents & CONTENTS_DETAIL) 2437 return TRUE; 2438 } 2439 2440 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CURVES) 2441 { 2442 if (pb->patchBrush) 2443 return TRUE; 2444 } 2445 2446 if( g_qeglobals.d_savedinfo.exclude & EXCLUDE_TERRAIN ) 2447 { 2448 if( pb->terrainBrush ) 2449 { 2450 return TRUE; 2451 } 2452 } 2453 2454 if (pb->owner == world_entity) 2455 { 2456 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD) 2457 return TRUE; 2458 return FALSE; 2459 } 2460 else 2461 { 2462 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT) 2463 { 2464 return (strncmp(pb->owner->eclass->name, "func_group", 10)); 2465 } 2466 } 2467 2468 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS) 2469 { 2470 return (pb->owner->eclass->nShowFlags & ECLASS_LIGHT); 2471 //if (!strncmp(pb->owner->eclass->name, "light", 5)) 2472 // return TRUE; 2473 } 2474 2475 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS) 2476 { 2477 return (pb->owner->eclass->nShowFlags & ECLASS_PATH); 2478 //if (!strncmp(pb->owner->eclass->name, "path", 4)) 2479 // return TRUE; 2480 } 2481 2482 return FALSE; 2483 } 2484 2485 /* 2486 ============================================================= 2487 2488 PATH LINES 2489 2490 ============================================================= 2491 */ 2492 2493 /* 2494 ================== 2495 DrawPathLines 2496 2497 Draws connections between entities. 2498 Needs to consider all entities, not just ones on screen, 2499 because the lines can be visible when neither end is. 2500 Called for both camera view and xy view. 2501 ================== 2502 */ 2503 void DrawPathLines (void) 2504 { 2505 int i, j, k; 2506 vec3_t mid, mid1; 2507 entity_t *se, *te; 2508 brush_t *sb, *tb; 2509 char *psz; 2510 vec3_t dir, s1, s2; 2511 vec_t len, f; 2512 int arrows; 2513 int num_entities; 2514 char *ent_target[MAX_MAP_ENTITIES]; 2515 entity_t *ent_entity[MAX_MAP_ENTITIES]; 2516 2517 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS) 2518 return; 2519 2520 num_entities = 0; 2521 for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next) 2522 { 2523 ent_target[num_entities] = ValueForKey (te, "target"); 2524 if (ent_target[num_entities][0]) 2525 { 2526 ent_entity[num_entities] = te; 2527 num_entities++; 2528 } 2529 } 2530 2531 for (se = entities.next ; se != &entities ; se = se->next) 2532 { 2533 psz = ValueForKey(se, "targetname"); 2534 2535 if (psz == NULL || psz[0] == '\0') 2536 continue; 2537 2538 sb = se->brushes.onext; 2539 if (sb == &se->brushes) 2540 continue; 2541 2542 for (k=0 ; k<num_entities ; k++) 2543 { 2544 if (strcmp (ent_target[k], psz)) 2545 continue; 2546 2547 te = ent_entity[k]; 2548 tb = te->brushes.onext; 2549 if (tb == &te->brushes) 2550 continue; 2551 2552 for (i=0 ; i<3 ; i++) 2553 mid[i] = (sb->mins[i] + sb->maxs[i])*0.5; 2554 2555 for (i=0 ; i<3 ; i++) 2556 mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5; 2557 2558 VectorSubtract (mid1, mid, dir); 2559 len = VectorNormalize (dir); 2560 s1[0] = -dir[1]*8 + dir[0]*8; 2561 s2[0] = dir[1]*8 + dir[0]*8; 2562 s1[1] = dir[0]*8 + dir[1]*8; 2563 s2[1] = -dir[0]*8 + dir[1]*8; 2564 2565 qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]); 2566 2567 qglBegin(GL_LINES); 2568 qglVertex3fv(mid); 2569 qglVertex3fv(mid1); 2570 2571 arrows = (int)(len / 256) + 1; 2572 2573 for (i=0 ; i<arrows ; i++) 2574 { 2575 f = len * (i + 0.5) / arrows; 2576 2577 for (j=0 ; j<3 ; j++) 2578 mid1[j] = mid[j] + f*dir[j]; 2579 qglVertex3fv (mid1); 2580 qglVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]); 2581 qglVertex3fv (mid1); 2582 qglVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]); 2583 } 2584 2585 qglEnd(); 2586 } 2587 } 2588 2589 return; 2590 } 2591 2592 //============================================================= 2593 2594 // can be greatly simplified but per usual i am in a hurry 2595 // which is not an excuse, just a fact 2596 void CXYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds) 2597 { 2598 2599 vec3_t vSize; 2600 VectorSubtract(vMaxBounds, vMinBounds, vSize); 2601 2602 qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65, 2603 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65, 2604 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65); 2605 2606 if (m_nViewType == XY) 2607 { 2608 qglBegin (GL_LINES); 2609 2610 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f); 2611 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); 2612 2613 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); 2614 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); 2615 2616 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f); 2617 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f); 2618 2619 2620 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f); 2621 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f); 2622 2623 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f); 2624 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f); 2625 2626 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f); 2627 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f); 2628 2629 qglEnd(); 2630 2631 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f); 2632 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]); 2633 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2634 2635 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f); 2636 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]); 2637 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2638 2639 qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f); 2640 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]); 2641 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2642 2643 } 2644 else 2645 if (m_nViewType == XZ) 2646 { 2647 qglBegin (GL_LINES); 2648 2649 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale); 2650 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale); 2651 2652 qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale); 2653 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale); 2654 2655 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale); 2656 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale); 2657 2658 2659 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2]); 2660 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]); 2661 2662 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]); 2663 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]); 2664 2665 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2]); 2666 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]); 2667 2668 qglEnd(); 2669 2670 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale); 2671 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]); 2672 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2673 2674 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2])); 2675 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]); 2676 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2677 2678 qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale); 2679 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]); 2680 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2681 2682 } 2683 else 2684 { 2685 qglBegin (GL_LINES); 2686 2687 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale); 2688 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); 2689 2690 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); 2691 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); 2692 2693 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale); 2694 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale); 2695 2696 2697 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]); 2698 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]); 2699 2700 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]); 2701 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]); 2702 2703 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]); 2704 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]); 2705 2706 qglEnd(); 2707 2708 qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale); 2709 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]); 2710 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2711 2712 qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2])); 2713 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]); 2714 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2715 2716 qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale); 2717 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]); 2718 qglCallLists (g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim); 2719 2720 } 2721 } 2722 2723 2724 2725 /* 2726 ============== 2727 XY_Draw 2728 ============== 2729 */ 2730 long g_lCount = 0; 2731 long g_lTotal = 0; 2732 extern void DrawBrushEntityName (brush_t *b); 2733 2734 void CXYWnd::XY_Draw() 2735 { 2736 brush_t *brush; 2737 float w, h; 2738 entity_t *e; 2739 double start, end; 2740 double start2, end2; 2741 vec3_t mins, maxs; 2742 int drawn, culled; 2743 int i; 2744 2745 if (!active_brushes.next) 2746 return; // not valid yet 2747 2748 if (m_bTiming) 2749 start = Sys_DoubleTime(); 2750 // 2751 // clear 2752 // 2753 m_bDirty = false; 2754 2755 qglViewport(0, 0, m_nWidth, m_nHeight); 2756 qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0], 2757 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1], 2758 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0); 2759 2760 qglClear(GL_COLOR_BUFFER_BIT); 2761 2762 // 2763 // set up viewpoint 2764 // 2765 qglMatrixMode(GL_PROJECTION); 2766 qglLoadIdentity (); 2767 2768 w = m_nWidth / 2 / m_fScale; 2769 h = m_nHeight / 2/ m_fScale; 2770 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 2771 int nDim2 = (m_nViewType == XY) ? 1 : 2; 2772 mins[0] = m_vOrigin[nDim1] - w; 2773 maxs[0] = m_vOrigin[nDim1] + w; 2774 mins[1] = m_vOrigin[nDim2] - h; 2775 maxs[1] = m_vOrigin[nDim2] + h; 2776 2777 2778 qglOrtho (mins[0], maxs[0], mins[1], maxs[1], -8192, 8192); 2779 //glRotatef 2780 // 2781 // now draw the grid 2782 // 2783 XY_DrawGrid (); 2784 2785 // 2786 // draw stuff 2787 // 2788 qglShadeModel (GL_FLAT); 2789 qglDisable(GL_TEXTURE_2D); 2790 qglDisable(GL_TEXTURE_1D); 2791 qglDisable(GL_DEPTH_TEST); 2792 qglDisable(GL_BLEND); 2793 qglColor3f(0, 0, 0); 2794 2795 //glEnable (GL_LINE_SMOOTH); 2796 2797 drawn = culled = 0; 2798 2799 if (m_nViewType != XY) 2800 { 2801 qglPushMatrix(); 2802 if (m_nViewType == YZ) 2803 qglRotatef (-90, 0, 1, 0); // put Z going up 2804 //else 2805 qglRotatef (-90, 1, 0, 0); // put Z going up 2806 } 2807 2808 e = world_entity; 2809 2810 if (m_bTiming) 2811 start2 = Sys_DoubleTime(); 2812 2813 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) 2814 { 2815 if (brush->mins[nDim1] > maxs[0] || 2816 brush->mins[nDim2] > maxs[1] || 2817 brush->maxs[nDim1] < mins[0] || 2818 brush->maxs[nDim2] < mins[1]) 2819 { 2820 culled++; 2821 continue; // off screen 2822 } 2823 2824 if (FilterBrush (brush)) 2825 continue; 2826 2827 drawn++; 2828 2829 if (brush->owner != e && brush->owner) 2830 { 2831 2832 qglColor3fv(brush->owner->eclass->color); 2833 } 2834 else 2835 { 2836 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]); 2837 } 2838 2839 Brush_DrawXY(brush, m_nViewType); 2840 } 2841 2842 2843 if (m_bTiming) 2844 end2 = Sys_DoubleTime(); 2845 2846 2847 DrawPathLines (); 2848 2849 // 2850 // draw pointfile 2851 // 2852 if ( g_qeglobals.d_pointfile_display_list) 2853 qglCallList (g_qeglobals.d_pointfile_display_list); 2854 2855 2856 if (!(m_nViewType == XY)) 2857 qglPopMatrix(); 2858 2859 // 2860 // draw block grid 2861 // 2862 if ( g_qeglobals.show_blocks) 2863 XY_DrawBlockGrid (); 2864 2865 // 2866 // now draw selected brushes 2867 // 2868 if (m_nViewType != XY) 2869 { 2870 qglPushMatrix(); 2871 if (m_nViewType == YZ) 2872 qglRotatef (-90, 0, 1, 0); // put Z going up 2873 //else 2874 qglRotatef (-90, 1, 0, 0); // put Z going up 2875 } 2876 2877 2878 qglPushMatrix(); 2879 qglTranslatef( g_qeglobals.d_select_translate[0], g_qeglobals.d_select_translate[1], g_qeglobals.d_select_translate[2]); 2880 2881 if (RotateMode()) 2882 qglColor3f(0.8, 0.1, 0.9); 2883 else 2884 if (ScaleMode()) 2885 qglColor3f(0.1, 0.8, 0.1); 2886 else 2887 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]); 2888 2889 2890 if (g_PrefsDlg.m_bNoStipple == FALSE) 2891 { 2892 qglEnable (GL_LINE_STIPPLE); 2893 qglLineStipple (3, 0xaaaa); 2894 } 2895 qglLineWidth (2); 2896 2897 vec3_t vMinBounds; 2898 vec3_t vMaxBounds; 2899 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = 9999.9f; 2900 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = -9999.9f; 2901 2902 int nSaveDrawn = drawn; 2903 bool bFixedSize = false; 2904 for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) 2905 { 2906 drawn++; 2907 Brush_DrawXY(brush, m_nViewType); 2908 2909 if (!bFixedSize) 2910 { 2911 if (brush->owner->eclass->fixedsize) 2912 bFixedSize = true; 2913 if (g_PrefsDlg.m_bSizePaint) 2914 { 2915 for (i = 0; i < 3; i ++) 2916 { 2917 if (brush->mins[i] < vMinBounds[i]) 2918 vMinBounds[i] = brush->mins[i]; 2919 if (brush->maxs[i] > vMaxBounds[i]) 2920 vMaxBounds[i] = brush->maxs[i]; 2921 } 2922 } 2923 } 2924 } 2925 2926 if (g_PrefsDlg.m_bNoStipple == FALSE) 2927 { 2928 qglDisable (GL_LINE_STIPPLE); 2929 } 2930 qglLineWidth (1); 2931 2932 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint) 2933 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds); 2934 2935 2936 // edge / vertex flags 2937 2938 if (g_qeglobals.d_select_mode == sel_vertex) 2939 { 2940 qglPointSize (4); 2941 qglColor3f (0,1,0); 2942 qglBegin (GL_POINTS); 2943 for (i=0 ; i<g_qeglobals.d_numpoints ; i++) 2944 qglVertex3fv (g_qeglobals.d_points[i]); 2945 qglEnd (); 2946 qglPointSize (1); 2947 } 2948 else if (g_qeglobals.d_select_mode == sel_edge) 2949 { 2950 float *v1, *v2; 2951 2952 qglPointSize (4); 2953 qglColor3f (0,0,1); 2954 qglBegin (GL_POINTS); 2955 for (i=0 ; i<g_qeglobals.d_numedges ; i++) 2956 { 2957 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1]; 2958 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2]; 2959 qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5); 2960 } 2961 qglEnd (); 2962 qglPointSize (1); 2963 } 2964 2965 2966 g_splineList->draw(static_cast<qboolean>(g_qeglobals.d_select_mode == sel_editpoint || g_qeglobals.d_select_mode == sel_addpoint)); 2967 2968 qglPopMatrix(); 2969 2970 qglTranslatef (-g_qeglobals.d_select_translate[0], -g_qeglobals.d_select_translate[1], -g_qeglobals.d_select_translate[2]); 2971 2972 2973 if (!(m_nViewType == XY)) 2974 qglPopMatrix(); 2975 2976 // area selection hack 2977 if (g_qeglobals.d_select_mode == sel_area) 2978 { 2979 qglEnable (GL_BLEND); 2980 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2981 qglColor4f(0.0, 0.0, 1.0, 0.25); 2982 qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]); 2983 qglDisable (GL_BLEND); 2984 } 2985 2986 2987 // 2988 // now draw camera point 2989 // 2990 DrawCameraIcon (); 2991 DrawZIcon (); 2992 2993 if (RotateMode()) 2994 { 2995 DrawRotateIcon(); 2996 } 2997 2998 // plugin entities 2999 //++timo TODO: use an object for the 2D view 3000 DrawPluginEntities( (VIEWTYPE)m_nViewType ); 3001 3002 qglFinish(); 3003 //QE_CheckOpenGLForErrors(); 3004 3005 if (m_bTiming) 3006 { 3007 end = Sys_DoubleTime (); 3008 i = (int)(1000*(end-start)); 3009 int i3 = (int)(1000*(end2-start2)); 3010 g_lCount++; 3011 g_lTotal += i; 3012 int i2 = g_lTotal / g_lCount; 3013 Sys_Printf ("xy: %i ab: %i avg: %i\n", i, i3, i2); 3014 } 3015 } 3016 3017 /* 3018 ============== 3019 XY_Overlay 3020 ============== 3021 */ 3022 void CXYWnd::XY_Overlay() 3023 { 3024 int w, h; 3025 int r[4]; 3026 static vec3_t lastz; 3027 static vec3_t lastcamera; 3028 3029 3030 qglViewport(0, 0, m_nWidth, m_nHeight); 3031 3032 // 3033 // set up viewpoint 3034 // 3035 qglMatrixMode(GL_PROJECTION); 3036 qglLoadIdentity (); 3037 3038 w = m_nWidth / 2 / m_fScale; 3039 h = m_nHeight / 2 / m_fScale; 3040 3041 qglOrtho (m_vOrigin[0] - w, m_vOrigin[0] + w , m_vOrigin[1] - h, m_vOrigin[1] + h, -8000, 8000); 3042 // 3043 // erase the old camera and z checker positions 3044 // if the entire xy hasn't been redrawn 3045 // 3046 if (m_bDirty) 3047 { 3048 qglReadBuffer (GL_BACK); 3049 qglDrawBuffer (GL_FRONT); 3050 3051 qglRasterPos2f (lastz[0]-9, lastz[1]-9); 3052 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r); 3053 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR); 3054 3055 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50); 3056 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r); 3057 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR); 3058 } 3059 m_bDirty = true; 3060 3061 // 3062 // save off underneath where we are about to draw 3063 // 3064 VectorCopy (z.origin, lastz); 3065 VectorCopy (g_pParentWnd->GetCamera()->Camera().origin, lastcamera); 3066 3067 qglReadBuffer (GL_FRONT); 3068 qglDrawBuffer (GL_BACK); 3069 3070 qglRasterPos2f (lastz[0]-9, lastz[1]-9); 3071 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r); 3072 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR); 3073 3074 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50); 3075 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r); 3076 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR); 3077 3078 // 3079 // draw the new icons 3080 // 3081 qglDrawBuffer (GL_FRONT); 3082 3083 qglShadeModel (GL_FLAT); 3084 qglDisable(GL_TEXTURE_2D); 3085 qglDisable(GL_TEXTURE_1D); 3086 qglDisable(GL_DEPTH_TEST); 3087 qglDisable(GL_BLEND); 3088 qglColor3f(0, 0, 0); 3089 3090 DrawCameraIcon (); 3091 DrawZIcon (); 3092 3093 qglDrawBuffer (GL_BACK); 3094 qglFinish(); 3095 } 3096 3097 3098 vec3_t& CXYWnd::GetOrigin() 3099 { 3100 return m_vOrigin; 3101 } 3102 3103 void CXYWnd::SetOrigin(vec3_t org) 3104 { 3105 m_vOrigin[0] = org[0]; 3106 m_vOrigin[1] = org[1]; 3107 m_vOrigin[2] = org[2]; 3108 } 3109 3110 void CXYWnd::OnSize(UINT nType, int cx, int cy) 3111 { 3112 CWnd::OnSize(nType, cx, cy); 3113 CRect rect; 3114 GetClientRect(rect); 3115 m_nWidth = rect.Width(); 3116 m_nHeight = rect.Height(); 3117 } 3118 3119 brush_t hold_brushes; 3120 void CXYWnd::Clip() 3121 { 3122 if (ClipMode()) 3123 { 3124 hold_brushes.next = &hold_brushes; 3125 ProduceSplitLists(); 3126 //brush_t* pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits; 3127 brush_t* pList; 3128 if (g_PrefsDlg.m_bSwitchClip) 3129 pList = ( (m_nViewType == XZ) ? g_bSwitch: !g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits; 3130 else 3131 pList = ( (m_nViewType == XZ) ? !g_bSwitch: g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits; 3132 3133 3134 if (pList->next != pList) 3135 { 3136 Brush_CopyList(pList, &hold_brushes); 3137 CleanList(&g_brFrontSplits); 3138 CleanList(&g_brBackSplits); 3139 Select_Delete(); 3140 Brush_CopyList(&hold_brushes, &selected_brushes); 3141 if (RogueClipMode()) 3142 RetainClipMode(false); 3143 else 3144 RetainClipMode(true); 3145 Sys_UpdateWindows(W_ALL); 3146 } 3147 } 3148 else if (PathMode()) 3149 { 3150 FinishSmartCreation(); 3151 if (g_pPathFunc) 3152 g_pPathFunc(true, g_nPathCount); 3153 g_pPathFunc = NULL; 3154 g_nPathCount = 0; 3155 g_bPathMode = false; 3156 } 3157 } 3158 3159 void CXYWnd::SplitClip() 3160 { 3161 ProduceSplitLists(); 3162 if ((g_brFrontSplits.next != &g_brFrontSplits) && 3163 (g_brBackSplits.next != &g_brBackSplits)) 3164 { 3165 Select_Delete(); 3166 Brush_CopyList(&g_brFrontSplits, &selected_brushes); 3167 Brush_CopyList(&g_brBackSplits, &selected_brushes); 3168 CleanList(&g_brFrontSplits); 3169 CleanList(&g_brBackSplits); 3170 if (RogueClipMode()) 3171 RetainClipMode(false); 3172 else 3173 RetainClipMode(true); 3174 } 3175 } 3176 3177 void CXYWnd::FlipClip() 3178 { 3179 g_bSwitch = !g_bSwitch; 3180 Sys_UpdateWindows(XY | W_CAMERA_IFON); 3181 } 3182 3183 3184 // makes sure the selected brush or camera is in view 3185 void CXYWnd::PositionView() 3186 { 3187 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 3188 int nDim2 = (m_nViewType == XY) ? 1 : 2; 3189 brush_t* b = selected_brushes.next; 3190 if (b && b->next != b) 3191 { 3192 m_vOrigin[nDim1] = b->mins[nDim1]; 3193 m_vOrigin[nDim2] = b->mins[nDim2]; 3194 } 3195 else 3196 { 3197 m_vOrigin[nDim1] = g_pParentWnd->GetCamera()->Camera().origin[nDim1]; 3198 m_vOrigin[nDim2] = g_pParentWnd->GetCamera()->Camera().origin[nDim2]; 3199 } 3200 } 3201 3202 void CXYWnd::VectorCopyXY(vec3_t in, vec3_t out) 3203 { 3204 if (m_nViewType == XY) 3205 { 3206 out[0] = in[0]; 3207 out[1] = in[1]; 3208 } 3209 else 3210 if (m_nViewType == XZ) 3211 { 3212 out[0] = in[0]; 3213 out[2] = in[2]; 3214 } 3215 else 3216 { 3217 out[1] = in[1]; 3218 out[2] = in[2]; 3219 } 3220 } 3221 3222 3223 void CXYWnd::OnDestroy() 3224 { 3225 QEW_StopGL( GetSafeHwnd(), s_hglrcXY, s_hdcXY ); 3226 CWnd::OnDestroy(); 3227 // delete this; 3228 } 3229 3230 void CXYWnd::SetViewType(int n) 3231 { 3232 m_nViewType = n; 3233 if (g_pParentWnd->CurrentStyle() == QR_QE4) 3234 { 3235 CString str = "YZ Side"; 3236 if (m_nViewType == XY) 3237 str = "XY Top"; 3238 else if (m_nViewType == XZ) 3239 str = "XZ Front"; 3240 SetWindowText(str); 3241 } 3242 }; 3243 3244 void CXYWnd::Redraw(unsigned int nBits) 3245 { 3246 m_nUpdateBits = nBits; 3247 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); 3248 m_nUpdateBits = W_XY; 3249 } 3250 3251 bool CXYWnd::RotateMode() 3252 { 3253 return g_bRotateMode; 3254 } 3255 3256 bool CXYWnd::ScaleMode() 3257 { 3258 return g_bScaleMode; 3259 } 3260 3261 bool CXYWnd::SetRotateMode(bool bMode) 3262 { 3263 if (bMode && selected_brushes.next != &selected_brushes) 3264 { 3265 g_bRotateMode = true; 3266 Select_GetTrueMid(g_vRotateOrigin); 3267 g_vRotation[0] = g_vRotation[1] = g_vRotation[2] = 0.0; 3268 } 3269 else 3270 { 3271 if (bMode) 3272 Sys_Printf("Need a brush selected to turn on Mouse Rotation mode\n"); 3273 g_bRotateMode = false; 3274 } 3275 RedrawWindow(); 3276 return g_bRotateMode; 3277 } 3278 3279 void CXYWnd::SetScaleMode(bool bMode) 3280 { 3281 g_bScaleMode = bMode; 3282 RedrawWindow(); 3283 } 3284 3285 3286 3287 3288 // xy - z 3289 // xz - y 3290 // yz - x 3291 3292 void CXYWnd::OnSelectMouserotate() 3293 { 3294 // TODO: Add your command handler code here 3295 3296 } 3297 3298 void CleanCopyEntities() 3299 { 3300 entity_t* pe = g_enClipboard.next; 3301 while (pe != NULL && pe != &g_enClipboard) 3302 { 3303 entity_t* next = pe->next; 3304 epair_t* enext = NULL; 3305 for (epair_t* ep = pe->epairs ; ep ; ep=enext) 3306 { 3307 enext = ep->next; 3308 free (ep->key); 3309 free (ep->value); 3310 free (ep); 3311 } 3312 free (pe); 3313 pe = next; 3314 } 3315 g_enClipboard.next = g_enClipboard.prev = &g_enClipboard; 3316 } 3317 3318 entity_t *Entity_CopyClone (entity_t *e) 3319 { 3320 entity_t *n; 3321 epair_t *ep, *np; 3322 3323 n = (entity_t*)qmalloc(sizeof(*n)); 3324 n->brushes.onext = n->brushes.oprev = &n->brushes; 3325 n->eclass = e->eclass; 3326 3327 // add the entity to the entity list 3328 n->next = g_enClipboard.next; 3329 g_enClipboard.next = n; 3330 n->next->prev = n; 3331 n->prev = &g_enClipboard; 3332 3333 for (ep = e->epairs ; ep ; ep=ep->next) 3334 { 3335 np = (epair_t*)qmalloc(sizeof(*np)); 3336 np->key = copystring(ep->key); 3337 np->value = copystring(ep->value); 3338 np->next = n->epairs; 3339 n->epairs = np; 3340 } 3341 return n; 3342 } 3343 3344 bool OnList(entity_t* pFind, CPtrArray* pList) 3345 { 3346 int nSize = pList->GetSize(); 3347 while (nSize-- > 0) 3348 { 3349 entity_t* pEntity = reinterpret_cast<entity_t*>(pList->GetAt(nSize)); 3350 if (pEntity == pFind) 3351 return true; 3352 } 3353 return false; 3354 } 3355 3356 void CXYWnd::Copy() 3357 { 3358 #if 1 3359 CWaitCursor WaitCursor; 3360 g_Clipboard.SetLength(0); 3361 g_PatchClipboard.SetLength(0); 3362 3363 Map_SaveSelected(&g_Clipboard, &g_PatchClipboard); 3364 bool bClipped = false; 3365 UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings"); 3366 if (nClipboard > 0) 3367 { 3368 if (OpenClipboard()) 3369 { 3370 ::EmptyClipboard(); 3371 long lSize = g_Clipboard.GetLength(); 3372 HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, lSize + sizeof(long)); 3373 if (h != NULL) 3374 { 3375 unsigned char *cp = reinterpret_cast<unsigned char*>(::GlobalLock(h)); 3376 memcpy(cp, &lSize, sizeof(long)); 3377 cp += sizeof(long); 3378 g_Clipboard.SeekToBegin(); 3379 g_Clipboard.Read(cp, lSize); 3380 ::GlobalUnlock(h); 3381 ::SetClipboardData(nClipboard, h); 3382 ::CloseClipboard(); 3383 bClipped = true; 3384 } 3385 } 3386 } 3387 3388 if (!bClipped) 3389 { 3390 Sys_Printf("Unable to register Windows clipboard formats, copy/paste between editors will not be possible"); 3391 } 3392 3393 /* 3394 CString strOut; 3395 ::GetTempPath(1024, strOut.GetBuffer(1024)); 3396 strOut.ReleaseBuffer(); 3397 AddSlash(strOut); 3398 strOut += "RadiantClipboard.$$$"; 3399 Map_SaveSelected(strOut.GetBuffer(0)); 3400 */ 3401 3402 #else 3403 CPtrArray holdArray; 3404 CleanList(&g_brClipboard); 3405 CleanCopyEntities(); 3406 for (brush_t* pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next) 3407 { 3408 if (pBrush->owner == world_entity) 3409 { 3410 brush_t* pClone = Brush_Clone(pBrush); 3411 pClone->owner = NULL; 3412 Brush_AddToList (pClone, &g_brClipboard); 3413 } 3414 else 3415 { 3416 if (!OnList(pBrush->owner, &holdArray)) 3417 { 3418 entity_t* e = pBrush->owner; 3419 holdArray.Add(reinterpret_cast<void*>(e)); 3420 entity_t* pEClone = Entity_CopyClone(e); 3421 for (brush_t* pEB = e->brushes.onext ; pEB != &e->brushes ; pEB=pEB->onext) 3422 { 3423 brush_t* pClone = Brush_Clone(pEB); 3424 //Brush_AddToList (pClone, &g_brClipboard); 3425 Entity_LinkBrush(pEClone, pClone); 3426 Brush_Build(pClone); 3427 } 3428 } 3429 } 3430 } 3431 #endif 3432 } 3433 3434 void CXYWnd::Undo() 3435 { 3436 /* 3437 if (g_brUndo.next != &g_brUndo) 3438 { 3439 g_bScreenUpdates = false; 3440 Select_Delete(); 3441 for (brush_t* pBrush = g_brUndo.next ; pBrush != NULL && pBrush != &g_brUndo ; pBrush=pBrush->next) 3442 { 3443 brush_t* pClone = Brush_Clone(pBrush); 3444 Brush_AddToList (pClone, &active_brushes); 3445 Entity_LinkBrush (pBrush->pUndoOwner, pClone); 3446 Brush_Build(pClone); 3447 Select_Brush(pClone); 3448 } 3449 CleanList(&g_brUndo); 3450 g_bScreenUpdates = true; 3451 Sys_UpdateWindows(W_ALL); 3452 } 3453 else Sys_Printf("Nothing to undo.../n"); 3454 */ 3455 } 3456 3457 void CXYWnd::UndoClear() 3458 { 3459 /* 3460 CleanList(&g_brUndo); 3461 */ 3462 } 3463 3464 void CXYWnd::UndoCopy() 3465 { 3466 /* 3467 CleanList(&g_brUndo); 3468 for (brush_t* pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next) 3469 { 3470 brush_t* pClone = Brush_Clone(pBrush); 3471 pClone->pUndoOwner = pBrush->owner; 3472 Brush_AddToList (pClone, &g_brUndo); 3473 } 3474 */ 3475 } 3476 3477 bool CXYWnd::UndoAvailable() 3478 { 3479 return (g_brUndo.next != &g_brUndo); 3480 } 3481 3482 3483 3484 void CXYWnd::Paste() 3485 { 3486 #if 1 3487 3488 CWaitCursor WaitCursor; 3489 bool bPasted = false; 3490 UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings"); 3491 if (nClipboard > 0 && OpenClipboard() && ::IsClipboardFormatAvailable(nClipboard)) 3492 { 3493 HANDLE h = ::GetClipboardData(nClipboard); 3494 if (h) 3495 { 3496 g_Clipboard.SetLength(0); 3497 unsigned char *cp = reinterpret_cast<unsigned char*>(::GlobalLock(h)); 3498 long lSize = 0; 3499 memcpy(&lSize, cp, sizeof(long)); 3500 cp += sizeof(long); 3501 g_Clipboard.Write(cp, lSize); 3502 } 3503 ::GlobalUnlock(h); 3504 ::CloseClipboard(); 3505 } 3506 3507 if (g_Clipboard.GetLength() > 0) 3508 { 3509 g_Clipboard.SeekToBegin(); 3510 int nLen = g_Clipboard.GetLength(); 3511 char* pBuffer = new char[nLen+1]; 3512 memset( pBuffer, 0, sizeof(pBuffer) ); 3513 g_Clipboard.Read(pBuffer, nLen); 3514 pBuffer[nLen] = '\0'; 3515 Map_ImportBuffer(pBuffer); 3516 delete []pBuffer; 3517 } 3518 3519 #if 0 3520 if (g_PatchClipboard.GetLength() > 0) 3521 { 3522 g_PatchClipboard.SeekToBegin(); 3523 int nLen = g_PatchClipboard.GetLength(); 3524 char* pBuffer = new char[nLen+1]; 3525 g_PatchClipboard.Read(pBuffer, nLen); 3526 pBuffer[nLen] = '\0'; 3527 Patch_ReadBuffer(pBuffer, true); 3528 delete []pBuffer; 3529 } 3530 #endif 3531 3532 #else 3533 if (g_brClipboard.next != &g_brClipboard || g_enClipboard.next != &g_enClipboard) 3534 { 3535 Select_Deselect(); 3536 3537 for (brush_t* pBrush = g_brClipboard.next ; pBrush != NULL && pBrush != &g_brClipboard ; pBrush=pBrush->next) 3538 { 3539 brush_t* pClone = Brush_Clone(pBrush); 3540 //pClone->owner = pBrush->owner; 3541 if (pClone->owner == NULL) 3542 Entity_LinkBrush (world_entity, pClone); 3543 3544 Brush_AddToList (pClone, &selected_brushes); 3545 Brush_Build(pClone); 3546 } 3547 3548 for (entity_t* pEntity = g_enClipboard.next; pEntity != NULL && pEntity != &g_enClipboard; pEntity = pEntity->next) 3549 { 3550 entity_t* pEClone = Entity_Clone(pEntity); 3551 for (brush_t* pEB = pEntity->brushes.onext ; pEB != &pEntity->brushes ; pEB=pEB->onext) 3552 { 3553 brush_t* pClone = Brush_Clone(pEB); 3554 Brush_AddToList (pClone, &selected_brushes); 3555 Entity_LinkBrush(pEClone, pClone); 3556 Brush_Build(pClone); 3557 if (pClone->owner && pClone->owner != world_entity) 3558 { 3559 UpdateEntitySel(pClone->owner->eclass); 3560 } 3561 } 3562 } 3563 3564 Sys_UpdateWindows(W_ALL); 3565 } 3566 else Sys_Printf("Nothing to paste.../n"); 3567 #endif 3568 } 3569 3570 3571 vec3_t& CXYWnd::Rotation() 3572 { 3573 return g_vRotation; 3574 } 3575 3576 vec3_t& CXYWnd::RotateOrigin() 3577 { 3578 return g_vRotateOrigin; 3579 } 3580 3581 3582 void CXYWnd::OnTimer(UINT nIDEvent) 3583 { 3584 int nDim1 = (m_nViewType == YZ) ? 1 : 0; 3585 int nDim2 = (m_nViewType == XY) ? 1 : 2; 3586 m_vOrigin[nDim1] += m_ptDragAdj.x / m_fScale; 3587 m_vOrigin[nDim2] -= m_ptDragAdj.y / m_fScale; 3588 Sys_UpdateWindows(W_XY | W_CAMERA); 3589 //int nH = (m_ptDrag.y == 0) ? -1 : m_ptDrag.y; 3590 m_ptDrag += m_ptDragAdj; 3591 m_ptDragTotal += m_ptDragAdj; 3592 XY_MouseMoved (m_ptDrag.x, m_nHeight - 1 - m_ptDrag.y , m_nScrollFlags); 3593 //m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale; 3594 //m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale; 3595 } 3596 3597 void CXYWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 3598 { 3599 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false); 3600 //CWnd::OnKeyUp(nChar, nRepCnt, nFlags); 3601 } 3602 3603 void CXYWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 3604 { 3605 CWnd::OnNcCalcSize(bCalcValidRects, lpncsp); 3606 } 3607 3608 void CXYWnd::OnKillFocus(CWnd* pNewWnd) 3609 { 3610 CWnd::OnKillFocus(pNewWnd); 3611 SendMessage(WM_NCACTIVATE, FALSE , 0 ); 3612 } 3613 3614 void CXYWnd::OnSetFocus(CWnd* pOldWnd) 3615 { 3616 CWnd::OnSetFocus(pOldWnd); 3617 SendMessage(WM_NCACTIVATE, TRUE , 0 ); 3618 } 3619 3620 void CXYWnd::OnClose() 3621 { 3622 CWnd::OnClose(); 3623 } 3624 3625 // should be static as should be the rotate scale stuff 3626 bool CXYWnd::AreaSelectOK() 3627 { 3628 return RotateMode() ? false : ScaleMode() ? false : true; 3629 }