1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 #include "tools/edit_gui_common.h"
30
31
32 #include "qe3.h"
33 #include "Radiant.h"
34 #include "XYWnd.h"
35 #include "DialogInfo.h"
36 #include "splines.h"
37 #include "../../renderer/tr_local.h"
38 #include "../../renderer/model_local.h" // for idRenderModelLiquid
39
40 #ifdef _DEBUG
41 #define new DEBUG_NEW
42 #undef THIS_FILE
43 static char THIS_FILE[] = __FILE__;
44 #endif
45
46 const char *g_pDimStrings[] = { "x:%.f", "y:%.f", "z:%.f" };
47 const char *g_pOrgStrings[] = { "(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)" };
48 CString g_strDim;
49 CString g_strStatus;
50
51 bool g_bCrossHairs = false;
52 bool g_bScaleMode;
53 int g_nScaleHow;
54 bool g_bRotateMode;
55 bool g_bClipMode;
56 bool g_bRogueClipMode;
57 bool g_bSwitch;
58 CClipPoint g_Clip1;
59 CClipPoint g_Clip2;
60 CClipPoint g_Clip3;
61 CClipPoint *g_pMovingClip;
62 brush_t g_brFrontSplits;
63 brush_t g_brBackSplits;
64
65 brush_t g_brClipboard;
66 brush_t g_brUndo;
67 entity_t g_enClipboard;
68
69 idVec3 g_vRotateOrigin;
70 idVec3 g_vRotation;
71
72 bool g_bPathMode;
73 CClipPoint g_PathPoints[256];
74 CClipPoint *g_pMovingPath;
75 int g_nPathCount;
76 int g_nPathLimit;
77
78 bool g_bSmartGo;
79
80 bool g_bPointMode;
81 CClipPoint g_PointPoints[512];
82 CClipPoint *g_pMovingPoint;
83 int g_nPointCount;
84 int g_nPointLimit;
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 void Select_Ungroup();
93
94 /*
95 =======================================================================================================================
96 =======================================================================================================================
97 */
AcquirePath(int nCount,PFNPathCallback * pFunc)98 void AcquirePath(int nCount, PFNPathCallback *pFunc) {
99 g_nPathCount = 0;
100 g_nPathLimit = nCount;
101 g_pPathFunc = pFunc;
102 g_bPathMode = true;
103 }
104
105 CPtrArray g_ptrMenus;
106
107 CMemFile g_Clipboard(4096);
108 CMemFile g_PatchClipboard(4096);
109
110 extern int pressx;
111 extern int pressy;
112
113 /*
114 =======================================================================================================================
115 =======================================================================================================================
116 */
fDiff(float f1,float f2)117 float fDiff(float f1, float f2) {
118 if (f1 > f2) {
119 return f1 - f2;
120 }
121 else {
122 return f2 - f1;
123 }
124 }
125
126 #define MAX_DRAG_POINTS 128
127
128 CPtrArray dragPoints;
129 static CDragPoint *activeDrag = NULL;
130 static bool activeDragging = false;
131
132 /*
133 =======================================================================================================================
134 =======================================================================================================================
135 */
PointWithin(idVec3 p,int nView)136 bool CDragPoint::PointWithin(idVec3 p, int nView) {
137 if (nView == -1) {
138 if (fDiff(p[0], vec[0]) <= 3 && fDiff(p[1], vec[1]) <= 3 && fDiff(p[2], vec[2]) <= 3) {
139 return true;
140 }
141 }
142 else {
143 int nDim1 = (nView == YZ) ? 1 : 0;
144 int nDim2 = (nView == XY) ? 1 : 2;
145 if (fDiff(p[nDim1], vec[nDim1]) <= 3 && fDiff(p[nDim2], vec[nDim2]) <= 3) {
146 return true;
147 }
148 }
149
150 return false;
151 }
152
153 /*
154 =======================================================================================================================
155 =======================================================================================================================
156 */
PointRay(const idVec3 & org,const idVec3 & dir,float * dist)157 CDragPoint *PointRay(const idVec3 &org, const idVec3 &dir, float *dist) {
158 int i, besti;
159 float d, bestd;
160 idVec3 temp;
161 CDragPoint *drag = NULL;
162 CDragPoint *priority = NULL;
163
164 // find the point closest to the ray
165 float scale = g_pParentWnd->ActiveXY()->Scale();
166 besti = -1;
167 bestd = 12 / scale / 2;
168
169 int count = dragPoints.GetSize();
170 for (i = 0; i < count; i++) {
171 drag = reinterpret_cast < CDragPoint * > (dragPoints[i]);
172 temp = drag->vec - org;
173 d = temp * dir;
174 temp = org + d * dir;
175 temp = drag->vec - temp;
176 d = temp.Length();
177 if ( d < bestd ) {
178 bestd = d;
179 besti = i;
180 if (priority == NULL) {
181 priority = reinterpret_cast < CDragPoint * > (dragPoints[besti]);
182 if (!priority->priority) {
183 priority = NULL;
184 }
185 }
186 }
187 }
188
189 if (besti == -1) {
190 return NULL;
191 }
192
193 drag = reinterpret_cast < CDragPoint * > (dragPoints[besti]);
194 if (priority && !drag->priority) {
195 drag = priority;
196 }
197
198 return drag;
199 }
200
201 /*
202 =======================================================================================================================
203 =======================================================================================================================
204 */
ClearSelectablePoints(brush_t * b)205 void ClearSelectablePoints(brush_t *b) {
206 if (b == NULL) {
207 dragPoints.RemoveAll();
208 }
209 else {
210 CPtrArray ptr;
211 ptr.Copy(dragPoints);
212 dragPoints.RemoveAll();
213
214 int count = ptr.GetSize();
215 for (int i = 0; i < count; i++) {
216 if (b == reinterpret_cast < CDragPoint * > ( ptr.GetAt(i))->pBrush ) {
217 continue;
218 }
219 else {
220 dragPoints.Add(ptr.GetAt(i));
221 }
222 }
223 }
224 }
225
226 /*
227 =======================================================================================================================
228 =======================================================================================================================
229 */
AddSelectablePoint(brush_t * b,idVec3 v,int type,bool priority)230 void AddSelectablePoint(brush_t *b, idVec3 v, int type, bool priority) {
231 dragPoints.Add(new CDragPoint(b, v, type, priority));
232 }
233
234 /*
235 =======================================================================================================================
236 =======================================================================================================================
237 */
UpdateSelectablePoint(brush_t * b,idVec3 v,int type)238 void UpdateSelectablePoint(brush_t *b, idVec3 v, int type) {
239 int count = dragPoints.GetSize();
240 for (int i = 0; i < count; i++) {
241 CDragPoint *drag = reinterpret_cast < CDragPoint * > (dragPoints.GetAt(i));
242 if (b == drag->pBrush && type == drag->nType) {
243 VectorCopy(v, drag->vec);
244 return;
245 }
246 }
247 }
248
249 /*
250 =======================================================================================================================
251 =======================================================================================================================
252 */
VectorToAngles(idVec3 vec,idVec3 angles)253 void VectorToAngles(idVec3 vec, idVec3 angles) {
254 float forward;
255 float yaw, pitch;
256
257 if ((vec[0] == 0) && (vec[1] == 0)) {
258 yaw = 0;
259 if (vec[2] > 0) {
260 pitch = 90;
261 }
262 else {
263 pitch = 270;
264 }
265 }
266 else {
267 yaw = RAD2DEG( atan2(vec[1], vec[0]) );
268 if (yaw < 0) {
269 yaw += 360;
270 }
271
272 forward = (float)idMath::Sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
273 pitch = RAD2DEG( atan2(vec[2], forward) );
274 if (pitch < 0) {
275 pitch += 360;
276 }
277 }
278
279 angles[0] = pitch;
280 angles[1] = yaw;
281 angles[2] = 0;
282 }
283
284 /*
285 =======================================================================================================================
286 RotateLight target is relative to the light origin up and right are relative to the target up and right are
287 perpendicular and are on a plane through the target with the target vector as normal delta is the movement of the
288 target relative to the light
289 =======================================================================================================================
290 */
VectorSnapGrid(idVec3 & v)291 void VectorSnapGrid(idVec3 &v) {
292 v.x = floor(v.x / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
293 v.y = floor(v.y / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
294 v.z = floor(v.z / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
295 }
296
297 /*
298 =======================================================================================================================
299 =======================================================================================================================
300 */
RotateLight(idVec3 & target,idVec3 & up,idVec3 & right,const idVec3 & delta)301 static void RotateLight(idVec3 &target, idVec3 &up, idVec3 &right, const idVec3 &delta) {
302 idVec3 newtarget, cross, dst;
303 idVec3 normal;
304 double angle, dist, d, len;
305 idMat3 rot;
306
307 // calculate new target
308 newtarget = target + delta;
309
310 // get the up and right vector relative to the light origin
311 up += target;
312 right += target;
313
314 len = target.Length() * newtarget.Length();
315
316 if (len > 0.1) {
317 // calculate the rotation angle between the vectors
318 double dp = target * newtarget;
319 double dv = dp / len;
320
321 angle = RAD2DEG( idMath::ACos( dv ) );
322
323 // get a vector orthogonal to the rotation plane
324 cross = target.Cross( newtarget );
325 cross.Normalize();
326
327 if (cross[0] || cross[1] || cross[2]) {
328 // build the rotation matrix
329 rot = idRotation( vec3_origin, cross, angle ).ToMat3();
330
331 rot.ProjectVector(target, dst);
332 target = dst;
333 rot.ProjectVector( up, dst );
334 up = dst;
335 rot.ProjectVector( right, dst);
336 right = dst;
337 }
338 }
339
340 //
341 // project the up and right vectors onto a plane that goes through the target and
342 // has normal vector target.Normalize()
343 //
344 normal = target;
345 normal.Normalize();
346 dist = normal * target;
347
348 d = (normal * up) - dist;
349 up -= d * normal;
350
351 d = (normal * right) - dist;
352 right -= d * normal;
353
354 //
355 // FIXME: maybe calculate the right vector with a cross product between the target
356 // and up vector, just to make sure the up and right vectors are perpendicular
357 // get the up and right vectors relative to the target
358 //
359 up -= target;
360 right -= target;
361
362 // move the target in the (target - light_origin) direction
363 target = newtarget;
364 VectorSnapGrid(target);
365 VectorSnapGrid(up);
366 VectorSnapGrid(right);
367 }
368
369 /*
370 =======================================================================================================================
371 =======================================================================================================================
372 */
373 extern idVec3 Brush_TransformedPoint(brush_t *b, const idVec3 &in);
374 extern idMat3 Brush_RotationMatrix(brush_t *b);
UpdateActiveDragPoint(const idVec3 & move)375 bool UpdateActiveDragPoint(const idVec3 &move) {
376 if (activeDrag) {
377 idMat3 mat = Brush_RotationMatrix(activeDrag->pBrush);
378 idMat3 invmat = mat.Transpose();
379 idVec3 target, up, right, start, end;
380 CString str;
381 if (activeDrag->nType == LIGHT_TARGET) {
382 GetVectorForKey(activeDrag->pBrush->owner, "light_target", target);
383 GetVectorForKey(activeDrag->pBrush->owner, "light_up", up);
384 GetVectorForKey(activeDrag->pBrush->owner, "light_right", right);
385 target *= mat;
386 up *= mat;
387 right *= mat;
388 RotateLight(target, up, right, move);
389 target *= invmat;
390 up *= invmat;
391 right *= invmat;
392 SetKeyVec3(activeDrag->pBrush->owner, "light_target", target);
393 SetKeyVec3(activeDrag->pBrush->owner, "light_up", up);
394 SetKeyVec3(activeDrag->pBrush->owner, "light_right", right);
395 target += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
396 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush, target), LIGHT_TARGET);
397 up += target;
398 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,up), LIGHT_UP);
399 right += target;
400 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,right), LIGHT_RIGHT);
401 }
402 else if (activeDrag->nType == LIGHT_UP) {
403 GetVectorForKey(activeDrag->pBrush->owner, "light_up", up);
404 up *= mat;
405 up += move;
406 up *= invmat;
407 SetKeyVec3(activeDrag->pBrush->owner, "light_up", up);
408 GetVectorForKey(activeDrag->pBrush->owner, "light_target", target);
409 target += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
410 up += target;
411 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,up), LIGHT_UP);
412 }
413 else if (activeDrag->nType == LIGHT_RIGHT) {
414 GetVectorForKey(activeDrag->pBrush->owner, "light_right", right);
415 right *= mat;
416 right += move;
417 right *= invmat;
418 SetKeyVec3(activeDrag->pBrush->owner, "light_right", right);
419 GetVectorForKey(activeDrag->pBrush->owner, "light_target", target);
420 target += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
421 right += target;
422 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,right), LIGHT_RIGHT);
423 }
424 else if (activeDrag->nType == LIGHT_START) {
425 GetVectorForKey(activeDrag->pBrush->owner, "light_start", start);
426 start *= mat;
427 start += move;
428 start *= invmat;
429 SetKeyVec3(activeDrag->pBrush->owner, "light_start", start);
430 start += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
431 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,start), LIGHT_START);
432 }
433 else if (activeDrag->nType == LIGHT_END) {
434 GetVectorForKey(activeDrag->pBrush->owner, "light_end", end);
435 end *= mat;
436 end += move;
437 end *= invmat;
438 SetKeyVec3(activeDrag->pBrush->owner, "light_end", end);
439 end += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
440 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush,end), LIGHT_END);
441 }
442 else if (activeDrag->nType == LIGHT_CENTER) {
443 GetVectorForKey(activeDrag->pBrush->owner, "light_center", end);
444 end *= mat;
445 end += move;
446 end *= invmat;
447 SetKeyVec3(activeDrag->pBrush->owner, "light_center", end);
448 end += (activeDrag->pBrush->trackLightOrigin) ? activeDrag->pBrush->owner->lightOrigin : activeDrag->pBrush->owner->origin;
449 UpdateSelectablePoint(activeDrag->pBrush, Brush_TransformedPoint(activeDrag->pBrush, end), LIGHT_CENTER);
450 }
451
452 // FIXME: just build the frustrum values
453 Brush_Build(activeDrag->pBrush);
454 return true;
455 }
456
457 return false;
458 }
459
460 /*
461 =======================================================================================================================
462 =======================================================================================================================
463 */
SetDragPointCursor(idVec3 p,int nView)464 bool SetDragPointCursor(idVec3 p, int nView) {
465 activeDrag = NULL;
466
467 int numDragPoints = dragPoints.GetSize();
468 for (int i = 0; i < numDragPoints; i++) {
469 if (reinterpret_cast < CDragPoint * > (dragPoints[i])->PointWithin(p, nView)) {
470 activeDrag = reinterpret_cast < CDragPoint * > (dragPoints[i]);
471 return true;
472 }
473 }
474
475 return false;
476 }
477
478 /*
479 =======================================================================================================================
480 =======================================================================================================================
481 */
SetActiveDrag(CDragPoint * p)482 void SetActiveDrag(CDragPoint *p) {
483 activeDrag = p;
484 }
485
486 /*
487 =======================================================================================================================
488 =======================================================================================================================
489 */
ClearActiveDrag()490 void ClearActiveDrag() {
491 activeDrag = NULL;
492 }
493
494 // CXYWnd
495 IMPLEMENT_DYNCREATE(CXYWnd, CWnd);
496
497 /*
498 =======================================================================================================================
499 =======================================================================================================================
500 */
CXYWnd()501 CXYWnd::CXYWnd() {
502 g_brClipboard.next = &g_brClipboard;
503 g_brUndo.next = &g_brUndo;
504 g_nScaleHow = 0;
505 g_bRotateMode = false;
506 g_bClipMode = false;
507 g_bRogueClipMode = false;
508 g_bSwitch = true;
509 g_pMovingClip = NULL;
510 g_pMovingPath = NULL;
511 g_brFrontSplits.next = &g_brFrontSplits;
512 g_brBackSplits.next = &g_brBackSplits;
513 m_bActive = false;
514
515 m_bRButtonDown = false;
516 m_nUpdateBits = W_XY;
517 g_bPathMode = false;
518 g_nPathCount = 0;
519 g_nPathLimit = 0;
520 m_nTimerID = -1;
521 m_nButtonstate = 0;
522 XY_Init();
523 }
524
525 /*
526 =======================================================================================================================
527 =======================================================================================================================
528 */
~CXYWnd()529 CXYWnd::~CXYWnd() {
530 int nSize = g_ptrMenus.GetSize();
531 while (nSize > 0) {
532 CMenu *pMenu = reinterpret_cast < CMenu * > (g_ptrMenus.GetAt(nSize - 1));
533 ASSERT(pMenu);
534 pMenu->DestroyMenu();
535 delete pMenu;
536 nSize--;
537 }
538
539 g_ptrMenus.RemoveAll();
540 m_mnuDrop.DestroyMenu();
541 }
542
543 BEGIN_MESSAGE_MAP(CXYWnd, CWnd)
544 //{{AFX_MSG_MAP(CXYWnd)
545 ON_WM_CREATE()
546 ON_WM_LBUTTONDOWN()
547 ON_WM_MBUTTONDOWN()
548 ON_WM_RBUTTONDOWN()
549 ON_WM_LBUTTONUP()
550 ON_WM_MBUTTONUP()
551 ON_WM_RBUTTONUP()
552 ON_WM_MOUSEMOVE()
553 ON_WM_PAINT()
554 ON_WM_KEYDOWN()
555 ON_WM_SIZE()
556 ON_WM_DESTROY()
557 ON_COMMAND(ID_SELECT_MOUSEROTATE, OnSelectMouserotate)
558 ON_WM_TIMER()
559 ON_WM_KEYUP()
560 ON_WM_NCCALCSIZE()
561 ON_WM_KILLFOCUS()
562 ON_WM_SETFOCUS()
563 ON_WM_CLOSE()
564 ON_WM_ERASEBKGND()
565 ON_WM_MOUSEWHEEL()
566 ON_COMMAND(ID_DROP_NEWMODEL, OnDropNewmodel)
567 //}}AFX_MSG_MAP
568 ON_COMMAND_RANGE(ID_ENTITY_START, ID_ENTITY_END, OnEntityCreate)
569 END_MESSAGE_MAP()
570 // CXYWnd message handlers
571 LONG WINAPI XYWndProc(HWND, UINT, WPARAM, LPARAM);
572
573 /*
574 =======================================================================================================================
575 =======================================================================================================================
576 */
PreCreateWindow(CREATESTRUCT & cs)577 BOOL CXYWnd::PreCreateWindow(CREATESTRUCT &cs) {
578 WNDCLASS wc;
579 HINSTANCE hInstance = AfxGetInstanceHandle();
580 if (::GetClassInfo(hInstance, XY_WINDOW_CLASS, &wc) == FALSE) {
581 // Register a new class
582 memset(&wc, 0, sizeof(wc));
583 wc.style = CS_NOCLOSE;
584 wc.lpszClassName = XY_WINDOW_CLASS;
585 wc.hCursor = NULL; // LoadCursor (NULL,IDC_ARROW);
586 wc.lpfnWndProc = ::DefWindowProc;
587 if (AfxRegisterClass(&wc) == FALSE) {
588 Error("CCamWnd RegisterClass: failed");
589 }
590 }
591
592 cs.lpszClass = XY_WINDOW_CLASS;
593 cs.lpszName = "VIEW";
594 if (cs.style != QE3_CHILDSTYLE) {
595 cs.style = QE3_SPLITTER_STYLE;
596 }
597
598 return CWnd::PreCreateWindow(cs);
599 }
600
601 HDC s_hdcXY;
602 HGLRC s_hglrcXY;
603
604 static unsigned s_stipple[32] = {
605 0xaaaaaaaa,
606 0x55555555,
607 0xaaaaaaaa,
608 0x55555555,
609 0xaaaaaaaa,
610 0x55555555,
611 0xaaaaaaaa,
612 0x55555555,
613 0xaaaaaaaa,
614 0x55555555,
615 0xaaaaaaaa,
616 0x55555555,
617 0xaaaaaaaa,
618 0x55555555,
619 0xaaaaaaaa,
620 0x55555555,
621 0xaaaaaaaa,
622 0x55555555,
623 0xaaaaaaaa,
624 0x55555555,
625 0xaaaaaaaa,
626 0x55555555,
627 0xaaaaaaaa,
628 0x55555555,
629 0xaaaaaaaa,
630 0x55555555,
631 0xaaaaaaaa,
632 0x55555555,
633 0xaaaaaaaa,
634 0x55555555,
635 0xaaaaaaaa,
636 0x55555555,
637 };
638
639 /*
640 =======================================================================================================================
641 WXY_WndProc
642 =======================================================================================================================
643 */
XYWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)644 LONG WINAPI XYWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
645 switch (uMsg)
646 {
647 case WM_DESTROY:
648 return 0;
649
650 case WM_NCCALCSIZE: // don't let windows copy pixels
651 DefWindowProc(hWnd, uMsg, wParam, lParam);
652 return WVR_REDRAW;
653
654 case WM_KILLFOCUS:
655 case WM_SETFOCUS:
656 SendMessage(hWnd, WM_NCACTIVATE, uMsg == WM_SETFOCUS, 0);
657 return 0;
658
659 case WM_CLOSE:
660 DestroyWindow(hWnd);
661 return 0;
662 }
663
664 return DefWindowProc(hWnd, uMsg, wParam, lParam);
665 }
666
667 /*
668 =======================================================================================================================
669 =======================================================================================================================
670 */
WXY_InitPixelFormat(PIXELFORMATDESCRIPTOR * pPFD)671 static void WXY_InitPixelFormat(PIXELFORMATDESCRIPTOR *pPFD) {
672 memset(pPFD, 0, sizeof(*pPFD));
673
674 pPFD->nSize = sizeof(PIXELFORMATDESCRIPTOR);
675 pPFD->nVersion = 1;
676 pPFD->dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
677 pPFD->iPixelType = PFD_TYPE_RGBA;
678 pPFD->cColorBits = 24;
679 pPFD->cDepthBits = 32;
680 pPFD->iLayerType = PFD_MAIN_PLANE;
681 }
682
683 /*
684 =======================================================================================================================
685 =======================================================================================================================
686 */
WXY_Print(void)687 void WXY_Print(void) {
688 DOCINFO di;
689
690 PRINTDLG pd;
691
692 /* initialize the PRINTDLG struct and execute it */
693 memset(&pd, 0, sizeof(pd));
694 pd.lStructSize = sizeof(pd);
695 pd.hwndOwner = g_pParentWnd->GetXYWnd()->GetSafeHwnd();
696 pd.Flags = PD_RETURNDC;
697 pd.hInstance = 0;
698 if (!PrintDlg(&pd) || !pd.hDC) {
699 g_pParentWnd->MessageBox("Could not PrintDlg()", "QE4 Print Error", MB_OK | MB_ICONERROR);
700 return;
701 }
702
703 /* StartDoc */
704 memset(&di, 0, sizeof(di));
705 di.cbSize = sizeof(di);
706 di.lpszDocName = "QE4";
707 if (StartDoc(pd.hDC, &di) <= 0) {
708 g_pParentWnd->MessageBox("Could not StartDoc()", "QE4 Print Error", MB_OK | MB_ICONERROR);
709 return;
710 }
711
712 /* StartPage */
713 if (StartPage(pd.hDC) <= 0) {
714 g_pParentWnd->MessageBox("Could not StartPage()", "QE4 Print Error", MB_OK | MB_ICONERROR);
715 return;
716 } { /* read pixels from the XY window */
717 int bmwidth = 320, bmheight = 320;
718 int pwidth, pheight;
719
720 RECT r;
721
722 GetWindowRect(g_pParentWnd->GetXYWnd()->GetSafeHwnd(), &r);
723
724 bmwidth = r.right - r.left;
725 bmheight = r.bottom - r.top;
726
727 pwidth = GetDeviceCaps(pd.hDC, PHYSICALWIDTH) - GetDeviceCaps(pd.hDC, PHYSICALOFFSETX);
728 pheight = GetDeviceCaps(pd.hDC, PHYSICALHEIGHT) - GetDeviceCaps(pd.hDC, PHYSICALOFFSETY);
729
730 StretchBlt(pd.hDC, 0, 0, pwidth, pheight, s_hdcXY, 0, 0, bmwidth, bmheight, SRCCOPY);
731 }
732
733 /* EndPage and EndDoc */
734 if (EndPage(pd.hDC) <= 0) {
735 g_pParentWnd->MessageBox("QE4 Print Error", "Could not EndPage()", MB_OK | MB_ICONERROR);
736 return;
737 }
738
739 if (EndDoc(pd.hDC) <= 0) {
740 g_pParentWnd->MessageBox("QE4 Print Error", "Could not EndDoc()", MB_OK | MB_ICONERROR);
741 return;
742 }
743 }
744
745 /*
746 =======================================================================================================================
747 =======================================================================================================================
748 */
OnCreate(LPCREATESTRUCT lpCreateStruct)749 int CXYWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
750 if (CWnd::OnCreate(lpCreateStruct) == -1) {
751 return -1;
752 }
753
754 s_hdcXY = ::GetDC(GetSafeHwnd());
755 QEW_SetupPixelFormat(s_hdcXY, false);
756
757 qglPolygonStipple((unsigned char *)s_stipple);
758 qglLineStipple(3, 0xaaaa);
759 return 0;
760 }
761
762 /*
763 =======================================================================================================================
764 =======================================================================================================================
765 */
ptSum(idVec3 pt)766 float ptSum(idVec3 pt) {
767 return pt[0] + pt[1] + pt[2];
768 }
769
770 /*
771 =======================================================================================================================
772 =======================================================================================================================
773 */
DropClipPoint(UINT nFlags,CPoint point)774 void CXYWnd::DropClipPoint(UINT nFlags, CPoint point) {
775 CRect rctZ;
776 GetClientRect(rctZ);
777 if (g_pMovingClip) {
778 SetCapture();
779 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, *g_pMovingClip);
780 }
781 else {
782 idVec3 *pPt = NULL;
783 if (g_Clip1.Set() == false) {
784 pPt = g_Clip1;
785 g_Clip1.Set(true);
786 g_Clip1.m_ptScreen = point;
787 }
788 else if (g_Clip2.Set() == false) {
789 pPt = g_Clip2;
790 g_Clip2.Set(true);
791 g_Clip2.m_ptScreen = point;
792 }
793 else if (g_Clip3.Set() == false) {
794 pPt = g_Clip3;
795 g_Clip3.Set(true);
796 g_Clip3.m_ptScreen = point;
797 }
798 else {
799 RetainClipMode(true);
800 pPt = g_Clip1;
801 g_Clip1.Set(true);
802 g_Clip1.m_ptScreen = point;
803 }
804
805 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, *pPt);
806
807 // Put the off-viewaxis coordinate at the top or bottom of selected brushes
808 if ( GetAsyncKeyState(VK_CONTROL) & 0x8000 ) {
809 if ( selected_brushes.next != &selected_brushes ) {
810 idVec3 smins, smaxs;
811 Select_GetBounds( smins, smaxs );
812
813 if ( m_nViewType == XY ) {
814 if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
815 pPt->z = smaxs.z;
816 } else {
817 pPt->z = smins.z;
818 }
819 } else if ( m_nViewType == YZ ) {
820 if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
821 pPt->x = smaxs.x;
822 } else {
823 pPt->x = smins.x;
824 }
825 } else {
826 if ( GetAsyncKeyState(VK_SHIFT) & 0x8000 ) {
827 pPt->y = smaxs.y;
828 } else {
829 pPt->y = smins.y;
830 }
831 }
832 }
833 }
834 }
835
836 Sys_UpdateWindows(XY | W_CAMERA_IFON);
837 }
838
839 /*
840 =======================================================================================================================
841 =======================================================================================================================
842 */
DropPathPoint(UINT nFlags,CPoint point)843 void CXYWnd::DropPathPoint(UINT nFlags, CPoint point) {
844 CRect rctZ;
845 GetClientRect(rctZ);
846 if (g_pMovingPath) {
847 SetCapture();
848 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, *g_pMovingPath);
849 }
850 else {
851 g_PathPoints[g_nPathCount].Set(true);
852 g_PathPoints[g_nPathCount].m_ptScreen = point;
853 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, g_PathPoints[g_nPathCount]);
854 g_nPathCount++;
855 if (g_nPathCount == g_nPathLimit) {
856 if (g_pPathFunc) {
857 g_pPathFunc(true, g_nPathCount);
858 }
859
860 g_nPathCount = 0;
861 g_bPathMode = false;
862 g_pPathFunc = NULL;
863 }
864 }
865
866 Sys_UpdateWindows(XY | W_CAMERA_IFON);
867 }
868
869 /*
870 =======================================================================================================================
871 =======================================================================================================================
872 */
AddPointPoint(UINT nFlags,idVec3 * pVec)873 void CXYWnd::AddPointPoint(UINT nFlags, idVec3 *pVec) {
874 g_PointPoints[g_nPointCount].Set(true);
875
876 // g_PointPoints[g_nPointCount].m_ptScreen = point;
877 g_PointPoints[g_nPointCount].m_ptClip = *pVec;
878 g_PointPoints[g_nPointCount].SetPointPtr(pVec);
879 g_nPointCount++;
880 Sys_UpdateWindows(XY | W_CAMERA_IFON);
881 }
882
883 /*
884 =======================================================================================================================
885 =======================================================================================================================
886 */
OnLButtonDown(UINT nFlags,CPoint point)887 void CXYWnd::OnLButtonDown(UINT nFlags, CPoint point) {
888 g_pParentWnd->SetActiveXY(this);
889 UndoCopy();
890
891 if (g_pParentWnd->GetNurbMode()) {
892 int i, num = g_pParentWnd->GetNurb()->GetNumValues();
893 idList<idVec2> temp;
894 for (i = 0; i < num; i++) {
895 temp.Append(g_pParentWnd->GetNurb()->GetValue(i));
896 }
897 CRect rctZ;
898 GetClientRect(rctZ);
899 idVec3 v3;
900 SnapToPoint(point.x, rctZ.Height() - 1 - point.y, v3);
901 temp.Append(idVec2(v3.x, v3.y));
902 num++;
903 g_pParentWnd->GetNurb()->Clear();
904 for (i = 0; i < num; i++) {
905 g_pParentWnd->GetNurb()->AddValue((1000 * i)/num, temp[i]);
906 }
907 }
908 if (ClipMode() && !RogueClipMode()) {
909 DropClipPoint(nFlags, point);
910 }
911 else if (PathMode()) {
912 DropPathPoint(nFlags, point);
913 }
914 else {
915 OriginalButtonDown(nFlags, point);
916 }
917 }
918
919 /*
920 =======================================================================================================================
921 =======================================================================================================================
922 */
OnMButtonDown(UINT nFlags,CPoint point)923 void CXYWnd::OnMButtonDown(UINT nFlags, CPoint point) {
924 OriginalButtonDown(nFlags, point);
925 }
926
927 /*
928 =======================================================================================================================
929 =======================================================================================================================
930 */
Betwixt(float f1,float f2)931 float Betwixt(float f1, float f2) {
932 if (f1 > f2) {
933 return f2 + ((f1 - f2) / 2);
934 }
935 else {
936 return f1 + ((f2 - f1) / 2);
937 }
938 }
939
940 /*
941 =======================================================================================================================
942 =======================================================================================================================
943 */
ProduceSplits(brush_t ** pFront,brush_t ** pBack)944 void CXYWnd::ProduceSplits(brush_t **pFront, brush_t **pBack) {
945 *pFront = NULL;
946 *pBack = NULL;
947 if (ClipMode()) {
948 if (g_Clip1.Set() && g_Clip2.Set()) {
949 face_t face;
950 VectorCopy(g_Clip1.m_ptClip, face.planepts[0]);
951 VectorCopy(g_Clip2.m_ptClip, face.planepts[1]);
952 VectorCopy(g_Clip3.m_ptClip, face.planepts[2]);
953 if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes)) {
954 if (g_Clip3.Set() == false) {
955 if (m_nViewType == XY) {
956 face.planepts[0][2] = selected_brushes.next->mins[2];
957 face.planepts[1][2] = selected_brushes.next->mins[2];
958 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
959 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
960 face.planepts[2][2] = selected_brushes.next->maxs[2];
961 }
962 else if (m_nViewType == YZ) {
963 face.planepts[0][0] = selected_brushes.next->mins[0];
964 face.planepts[1][0] = selected_brushes.next->mins[0];
965 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
966 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
967 face.planepts[2][0] = selected_brushes.next->maxs[0];
968 }
969 else {
970 face.planepts[0][1] = selected_brushes.next->mins[1];
971 face.planepts[1][1] = selected_brushes.next->mins[1];
972 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
973 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
974 face.planepts[2][1] = selected_brushes.next->maxs[1];
975 }
976 }
977
978 Brush_SplitBrushByFace(selected_brushes.next, &face, pFront, pBack);
979 }
980 }
981 }
982 }
983
984 /*
985 =======================================================================================================================
986 =======================================================================================================================
987 */
CleanList(brush_t * pList)988 void CleanList(brush_t *pList) {
989 brush_t *pBrush = pList->next;
990 while (pBrush != NULL && pBrush != pList) {
991 brush_t *pNext = pBrush->next;
992 Brush_Free(pBrush);
993 pBrush = pNext;
994 }
995 }
996
997 /*
998 =======================================================================================================================
999 =======================================================================================================================
1000 */
ProduceSplitLists()1001 void CXYWnd::ProduceSplitLists() {
1002 if (AnyPatchesSelected()) {
1003 Sys_Status("Deslecting patches for clip operation.\n");
1004
1005 brush_t *next;
1006 for (brush_t * pb = selected_brushes.next; pb != &selected_brushes; pb = next) {
1007 next = pb->next;
1008 if (pb->pPatch) {
1009 Brush_RemoveFromList(pb);
1010 Brush_AddToList(pb, &active_brushes);
1011 UpdatePatchInspector();
1012 }
1013 }
1014 }
1015
1016 CleanList(&g_brFrontSplits);
1017 CleanList(&g_brBackSplits);
1018 g_brFrontSplits.next = &g_brFrontSplits;
1019 g_brBackSplits.next = &g_brBackSplits;
1020
1021 brush_t *pBrush;
1022 for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next) {
1023 brush_t *pFront = NULL;
1024 brush_t *pBack = NULL;
1025 if (ClipMode()) {
1026 if (g_Clip1.Set() && g_Clip2.Set()) {
1027 face_t face;
1028 VectorCopy(g_Clip1.m_ptClip, face.planepts[0]);
1029 VectorCopy(g_Clip2.m_ptClip, face.planepts[1]);
1030 VectorCopy(g_Clip3.m_ptClip, face.planepts[2]);
1031 if (g_Clip3.Set() == false) {
1032 if (g_pParentWnd->ActiveXY()->GetViewType() == XY) {
1033 face.planepts[0][2] = pBrush->mins[2];
1034 face.planepts[1][2] = pBrush->mins[2];
1035 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
1036 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
1037 face.planepts[2][2] = pBrush->maxs[2];
1038 }
1039 else if (g_pParentWnd->ActiveXY()->GetViewType() == YZ) {
1040 face.planepts[0][0] = pBrush->mins[0];
1041 face.planepts[1][0] = pBrush->mins[0];
1042 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
1043 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
1044 face.planepts[2][0] = pBrush->maxs[0];
1045 }
1046 else {
1047 face.planepts[0][1] = pBrush->mins[1];
1048 face.planepts[1][1] = pBrush->mins[1];
1049 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
1050 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
1051 face.planepts[2][1] = pBrush->maxs[1];
1052 }
1053 }
1054
1055 Brush_SplitBrushByFace(pBrush, &face, &pFront, &pBack);
1056 if (pBack) {
1057 Brush_AddToList(pBack, &g_brBackSplits);
1058 }
1059
1060 if (pFront) {
1061 Brush_AddToList(pFront, &g_brFrontSplits);
1062 }
1063 }
1064 }
1065 }
1066 }
1067
1068 /*
1069 =======================================================================================================================
1070 =======================================================================================================================
1071 */
Brush_CopyList(brush_t * pFrom,brush_t * pTo)1072 void Brush_CopyList(brush_t *pFrom, brush_t *pTo) {
1073 brush_t *pBrush = pFrom->next;
1074 while (pBrush != NULL && pBrush != pFrom) {
1075 brush_t *pNext = pBrush->next;
1076 Brush_RemoveFromList(pBrush);
1077 Brush_AddToList(pBrush, pTo);
1078 pBrush = pNext;
1079 }
1080 }
1081
1082 /*
1083 =======================================================================================================================
1084 =======================================================================================================================
1085 */
OnRButtonDown(UINT nFlags,CPoint point)1086 void CXYWnd::OnRButtonDown(UINT nFlags, CPoint point) {
1087 g_pParentWnd->SetActiveXY(this);
1088 m_ptDown = point;
1089 m_bRButtonDown = true;
1090
1091 if (g_PrefsDlg.m_nMouseButtons == 3) { // 3 button mouse
1092 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
1093 if (ClipMode()) { // already there?
1094 DropClipPoint(nFlags, point);
1095 }
1096 else {
1097 SetClipMode(true);
1098 g_bRogueClipMode = true;
1099 DropClipPoint(nFlags, point);
1100 }
1101
1102 return;
1103 }
1104 }
1105
1106 OriginalButtonDown(nFlags, point);
1107 }
1108
1109 /*
1110 =======================================================================================================================
1111 =======================================================================================================================
1112 */
OnLButtonUp(UINT nFlags,CPoint point)1113 void CXYWnd::OnLButtonUp(UINT nFlags, CPoint point) {
1114
1115 if (ClipMode()) {
1116 if (g_pMovingClip) {
1117 ReleaseCapture();
1118 g_pMovingClip = NULL;
1119 }
1120 }
1121
1122 OriginalButtonUp(nFlags, point);
1123 }
1124
1125 /*
1126 =======================================================================================================================
1127 =======================================================================================================================
1128 */
OnMButtonUp(UINT nFlags,CPoint point)1129 void CXYWnd::OnMButtonUp(UINT nFlags, CPoint point) {
1130 OriginalButtonUp(nFlags, point);
1131 }
1132
1133 /*
1134 =======================================================================================================================
1135 =======================================================================================================================
1136 */
OnRButtonUp(UINT nFlags,CPoint point)1137 void CXYWnd::OnRButtonUp(UINT nFlags, CPoint point) {
1138 m_bRButtonDown = false;
1139 if (point == m_ptDown) { // mouse didn't move
1140 bool bGo = true;
1141 if ((GetAsyncKeyState(VK_MENU) & 0x8000)) {
1142 bGo = false;
1143 }
1144
1145 if ((GetAsyncKeyState(VK_CONTROL) & 0x8000)) {
1146 bGo = false;
1147 }
1148
1149 if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
1150 bGo = false;
1151 }
1152
1153 if (bGo) {
1154 HandleDrop();
1155 }
1156 }
1157
1158 OriginalButtonUp(nFlags, point);
1159 }
1160
1161 /*
1162 =======================================================================================================================
1163 =======================================================================================================================
1164 */
OriginalButtonDown(UINT nFlags,CPoint point)1165 void CXYWnd::OriginalButtonDown(UINT nFlags, CPoint point) {
1166 CRect rctZ;
1167 GetClientRect(rctZ);
1168 SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1169 if (g_pParentWnd->GetTopWindow() != this) {
1170 BringWindowToTop();
1171 }
1172
1173 SetFocus();
1174 SetCapture();
1175 XY_MouseDown(point.x, rctZ.Height() - 1 - point.y, nFlags);
1176 m_nScrollFlags = nFlags;
1177 }
1178
1179 /*
1180 =======================================================================================================================
1181 =======================================================================================================================
1182 */
OriginalButtonUp(UINT nFlags,CPoint point)1183 void CXYWnd::OriginalButtonUp(UINT nFlags, CPoint point) {
1184 CRect rctZ;
1185 GetClientRect(rctZ);
1186 XY_MouseUp(point.x, rctZ.Height() - 1 - point.y, nFlags);
1187 if (!(nFlags & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON))) {
1188 ReleaseCapture();
1189 }
1190 }
1191
1192 idVec3 tdp;
1193
1194 /*
1195 =======================================================================================================================
1196 =======================================================================================================================
1197 */
OnMouseMove(UINT nFlags,CPoint point)1198 void CXYWnd::OnMouseMove(UINT nFlags, CPoint point) {
1199
1200 m_ptDown.x = 0;
1201 m_ptDown.y = 0;
1202
1203 if
1204 (
1205 g_PrefsDlg.m_bChaseMouse == TRUE &&
1206 (point.x < 0 || point.y < 0 || point.x > m_nWidth || point.y > m_nHeight) &&
1207 GetCapture() == this
1208 ) {
1209 float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
1210
1211 // m_ptDrag = point;
1212 m_ptDragAdj.x = 0;
1213 m_ptDragAdj.y = 0;
1214 if (point.x < 0) {
1215 m_ptDragAdj.x = -fAdjustment;
1216 }
1217 else if (point.x > m_nWidth) {
1218 m_ptDragAdj.x = fAdjustment;
1219 }
1220
1221 if (point.y < 0) {
1222 m_ptDragAdj.y = -fAdjustment;
1223 }
1224 else if (point.y > m_nHeight) {
1225 m_ptDragAdj.y = fAdjustment;
1226 }
1227
1228 if (m_nTimerID == -1) {
1229 m_nTimerID = SetTimer(100, 50, NULL);
1230 m_ptDrag = point;
1231 m_ptDragTotal = 0;
1232 }
1233
1234 return;
1235 }
1236
1237 // else if (m_nTimerID != -1)
1238 if (m_nTimerID != -1) {
1239 KillTimer(m_nTimerID);
1240 pressx -= m_ptDragTotal.x;
1241 pressy += m_ptDragTotal.y;
1242 m_nTimerID = -1;
1243
1244 // return;
1245 }
1246
1247 bool bCrossHair = false;
1248 if (!m_bRButtonDown) {
1249 tdp[0] = tdp[1] = tdp[2] = 0.0;
1250 SnapToPoint(point.x, m_nHeight - 1 - point.y, tdp);
1251
1252 g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]);
1253 g_pParentWnd->SetStatusText(1, g_strStatus);
1254
1255 //
1256 // i need to generalize the point code.. having 3 flavors pretty much sucks.. once
1257 // the new curve stuff looks like it is going to stick i will rationalize this
1258 // down to a single interface..
1259 //
1260 if (PointMode()) {
1261 if (g_pMovingPoint && GetCapture() == this) {
1262 bCrossHair = true;
1263 SnapToPoint(point.x, m_nHeight - 1 - point.y, g_pMovingPoint->m_ptClip);
1264 g_pMovingPoint->UpdatePointPtr();
1265 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1266 }
1267 else {
1268 g_pMovingPoint = NULL;
1269
1270 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1271 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1272 for (int n = 0; n < g_nPointCount; n++) {
1273 if
1274 (
1275 fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1276 fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3
1277 ) {
1278 bCrossHair = true;
1279 g_pMovingPoint = &g_PointPoints[n];
1280 }
1281 }
1282 }
1283 }
1284 else if (ClipMode()) {
1285 if (g_pMovingClip && GetCapture() == this) {
1286 bCrossHair = true;
1287 SnapToPoint(point.x, m_nHeight - 1 - point.y, g_pMovingClip->m_ptClip);
1288 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1289 }
1290 else {
1291 g_pMovingClip = NULL;
1292
1293 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1294 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1295 if (g_Clip1.Set()) {
1296 if
1297 (
1298 fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1299 fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3
1300 ) {
1301 bCrossHair = true;
1302 g_pMovingClip = &g_Clip1;
1303 }
1304 }
1305
1306 if (g_Clip2.Set()) {
1307 if
1308 (
1309 fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1310 fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3
1311 ) {
1312 bCrossHair = true;
1313 g_pMovingClip = &g_Clip2;
1314 }
1315 }
1316
1317 if (g_Clip3.Set()) {
1318 if
1319 (
1320 fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1321 fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3
1322 ) {
1323 bCrossHair = true;
1324 g_pMovingClip = &g_Clip3;
1325 }
1326 }
1327 }
1328
1329 if (bCrossHair == false) {
1330 XY_MouseMoved(point.x, m_nHeight - 1 - point.y, nFlags);
1331 }
1332 }
1333 else if (PathMode()) {
1334 if (g_pMovingPath && GetCapture() == this) {
1335 bCrossHair = true;
1336 SnapToPoint(point.x, m_nHeight - 1 - point.y, g_pMovingPath->m_ptClip);
1337 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1338 }
1339 else {
1340 g_pMovingPath = NULL;
1341
1342 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1343 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1344 for (int n = 0; n < g_nPathCount; n++) {
1345 if
1346 (
1347 fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1348 fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3
1349 ) {
1350 bCrossHair = true;
1351 g_pMovingPath = &g_PathPoints[n];
1352 }
1353 }
1354 }
1355 }
1356 else {
1357 bCrossHair = XY_MouseMoved(point.x, m_nHeight - 1 - point.y, nFlags);
1358 }
1359 }
1360 else {
1361 bCrossHair = XY_MouseMoved(point.x, m_nHeight - 1 - point.y, nFlags);
1362 }
1363
1364 if (bCrossHair) {
1365 SetCursor(::LoadCursor(NULL, IDC_CROSS));
1366 }
1367 else {
1368 SetCursor(::LoadCursor(NULL, IDC_ARROW));
1369 }
1370
1371 /// If precision crosshair is active, force redraw of the 2d view on mouse move
1372 if( m_precisionCrosshairMode != PRECISION_CROSSHAIR_NONE )
1373 {
1374 /// Force 2d view redraw (so that the precision cursor moves with the mouse)
1375 Sys_UpdateWindows( W_XY );
1376 }
1377 }
1378
1379 /*
1380 =======================================================================================================================
1381 =======================================================================================================================
1382 */
RetainClipMode(bool bMode)1383 void CXYWnd::RetainClipMode(bool bMode) {
1384 bool bSave = g_bRogueClipMode;
1385 SetClipMode(bMode);
1386 if (bMode == true) {
1387 g_bRogueClipMode = bSave;
1388 }
1389 else {
1390 g_bRogueClipMode = false;
1391 }
1392 }
1393
1394 /*
1395 =======================================================================================================================
1396 =======================================================================================================================
1397 */
SetClipMode(bool bMode)1398 void CXYWnd::SetClipMode(bool bMode) {
1399 g_bClipMode = bMode;
1400 g_bRogueClipMode = false;
1401 if (bMode) {
1402 g_Clip1.Reset();
1403 g_Clip2.Reset();
1404 g_Clip3.Reset();
1405 CleanList(&g_brFrontSplits);
1406 CleanList(&g_brBackSplits);
1407 g_brFrontSplits.next = &g_brFrontSplits;
1408 g_brBackSplits.next = &g_brBackSplits;
1409 }
1410 else {
1411 if (g_pMovingClip) {
1412 ReleaseCapture();
1413 g_pMovingClip = NULL;
1414 }
1415
1416 CleanList(&g_brFrontSplits);
1417 CleanList(&g_brBackSplits);
1418 g_brFrontSplits.next = &g_brFrontSplits;
1419 g_brBackSplits.next = &g_brBackSplits;
1420 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1421 }
1422 }
1423
1424 /*
1425 =======================================================================================================================
1426 =======================================================================================================================
1427 */
ClipMode()1428 bool CXYWnd::ClipMode() {
1429 return g_bClipMode;
1430 }
1431
1432 /*
1433 =======================================================================================================================
1434 =======================================================================================================================
1435 */
RogueClipMode()1436 bool CXYWnd::RogueClipMode() {
1437 return g_bRogueClipMode;
1438 }
1439
1440 /*
1441 =======================================================================================================================
1442 =======================================================================================================================
1443 */
PathMode()1444 bool CXYWnd::PathMode() {
1445 return g_bPathMode;
1446 }
1447
1448 /*
1449 =======================================================================================================================
1450 =======================================================================================================================
1451 */
PointMode()1452 bool CXYWnd::PointMode() {
1453 return g_bPointMode;
1454 }
1455
1456 /*
1457 =======================================================================================================================
1458 =======================================================================================================================
1459 */
SetPointMode(bool b)1460 void CXYWnd::SetPointMode(bool b) {
1461 g_bPointMode = b;
1462 if (!b) {
1463 g_nPointCount = 0;
1464 }
1465 }
1466
1467 /*
1468 =======================================================================================================================
1469 =======================================================================================================================
1470 */
OnPaint()1471 void CXYWnd::OnPaint() {
1472 CPaintDC dc(this); // device context for painting
1473 bool bPaint = true;
1474 if (!qwglMakeCurrent(dc.m_hDC, win32.hGLRC)) {
1475 common->Printf("ERROR: wglMakeCurrent failed.. Error:%i\n", qglGetError());
1476 common->Printf("Please restart Q3Radiant if the Map view is not working\n");
1477 bPaint = false;
1478 }
1479
1480 if (bPaint) {
1481 QE_CheckOpenGLForErrors();
1482 XY_Draw();
1483 QE_CheckOpenGLForErrors();
1484
1485 if (m_nViewType != XY) {
1486 qglPushMatrix();
1487 if (m_nViewType == YZ) {
1488 qglRotatef(-90, 0, 1, 0); // put Z going up
1489 }
1490
1491 qglRotatef(-90, 1, 0, 0); // put Z going up
1492 }
1493
1494 if ( g_bCrossHairs ) {
1495 qglColor4f( 0.2f, 0.9f, 0.2f, 0.8f );
1496 qglBegin(GL_LINES);
1497 if (m_nViewType == XY) {
1498 qglVertex2f(-16384, tdp[1]);
1499 qglVertex2f(16384, tdp[1]);
1500 qglVertex2f(tdp[0], -16384);
1501 qglVertex2f(tdp[0], 16384);
1502 }
1503 else if (m_nViewType == YZ) {
1504 qglVertex3f(tdp[0], -16384, tdp[2]);
1505 qglVertex3f(tdp[0], 16384, tdp[2]);
1506 qglVertex3f(tdp[0], tdp[1], -16384);
1507 qglVertex3f(tdp[0], tdp[1], 16384);
1508 }
1509 else {
1510 qglVertex3f(-16384, tdp[1], tdp[2]);
1511 qglVertex3f(16384, tdp[1], tdp[2]);
1512 qglVertex3f(tdp[0], tdp[1], -16384);
1513 qglVertex3f(tdp[0], tdp[1], 16384);
1514 }
1515
1516 qglEnd();
1517 }
1518
1519 if (ClipMode()) {
1520 qglPointSize(4);
1521 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER].ToFloatPtr());
1522 qglBegin(GL_POINTS);
1523 if (g_Clip1.Set()) {
1524 qglVertex3fv(g_Clip1);
1525 }
1526
1527 if (g_Clip2.Set()) {
1528 qglVertex3fv(g_Clip2);
1529 }
1530
1531 if (g_Clip3.Set()) {
1532 qglVertex3fv(g_Clip3);
1533 }
1534
1535 qglEnd();
1536 qglPointSize(1);
1537
1538 CString strMsg;
1539 if (g_Clip1.Set()) {
1540 qglRasterPos3f(g_Clip1.m_ptClip[0] + 2, g_Clip1.m_ptClip[1] + 2, g_Clip1.m_ptClip[2] + 2);
1541 strMsg = "1";
1542
1543 // strMsg.Format("1 (%f, %f, %f)", g_Clip1[0], g_Clip1[1], g_Clip1[2]);
1544 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1545 }
1546
1547 if (g_Clip2.Set()) {
1548 qglRasterPos3f(g_Clip2.m_ptClip[0] + 2, g_Clip2.m_ptClip[1] + 2, g_Clip2.m_ptClip[2] + 2);
1549 strMsg = "2";
1550
1551 // strMsg.Format("2 (%f, %f, %f)", g_Clip2[0], g_Clip2[1], g_Clip2[2]);
1552 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1553 }
1554
1555 if (g_Clip3.Set()) {
1556 qglRasterPos3f(g_Clip3.m_ptClip[0] + 2, g_Clip3.m_ptClip[1] + 2, g_Clip3.m_ptClip[2] + 2);
1557 strMsg = "3";
1558
1559 // strMsg.Format("3 (%f, %f, %f)", g_Clip3[0], g_Clip3[1], g_Clip3[2]);
1560 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1561 }
1562
1563 if (g_Clip1.Set() && g_Clip2.Set() && selected_brushes.next != &selected_brushes) {
1564 ProduceSplitLists();
1565
1566 brush_t *pBrush;
1567 brush_t *pList = ((m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
1568 for (pBrush = pList->next; pBrush != NULL && pBrush != pList; pBrush = pBrush->next) {
1569 qglColor3f(1, 1, 0);
1570
1571 face_t *face;
1572 int order;
1573 for (face = pBrush->brush_faces, order = 0; face; face = face->next, order++) {
1574 idWinding *w = face->face_winding;
1575 if (!w) {
1576 continue;
1577 }
1578
1579 // draw the polygon
1580 qglBegin(GL_LINE_LOOP);
1581 for (int i = 0; i < w->GetNumPoints(); i++) {
1582 qglVertex3fv( (*w)[i].ToFloatPtr() );
1583 }
1584
1585 qglEnd();
1586 }
1587 }
1588 }
1589 }
1590
1591 if (PathMode()) {
1592 qglPointSize(4);
1593 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER].ToFloatPtr());
1594 qglBegin(GL_POINTS);
1595
1596 int n;
1597 for ( n = 0; n < g_nPathCount; n++) {
1598 qglVertex3fv(g_PathPoints[n]);
1599 }
1600
1601 qglEnd();
1602 qglPointSize(1);
1603
1604 CString strMsg;
1605 for (n = 0; n < g_nPathCount; n++) {
1606 qglRasterPos3f
1607 (
1608 g_PathPoints[n].m_ptClip[0] + 2,
1609 g_PathPoints[n].m_ptClip[1] + 2,
1610 g_PathPoints[n].m_ptClip[2] + 2
1611 );
1612 strMsg.Format("%i", n + 1);
1613 qglCallLists(strMsg.GetLength(), GL_UNSIGNED_BYTE, strMsg);
1614 }
1615 }
1616
1617 if (m_nViewType != XY) {
1618 qglPopMatrix();
1619 }
1620
1621 qwglSwapBuffers(dc.m_hDC);
1622 TRACE("XY Paint\n");
1623 }
1624 }
1625
1626 /*
1627 =======================================================================================================================
1628 =======================================================================================================================
1629 */
OnKeyDown(UINT nChar,UINT nRepCnt,UINT nFlags)1630 void CXYWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
1631 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
1632 }
1633
1634 //
1635 // =======================================================================================================================
1636 // FIXME: the brush_t *pBrush is never used. ( Entity_Create uses selected_brushes )
1637 // =======================================================================================================================
1638 //
CreateEntityFromName(char * pName,brush_t * pBrush,bool forceFixed,idVec3 min,idVec3 max,idVec3 org)1639 void CreateEntityFromName(char *pName, brush_t *pBrush, bool forceFixed, idVec3 min, idVec3 max, idVec3 org) {
1640 eclass_t *pecNew;
1641 entity_t *petNew;
1642 if (stricmp(pName, "worldspawn") == 0) {
1643 g_pParentWnd->MessageBox("Can't create an entity with worldspawn.", "info", 0);
1644 return;
1645 }
1646
1647 pecNew = Eclass_ForName(pName, false);
1648
1649 if ((GetAsyncKeyState(VK_SHIFT) & 0x8000)) {
1650 Select_Ungroup();
1651 }
1652
1653 // create it
1654 petNew = Entity_Create(pecNew, forceFixed);
1655
1656 if (petNew && idStr::Icmp(pName, "light") == 0 ) {
1657 idVec3 rad = max - min;
1658 rad *= 0.5;
1659 if (rad.x != 0 && rad.y != 0 && rad.z != 0) {
1660 SetKeyValue(petNew, "light_radius", va("%g %g %g", idMath::Fabs(rad.x), idMath::Fabs(rad.y), idMath::Fabs(rad.z)));
1661 DeleteKey(petNew, "light");
1662 }
1663 }
1664
1665
1666 if (petNew == NULL) {
1667 if (!((selected_brushes.next == &selected_brushes) || (selected_brushes.next->next != &selected_brushes))) {
1668 brush_t *b = selected_brushes.next;
1669 if (b->owner != world_entity && ((b->owner->eclass->fixedsize && pecNew->fixedsize) || forceFixed)) {
1670 idVec3 mins, maxs;
1671 idVec3 origin;
1672 for (int i = 0; i < 3; i++) {
1673 origin[i] = b->mins[i] - pecNew->mins[i];
1674 }
1675
1676 VectorAdd(pecNew->mins, origin, mins);
1677 VectorAdd(pecNew->maxs, origin, maxs);
1678
1679 brush_t *nb = Brush_Create(mins, maxs, &pecNew->texdef);
1680 Entity_LinkBrush(b->owner, nb);
1681 nb->owner->eclass = pecNew;
1682 SetKeyValue(nb->owner, "classname", pName);
1683 Brush_Free(b);
1684 Brush_Build(nb);
1685 Brush_AddToList(nb, &active_brushes);
1686 Select_Brush(nb);
1687 return;
1688 }
1689 }
1690
1691 g_pParentWnd->MessageBox("Failed to create entity.", "info", 0);
1692 return;
1693 }
1694
1695 Select_Deselect();
1696
1697 //
1698 // entity_t* pEntity = world_entity; if (selected_brushes.next !=
1699 // &selected_brushes) pEntity = selected_brushes.next->owner;
1700 //
1701 Select_Brush(petNew->brushes.onext);
1702 Brush_Build(petNew->brushes.onext);
1703
1704 }
1705
1706 /*
1707 =======================================================================================================================
1708 =======================================================================================================================
1709 */
CreateEntityBrush(int x,int y,CXYWnd * pWnd)1710 brush_t *CreateEntityBrush(int x, int y, CXYWnd *pWnd) {
1711 idVec3 mins, maxs;
1712 int i;
1713 float temp;
1714 brush_t *n;
1715
1716 pWnd->SnapToPoint(x, y, mins);
1717 x += 32;
1718 y += 32;
1719 pWnd->SnapToPoint(x, y, maxs);
1720
1721 int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
1722 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom[nDim] / g_qeglobals.d_gridsize));
1723 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top[nDim] / g_qeglobals.d_gridsize));
1724
1725 if (maxs[nDim] <= mins[nDim]) {
1726 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
1727 }
1728
1729 for (i = 0; i < 3; i++) {
1730 if (mins[i] == maxs[i]) {
1731 maxs[i] += 16; // don't create a degenerate brush
1732 }
1733
1734 if (mins[i] > maxs[i]) {
1735 temp = mins[i];
1736 mins[i] = maxs[i];
1737 maxs[i] = temp;
1738 }
1739 }
1740
1741 n = Brush_Create(mins, maxs, &g_qeglobals.d_texturewin.texdef);
1742 if (!n) {
1743 return NULL;
1744 }
1745
1746 Brush_AddToList(n, &selected_brushes);
1747 Entity_LinkBrush(world_entity, n);
1748 Brush_Build(n);
1749 return n;
1750 }
1751
1752 /*
1753 =======================================================================================================================
1754 =======================================================================================================================
1755 */
CreateRightClickEntity(CXYWnd * pWnd,int x,int y,char * pName)1756 void CreateRightClickEntity(CXYWnd *pWnd, int x, int y, char *pName) {
1757 idVec3 min, max, org;
1758 Select_GetBounds(min, max);
1759 Select_GetMid(org);
1760
1761 CRect rctZ;
1762 pWnd->GetClientRect(rctZ);
1763
1764 brush_t *pBrush;
1765 if (selected_brushes.next == &selected_brushes) {
1766 pBrush = CreateEntityBrush(x, rctZ.Height() - 1 - y, pWnd);
1767 min.Zero();
1768 max.Zero();
1769 CreateEntityFromName(pName, pBrush, true, min, max, org);
1770 }
1771 else {
1772 pBrush = selected_brushes.next;
1773 CreateEntityFromName(pName, pBrush, false, min, max, org);
1774 }
1775 }
1776
1777 /*
1778 =======================================================================================================================
1779 =======================================================================================================================
1780 */
CreateSmartBrush(idVec3 v)1781 brush_t *CreateSmartBrush(idVec3 v) {
1782 idVec3 mins, maxs;
1783 int i;
1784 brush_t *n;
1785
1786 for (i = 0; i < 3; i++) {
1787 mins[i] = v[i] - 16;
1788 maxs[i] = v[i] + 16;
1789 }
1790
1791 n = Brush_Create(mins, maxs, &g_qeglobals.d_texturewin.texdef);
1792 if (!n) {
1793 return NULL;
1794 }
1795
1796 Brush_AddToList(n, &selected_brushes);
1797
1798 // Entity_LinkBrush(world_entity, n);
1799 Brush_Build(n);
1800 return n;
1801 }
1802
1803 CString g_strSmartEntity;
1804 int g_nSmartX;
1805 int g_nSmartY;
1806 bool g_bSmartWaiting;
1807
1808 /*
1809 =======================================================================================================================
1810 =======================================================================================================================
1811 */
_SmartPointDone(bool b,int n)1812 void _SmartPointDone(bool b, int n) {
1813 g_bSmartWaiting = false;
1814 }
1815
1816 /*
1817 =======================================================================================================================
1818 =======================================================================================================================
1819 */
CreateSmartEntity(CXYWnd * pWnd,int x,int y,const char * pName)1820 void CreateSmartEntity(CXYWnd *pWnd, int x, int y, const char *pName) {
1821 g_nSmartX = x;
1822 g_nSmartY = y;
1823 g_strSmartEntity = pName;
1824 if (g_strSmartEntity.Find("Smart_Train") >= 0) {
1825 ShowInfoDialog("Select the path of the train by left clicking in XY, YZ and/or XZ views. You can move an already dropped point by grabbing and moving it. When you are finished, press ENTER to accept and create the entity and path(s), press ESC to abandon the creation");
1826 g_bPathMode = true;
1827 g_nPathLimit = 0;
1828 g_nPathCount = 0;
1829 g_bSmartGo = true;
1830 }
1831 else if (g_strSmartEntity.Find("Smart_Monster...") >= 0) {
1832 g_bPathMode = true;
1833 g_nPathLimit = 0;
1834 g_nPathCount = 0;
1835 }
1836 else if (g_strSmartEntity.Find("Smart_Rotating") >= 0) {
1837 g_bSmartWaiting = true;
1838 ShowInfoDialog("Left click to specify the rotation origin");
1839 AcquirePath(1, &_SmartPointDone);
1840 while (g_bSmartWaiting) {
1841 MSG msg;
1842 if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1843 TranslateMessage(&msg);
1844 DispatchMessage(&msg);
1845 }
1846 }
1847
1848 HideInfoDialog();
1849
1850 CPtrArray array;
1851 g_bScreenUpdates = false;
1852 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
1853 array.Add(reinterpret_cast < void * > (selected_brushes.next));
1854 Select_Deselect();
1855
1856 brush_t *pBrush = CreateSmartBrush(g_PathPoints[0]);
1857 array.Add(pBrush);
1858 Select_Deselect();
1859 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(0)));
1860 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(1)));
1861 ConnectEntities();
1862 g_bScreenUpdates = true;
1863 }
1864 }
1865
1866 /*
1867 =======================================================================================================================
1868 =======================================================================================================================
1869 */
FinishSmartCreation()1870 void FinishSmartCreation() {
1871 CPtrArray array;
1872 HideInfoDialog();
1873
1874 brush_t *pEntities = NULL;
1875 if (g_strSmartEntity.Find("Smart_Train") >= 0) {
1876 g_bScreenUpdates = false;
1877 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
1878 array.Add(reinterpret_cast < void * > (selected_brushes.next));
1879 int n;
1880 for (n = 0; n < g_nPathCount; n++) {
1881 Select_Deselect();
1882 CreateRightClickEntity
1883 (
1884 g_pParentWnd->ActiveXY(),
1885 g_PathPoints[n].m_ptScreen.x,
1886 g_PathPoints[n].m_ptScreen.y,
1887 "path_corner"
1888 );
1889 array.Add(reinterpret_cast < void * > (selected_brushes.next));
1890 }
1891
1892 for (n = 0; n < g_nPathCount; n++) {
1893 Select_Deselect();
1894 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(n)));
1895 Select_Brush(reinterpret_cast < brush_t * > (array.GetAt(n + 1)));
1896 ConnectEntities();
1897 }
1898
1899 g_bScreenUpdates = true;
1900 }
1901
1902 g_nPathCount = 0;
1903 g_bPathMode = false;
1904 Sys_UpdateWindows(W_ALL);
1905 }
1906
1907 /*
1908 =======================================================================================================================
1909 =======================================================================================================================
1910 */
KillPathMode()1911 void CXYWnd::KillPathMode() {
1912 g_bSmartGo = false;
1913 g_bPathMode = false;
1914 if (g_pPathFunc) {
1915 g_pPathFunc(false, g_nPathCount);
1916 }
1917
1918 g_nPathCount = 0;
1919 g_pPathFunc = NULL;
1920 Sys_UpdateWindows(W_ALL);
1921 }
1922
1923 //
1924 // =======================================================================================================================
1925 // gets called for drop down menu messages TIP: it's not always about EntityCreate
1926 // =======================================================================================================================
1927 //
OnEntityCreate(unsigned int nID)1928 void CXYWnd::OnEntityCreate(unsigned int nID) {
1929 if (m_mnuDrop.GetSafeHmenu()) {
1930 CString strItem;
1931 m_mnuDrop.GetMenuString(nID, strItem, MF_BYCOMMAND);
1932
1933 if (strItem.CompareNoCase("Add to...") == 0) {
1934 //
1935 // ++timo TODO: fill the menu with current groups? this one is for adding to
1936 // existing groups only
1937 //
1938 common->Printf("TODO: Add to... in CXYWnd::OnEntityCreate\n");
1939 }
1940 else if (strItem.CompareNoCase("Remove") == 0) {
1941 // remove selected brushes from their current group
1942 brush_t *b;
1943 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1944 }
1945 }
1946
1947 // ++timo FIXME: remove when all hooks are in
1948 if
1949 (
1950 strItem.CompareNoCase("Add to...") == 0 ||
1951 strItem.CompareNoCase("Remove") == 0 ||
1952 strItem.CompareNoCase("Name...") == 0 ||
1953 strItem.CompareNoCase("New group...") == 0
1954 ) {
1955 common->Printf("TODO: hook drop down group menu\n");
1956 return;
1957 }
1958
1959 if (strItem.Find("Smart_") >= 0) {
1960 CreateSmartEntity(this, m_ptDown.x, m_ptDown.y, strItem);
1961 }
1962 else {
1963 CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, strItem.GetBuffer(0));
1964 }
1965
1966 Sys_UpdateWindows(W_ALL);
1967
1968 // OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
1969 }
1970 }
1971
OnCmdMsg(UINT nID,int nCode,void * pExtra,AFX_CMDHANDLERINFO * pHandlerInfo)1972 BOOL CXYWnd::OnCmdMsg( UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo )
1973 {
1974 if ( CWnd::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo ) ) {
1975 return TRUE;
1976 }
1977 return AfxGetMainWnd()->OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
1978 }
1979
MergeMenu(CMenu * pMenuDestination,const CMenu * pMenuAdd,bool bTopLevel)1980 bool MergeMenu(CMenu * pMenuDestination, const CMenu * pMenuAdd, bool bTopLevel /*=false*/)
1981 {
1982 // get the number menu items in the menus
1983 int iMenuAddItemCount = pMenuAdd->GetMenuItemCount();
1984 int iMenuDestItemCount = pMenuDestination->GetMenuItemCount();
1985
1986 // if there are no items return
1987 if (iMenuAddItemCount == 0)
1988 return true;
1989
1990 // if we are not at top level and the destination menu is not empty
1991 // -> we append a seperator
1992 if (!bTopLevel && iMenuDestItemCount > 0)
1993 pMenuDestination->AppendMenu(MF_SEPARATOR);
1994
1995 // iterate through the top level of <pMenuAdd>
1996 for(int iLoop = 0; iLoop < iMenuAddItemCount; iLoop++)
1997 {
1998 // get the menu string from the add menu
1999 CString sMenuAddString;
2000 pMenuAdd->GetMenuString(iLoop, sMenuAddString, MF_BYPOSITION);
2001
2002 // try to get the submenu of the current menu item
2003 CMenu* pSubMenu = pMenuAdd->GetSubMenu(iLoop);
2004
2005 // check if we have a sub menu
2006 if (!pSubMenu)
2007 {
2008 // normal menu item
2009 // read the source and append at the destination
2010 UINT nState = pMenuAdd->GetMenuState(iLoop, MF_BYPOSITION);
2011 UINT nItemID = pMenuAdd->GetMenuItemID(iLoop);
2012 if (pMenuDestination->AppendMenu(nState, nItemID, sMenuAddString))
2013 {
2014 // menu item added, don't forget to correct the item count
2015 iMenuDestItemCount++;
2016 }
2017 else
2018 {
2019 TRACE("MergeMenu: AppendMenu failed!\n");
2020 return false;
2021 }
2022 }
2023 else
2024 {
2025 // create or insert a new popup menu item
2026
2027 // default insert pos is like ap
2028 int iInsertPosDefault = -1;
2029
2030 // if we are at top level merge into existing popups rather than
2031 // creating new ones
2032 if(bTopLevel)
2033 {
2034 ASSERT(sMenuAddString != "&?" && sMenuAddString !=
2035 "?");
2036 CString csAdd(sMenuAddString);
2037 csAdd.Remove('&'); // for comparison of menu items supress '&'
2038 bool bAdded = false;
2039
2040 // try to find existing popup
2041 for( int iLoop1 = 0; iLoop1 < iMenuDestItemCount; iLoop1++ )
2042 {
2043 // get the menu string from the destination menu
2044 CString sDest;
2045 pMenuDestination->GetMenuString(iLoop1, sDest, MF_BYPOSITION);
2046 sDest.Remove('&'); // for a better compare (s.a.)
2047
2048 if (csAdd == sDest)
2049 {
2050 // we got a hit -> merge the two popups
2051 // try to get the submenu of the desired destination menu item
2052 CMenu* pSubMenuDest =
2053 pMenuDestination->GetSubMenu(iLoop1);
2054
2055 if (pSubMenuDest)
2056 {
2057 // merge the popup recursivly and continue with outer for loop
2058 if (!MergeMenu(pSubMenuDest, pSubMenu, false))
2059 return false;
2060 bAdded = true;
2061 break;
2062 }
2063 }
2064
2065 // alternativ insert before <Window> or <Help>
2066 if (iInsertPosDefault == -1 && (sDest == "Window"
2067 || sDest == "?" || sDest == "Help"))
2068 {
2069 iInsertPosDefault = iLoop1;
2070 }
2071 } // for (iLoop1)
2072 if (bAdded)
2073 {
2074 // menu added, so go on with loop over pMenuAdd's top level
2075 continue;
2076 }
2077 } // if (bTopLevel)
2078
2079 // if the top level search did not find a position append the menu
2080 if( iInsertPosDefault == -1 )
2081 {
2082 iInsertPosDefault = pMenuDestination->GetMenuItemCount();
2083 }
2084
2085 // create a new popup and insert before <Window> or <Help>
2086 CMenu NewPopupMenu;
2087 if (!NewPopupMenu.CreatePopupMenu())
2088 {
2089 TRACE("MergeMenu: CreatePopupMenu failed!\n");
2090 return false;
2091 }
2092
2093 // merge the new popup recursivly
2094 if (!MergeMenu(&NewPopupMenu, pSubMenu, false))
2095 return false;
2096
2097 // insert the new popup menu into the destination menu
2098 HMENU hNewMenu = NewPopupMenu.GetSafeHmenu();
2099 if (pMenuDestination->InsertMenu(iInsertPosDefault,
2100 MF_BYPOSITION | MF_POPUP | MF_ENABLED,
2101 (UINT)hNewMenu, sMenuAddString ))
2102 {
2103 // don't forget to correct the item count
2104 iMenuDestItemCount++;
2105 }
2106 else
2107 {
2108 TRACE("MergeMenu: InsertMenu failed!\n");
2109 return false;
2110 }
2111
2112 // don't destroy the new menu
2113 NewPopupMenu.Detach();
2114 } // if (pSubMenu)
2115 } // for (iLoop)
2116 return true;
2117 }
2118
2119
2120
2121
2122 /*
2123 =======================================================================================================================
2124 =======================================================================================================================
2125 */
HandleDrop()2126 void CXYWnd::HandleDrop() {
2127 if (g_PrefsDlg.m_bRightClick == false) {
2128 return;
2129 }
2130
2131 if (!m_mnuDrop.GetSafeHmenu()) { // first time, load it up
2132 m_mnuDrop.CreatePopupMenu();
2133
2134 CMenu *drop = new CMenu;
2135 drop->LoadMenu( IDR_MENU_DROP );
2136
2137 MergeMenu( &m_mnuDrop, drop, false );
2138
2139 int nID = ID_ENTITY_START;
2140
2141 CMenu *pMakeEntityPop = &m_mnuDrop;
2142
2143 // Todo: Make this a config option maybe?
2144 const int entitiesOnSubMenu = false;
2145 if ( entitiesOnSubMenu ) {
2146 pMakeEntityPop = new CMenu;
2147 pMakeEntityPop->CreateMenu();
2148 }
2149
2150 CMenu *pChild = NULL;
2151
2152 eclass_t *e;
2153 CString strActive;
2154 CString strLast;
2155 CString strName;
2156 for (e = eclass; e; e = e->next) {
2157 strLast = strName;
2158 strName = e->name;
2159
2160 int n_ = strName.Find("_");
2161 if (n_ > 0) {
2162 CString strLeft = strName.Left(n_);
2163 CString strRight = strName.Right(strName.GetLength() - n_ - 1);
2164 if (strLeft == strActive) { // this is a child
2165 ASSERT(pChild);
2166 pChild->AppendMenu(MF_STRING, nID++, strName);
2167 }
2168 else {
2169 if (pChild) {
2170 pMakeEntityPop->AppendMenu (
2171 MF_POPUP,
2172 reinterpret_cast < unsigned int > (pChild->GetSafeHmenu()),
2173 strActive
2174 );
2175 g_ptrMenus.Add(pChild);
2176
2177 // pChild->DestroyMenu(); delete pChild;
2178 pChild = NULL;
2179 }
2180
2181 strActive = strLeft;
2182 pChild = new CMenu;
2183 pChild->CreateMenu();
2184 pChild->AppendMenu(MF_STRING, nID++, strName);
2185 }
2186 }
2187 else {
2188 if (pChild) {
2189 pMakeEntityPop->AppendMenu (
2190 MF_POPUP,
2191 reinterpret_cast < unsigned int > (pChild->GetSafeHmenu()),
2192 strActive
2193 );
2194 g_ptrMenus.Add(pChild);
2195
2196 // pChild->DestroyMenu(); delete pChild;
2197 pChild = NULL;
2198 }
2199
2200 strActive = "";
2201 pMakeEntityPop->AppendMenu(MF_STRING, nID++, strName);
2202 }
2203 }
2204 if ( pMakeEntityPop != &m_mnuDrop ) {
2205 m_mnuDrop.AppendMenu (
2206 MF_POPUP,
2207 reinterpret_cast < unsigned int > (pMakeEntityPop->GetSafeHmenu()),
2208 "Make Entity"
2209 );
2210 }
2211 }
2212
2213 CPoint ptMouse;
2214 GetCursorPos(&ptMouse);
2215 m_mnuDrop.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, ptMouse.x, ptMouse.y, this);
2216 }
2217
2218 /*
2219 =======================================================================================================================
2220 =======================================================================================================================
2221 */
XY_Init()2222 void CXYWnd::XY_Init() {
2223 m_vOrigin[0] = 0;
2224 m_vOrigin[1] = 20;
2225 m_vOrigin[2] = 46;
2226 m_fScale = 1;
2227 m_precisionCrosshairMode = PRECISION_CROSSHAIR_NONE;
2228 }
2229
2230 /*
2231 =======================================================================================================================
2232 =======================================================================================================================
2233 */
SnapToPoint(int x,int y,idVec3 & point)2234 void CXYWnd::SnapToPoint(int x, int y, idVec3 &point) {
2235 if (g_PrefsDlg.m_bNoClamp) {
2236 XY_ToPoint(x, y, point);
2237 }
2238 else {
2239 XY_ToGridPoint(x, y, point);
2240 }
2241
2242 // -- else -- XY_ToPoint(x, y, point); -- //XY_ToPoint(x, y, point);
2243 }
2244
2245 /*
2246 =======================================================================================================================
2247 =======================================================================================================================
2248 */
XY_ToPoint(int x,int y,idVec3 & point)2249 void CXYWnd::XY_ToPoint(int x, int y, idVec3 &point) {
2250 float fx = x;
2251 float fy = y;
2252 float fw = m_nWidth;
2253 float fh = m_nHeight;
2254 if (m_nViewType == XY) {
2255 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2256 point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
2257
2258 // point[2] = 0;
2259 }
2260 else if (m_nViewType == YZ) {
2261 //
2262 // //point[0] = 0; point[1] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; point[2] =
2263 // m_vOrigin[1] + (fy - fh / 2 ) / m_fScale;
2264 //
2265 point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
2266 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
2267 }
2268 else {
2269 //
2270 // point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale; /point[1] = 0; point[2] =
2271 // m_vOrigin[1] + (fy - fh / 2) / m_fScale;
2272 //
2273 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2274
2275 // point[1] = 0;
2276 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
2277 }
2278 }
2279
2280 /*
2281 =======================================================================================================================
2282 =======================================================================================================================
2283 */
XY_ToGridPoint(int x,int y,idVec3 & point)2284 void CXYWnd::XY_ToGridPoint(int x, int y, idVec3 &point) {
2285 if (m_nViewType == XY) {
2286 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2287 point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2288
2289 // point[2] = 0;
2290 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2291 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2292 }
2293 else if (m_nViewType == YZ) {
2294 //
2295 // point[0] = 0; point[1] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; point[2]
2296 // = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2297 //
2298 point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
2299 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2300 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2301 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2302 }
2303 else {
2304 //
2305 // point[1] = 0; point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale; point[2]
2306 // = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2307 //
2308 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2309 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2310 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2311 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2312 }
2313 }
2314
2315 /*
2316 =======================================================================================================================
2317 =======================================================================================================================
2318 */
2319 idVec3 dragOrigin;
2320 idVec3 dragDir;
2321 idVec3 dragX;
2322 idVec3 dragY;
2323
XY_MouseDown(int x,int y,int buttons)2324 void CXYWnd::XY_MouseDown(int x, int y, int buttons) {
2325 idVec3 point,center;
2326 idVec3 origin, dir, right, up;
2327
2328 m_nButtonstate = buttons;
2329 m_nPressx = x;
2330 m_nPressy = y;
2331 VectorCopy(vec3_origin, m_vPressdelta);
2332
2333 point.Zero();
2334
2335 XY_ToPoint(x, y, point);
2336
2337 VectorCopy(point, origin);
2338
2339 dir.Zero();
2340 if (m_nViewType == XY) {
2341 origin[2] = HUGE_DISTANCE;
2342 dir[2] = -1;
2343 right[0] = 1 / m_fScale;
2344 right[1] = 0;
2345 right[2] = 0;
2346 up[0] = 0;
2347 up[1] = 1 / m_fScale;
2348 up[2] = 0;
2349 point[2] = g_pParentWnd->GetCamera()->Camera().origin[2];
2350 }
2351 else if (m_nViewType == YZ) {
2352 origin[0] = HUGE_DISTANCE;
2353 dir[0] = -1;
2354 right[1] = 1 / m_fScale;
2355 right[2] = 0;
2356 right[0] = 0;
2357 up[0] = 0;
2358 up[2] = 1 / m_fScale;
2359 up[1] = 0;
2360 point[0] = g_pParentWnd->GetCamera()->Camera().origin[0];
2361 }
2362 else {
2363 origin[1] = HUGE_DISTANCE;
2364 dir[1] = -1;
2365 right[0] = 1 / m_fScale;
2366 right[2] = 0;
2367 right[1] = 0;
2368 up[0] = 0;
2369 up[2] = 1 / m_fScale;
2370 up[1] = 0;
2371 point[1] = g_pParentWnd->GetCamera()->Camera().origin[1];
2372 }
2373
2374 dragOrigin = m_vOrigin;
2375 dragDir = dir;
2376 dragX = right;
2377 dragY = up;
2378
2379 m_bPress_selection = (selected_brushes.next != &selected_brushes);
2380
2381 GetCursorPos(&m_ptCursor);
2382
2383 // Sys_GetCursorPos (&m_ptCursor.x, &m_ptCursor.y);
2384 if (buttons == MK_LBUTTON && activeDrag) {
2385 activeDragging = true;
2386 }
2387 else {
2388 activeDragging = false;
2389 }
2390
2391 // lbutton = manipulate selection shift-LBUTTON = select
2392 if
2393 (
2394 (buttons == MK_LBUTTON) ||
2395 (buttons == (MK_LBUTTON | MK_SHIFT)) ||
2396 (buttons == (MK_LBUTTON | MK_CONTROL)) ||
2397 (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT))
2398 ) {
2399 if (g_qeglobals.d_select_mode == sel_addpoint) {
2400 XY_ToGridPoint(x, y, point);
2401 if (g_qeglobals.selectObject) {
2402 g_qeglobals.selectObject->addPoint(point);
2403 }
2404
2405 return;
2406 }
2407
2408 Patch_SetView((m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
2409 Drag_Begin(x, y, buttons, right, up, origin, dir);
2410 return;
2411 }
2412
2413 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
2414
2415 // control mbutton = move camera
2416 if (m_nButtonstate == (MK_CONTROL | nMouseButton)) {
2417 VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
2418 Sys_UpdateWindows(W_CAMERA | W_XY_OVERLAY);
2419 }
2420
2421 // mbutton = angle camera
2422 if
2423 (
2424 (g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
2425 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT | MK_CONTROL | MK_RBUTTON))
2426 ) {
2427 VectorSubtract(point, g_pParentWnd->GetCamera()->Camera().origin, point);
2428
2429 int n1 = (m_nViewType == XY) ? 1 : 2;
2430 int n2 = (m_nViewType == YZ) ? 1 : 0;
2431 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
2432 if (point[n1] || point[n2]) {
2433 g_pParentWnd->GetCamera()->Camera().angles[nAngle] = RAD2DEG( atan2(point[n1], point[n2]) );
2434 Sys_UpdateWindows(W_CAMERA_IFON | W_XY_OVERLAY);
2435 }
2436 }
2437
2438 // shift mbutton = move z checker
2439 if (m_nButtonstate == (MK_SHIFT | nMouseButton)) {
2440 if (RotateMode() || g_bPatchBendMode) {
2441 SnapToPoint(x, y, point);
2442 VectorCopyXY(point, g_vRotateOrigin);
2443 if (g_bPatchBendMode) {
2444 VectorCopy(point, g_vBendOrigin);
2445 }
2446
2447 Sys_UpdateWindows(W_XY);
2448 return;
2449 }
2450 else {
2451 SnapToPoint(x, y, point);
2452 if (m_nViewType == XY) {
2453 z.origin[0] = point[0];
2454 z.origin[1] = point[1];
2455 }
2456 else if (m_nViewType == YZ) {
2457 z.origin[0] = point[1];
2458 z.origin[1] = point[2];
2459 }
2460 else {
2461 z.origin[0] = point[0];
2462 z.origin[1] = point[2];
2463 }
2464
2465 Sys_UpdateWindows(W_XY_OVERLAY | W_Z);
2466 return;
2467 }
2468 }
2469 }
2470
2471 /*
2472 =======================================================================================================================
2473 =======================================================================================================================
2474 */
XY_MouseUp(int x,int y,int buttons)2475 void CXYWnd::XY_MouseUp(int x, int y, int buttons) {
2476 activeDragging = false;
2477 Drag_MouseUp(buttons);
2478 if (!m_bPress_selection) {
2479 Sys_UpdateWindows(W_ALL);
2480 }
2481
2482 m_nButtonstate = 0;
2483 while (::ShowCursor(TRUE) < 0)
2484 ;
2485 }
2486
2487 /*
2488 =======================================================================================================================
2489 =======================================================================================================================
2490 */
DragDelta(int x,int y,idVec3 & move)2491 bool CXYWnd::DragDelta(int x, int y, idVec3 &move) {
2492 idVec3 xvec, yvec, delta;
2493 int i;
2494
2495 xvec[0] = 1 / m_fScale;
2496 xvec[1] = xvec[2] = 0;
2497 yvec[1] = 1 / m_fScale;
2498 yvec[0] = yvec[2] = 0;
2499
2500 for (i = 0; i < 3; i++) {
2501 delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
2502 if (!g_PrefsDlg.m_bNoClamp) {
2503 delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2504 }
2505 }
2506
2507 VectorSubtract(delta, m_vPressdelta, move);
2508 VectorCopy(delta, m_vPressdelta);
2509
2510
2511 if (move[0] || move[1] || move[2]) {
2512 return true;
2513 }
2514
2515 return false;
2516 }
2517
2518 /*
2519 =======================================================================================================================
2520 NewBrushDrag
2521 =======================================================================================================================
2522 */
NewBrushDrag(int x,int y)2523 void CXYWnd::NewBrushDrag(int x, int y) {
2524 idVec3 mins, maxs, junk;
2525 int i;
2526 float temp;
2527 brush_t *n;
2528
2529 if ( radiant_entityMode.GetBool() ) {
2530 return;
2531 }
2532
2533 if (!DragDelta(x, y, junk)) {
2534 return;
2535 }
2536
2537 // delete the current selection
2538 if (selected_brushes.next != &selected_brushes) {
2539 Brush_Free(selected_brushes.next);
2540 }
2541
2542 SnapToPoint(m_nPressx, m_nPressy, mins);
2543
2544 int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
2545
2546 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom[nDim] / g_qeglobals.d_gridsize));
2547 SnapToPoint(x, y, maxs);
2548 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top[nDim] / g_qeglobals.d_gridsize));
2549 if (maxs[nDim] <= mins[nDim]) {
2550 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
2551 }
2552
2553 for (i = 0; i < 3; i++) {
2554 if (mins[i] == maxs[i]) {
2555 return; // don't create a degenerate brush
2556 }
2557
2558 if (mins[i] > maxs[i]) {
2559 temp = mins[i];
2560 mins[i] = maxs[i];
2561 maxs[i] = temp;
2562 }
2563 }
2564
2565 n = Brush_Create(mins, maxs, &g_qeglobals.d_texturewin.texdef);
2566 if (!n) {
2567 return;
2568 }
2569
2570 idVec3 vSize;
2571 VectorSubtract(maxs, mins, vSize);
2572 g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
2573 g_pParentWnd->SetStatusText(2, g_strStatus);
2574
2575 Brush_AddToList(n, &selected_brushes);
2576
2577 Entity_LinkBrush(world_entity, n);
2578
2579 Brush_Build(n);
2580
2581 // Sys_UpdateWindows (W_ALL);
2582 Sys_UpdateWindows(W_XY | W_CAMERA);
2583 }
2584
2585 /*
2586 =======================================================================================================================
2587 XY_MouseMoved
2588 =======================================================================================================================
2589 */
XY_MouseMoved(int x,int y,int buttons)2590 bool CXYWnd::XY_MouseMoved(int x, int y, int buttons) {
2591 idVec3 point;
2592
2593 if (!m_nButtonstate) {
2594 if (g_bCrossHairs) {
2595 ::ShowCursor(FALSE);
2596 Sys_UpdateWindows(W_XY | W_XY_OVERLAY);
2597 ::ShowCursor(TRUE);
2598 }
2599
2600 return false;
2601 }
2602
2603 //
2604 // lbutton without selection = drag new brush if (m_nButtonstate == MK_LBUTTON &&
2605 // !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint &&
2606 // g_qeglobals.d_select_mode != sel_splineedit)
2607 //
2608 if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode == sel_brush) {
2609 NewBrushDrag(x, y);
2610 return false;
2611 }
2612
2613 // lbutton (possibly with control and or shift) with selection = drag selection
2614 if (m_nButtonstate & MK_LBUTTON) {
2615 Drag_MouseMoved(x, y, buttons);
2616 Sys_UpdateWindows(W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
2617 return false;
2618 }
2619
2620 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
2621
2622 // control mbutton = move camera
2623 if (m_nButtonstate == (MK_CONTROL | nMouseButton)) {
2624 SnapToPoint(x, y, point);
2625 VectorCopyXY(point, g_pParentWnd->GetCamera()->Camera().origin);
2626 Sys_UpdateWindows(W_XY_OVERLAY | W_CAMERA);
2627 return false;
2628 }
2629
2630 // shift mbutton = move z checker
2631 if (m_nButtonstate == (MK_SHIFT | nMouseButton)) {
2632 if (RotateMode() || g_bPatchBendMode) {
2633 SnapToPoint(x, y, point);
2634 VectorCopyXY(point, g_vRotateOrigin);
2635 if (g_bPatchBendMode) {
2636 VectorCopy(point, g_vBendOrigin);
2637 }
2638
2639 Sys_UpdateWindows(W_XY);
2640 return false;
2641 }
2642 else {
2643 SnapToPoint(x, y, point);
2644 if (m_nViewType == XY) {
2645 z.origin[0] = point[0];
2646 z.origin[1] = point[1];
2647 }
2648 else if (m_nViewType == YZ) {
2649 z.origin[0] = point[1];
2650 z.origin[1] = point[2];
2651 }
2652 else {
2653 z.origin[0] = point[0];
2654 z.origin[1] = point[2];
2655 }
2656 }
2657
2658 Sys_UpdateWindows(W_XY_OVERLAY | W_Z);
2659 return false;
2660 }
2661
2662 // mbutton = angle camera
2663 if
2664 (
2665 (g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
2666 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT | MK_CONTROL | MK_RBUTTON))
2667 ) {
2668 SnapToPoint(x, y, point);
2669 VectorSubtract(point, g_pParentWnd->GetCamera()->Camera().origin, point);
2670
2671 int n1 = (m_nViewType == XY) ? 1 : 2;
2672 int n2 = (m_nViewType == YZ) ? 1 : 0;
2673 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
2674 if (point[n1] || point[n2]) {
2675 g_pParentWnd->GetCamera()->Camera().angles[nAngle] = RAD2DEG( atan2(point[n1], point[n2]) );
2676 Sys_UpdateWindows(W_CAMERA_IFON | W_XY_OVERLAY);
2677 }
2678
2679 return false;
2680 }
2681
2682 // rbutton = drag xy origin
2683 if (m_nButtonstate == MK_RBUTTON) {
2684 Sys_GetCursorPos(&x, &y);
2685
2686 if (x != m_ptCursor.x || y != m_ptCursor.y) {
2687 if ((GetAsyncKeyState(VK_MENU) & 0x8000)) {
2688 int *px = &x;
2689 long *px2 = &m_ptCursor.x;
2690
2691 if (fDiff(y, m_ptCursor.y) > fDiff(x, m_ptCursor.x)) {
2692 px = &y;
2693 px2 = &m_ptCursor.y;
2694 }
2695
2696 if (*px > *px2) {
2697 // zoom in
2698 SetScale( Scale() * 1.1f );
2699 if ( Scale() < 0.1f ) {
2700 SetScale( 0.1f );
2701 }
2702 }
2703 else if (*px < *px2) {
2704 // zoom out
2705 SetScale( Scale() * 0.9f );
2706 if ( Scale() > 16.0f ) {
2707 SetScale( 16.0f );
2708 }
2709 }
2710
2711 *px2 = *px;
2712 Sys_UpdateWindows(W_XY | W_XY_OVERLAY);
2713 }
2714 else {
2715 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2716 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2717 m_vOrigin[nDim1] -= (x - m_ptCursor.x) / m_fScale;
2718 m_vOrigin[nDim2] += (y - m_ptCursor.y) / m_fScale;
2719 SetCursorPos(m_ptCursor.x, m_ptCursor.y);
2720 ::ShowCursor(FALSE);
2721
2722 // XY_Draw(); RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
2723 Sys_UpdateWindows(W_XY | W_XY_OVERLAY);
2724
2725 // ::ShowCursor(TRUE);
2726 }
2727 }
2728
2729 return false;
2730 }
2731
2732 return false;
2733 }
2734
2735 /*
2736 =======================================================================================================================
2737 DRAWING �
2738 XY_DrawGrid
2739 =======================================================================================================================
2740 */
XY_DrawGrid()2741 void CXYWnd::XY_DrawGrid() {
2742 float x, y, xb, xe, yb, ye;
2743 int w, h;
2744 char text[32];
2745
2746 int startPos = max ( 64 , g_qeglobals.d_gridsize );
2747
2748 w = m_nWidth / 2 / m_fScale;
2749 h = m_nHeight / 2 / m_fScale;
2750
2751 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2752 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2753
2754 // int nDim1 = 0; int nDim2 = 1;
2755 xb = m_vOrigin[nDim1] - w;
2756 if (xb < region_mins[nDim1]) {
2757 xb = region_mins[nDim1];
2758 }
2759
2760 xb = startPos * floor(xb / startPos);
2761
2762 xe = m_vOrigin[nDim1] + w;
2763 if (xe > region_maxs[nDim1]) {
2764 xe = region_maxs[nDim1];
2765 }
2766
2767 xe = startPos * ceil(xe / startPos);
2768
2769 yb = m_vOrigin[nDim2] - h;
2770 if (yb < region_mins[nDim2]) {
2771 yb = region_mins[nDim2];
2772 }
2773
2774 yb = startPos * floor(yb / startPos);
2775
2776 ye = m_vOrigin[nDim2] + h;
2777 if (ye > region_maxs[nDim2]) {
2778 ye = region_maxs[nDim2];
2779 }
2780
2781 ye = startPos * ceil(ye / startPos);
2782
2783 // draw major blocks
2784 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMAJOR].ToFloatPtr());
2785
2786 int stepSize = 64 * 0.1 / m_fScale;
2787 if (stepSize < 64) {
2788 stepSize = max ( 64 , g_qeglobals.d_gridsize );
2789 }
2790 else {
2791 int i;
2792 for (i = 1; i < stepSize; i <<= 1) {
2793 }
2794
2795 stepSize = i;
2796 }
2797
2798 if (g_qeglobals.d_showgrid) {
2799 qglBegin(GL_LINES);
2800
2801 for (x = xb; x <= xe; x += stepSize) {
2802 qglVertex2f(x, yb);
2803 qglVertex2f(x, ye);
2804 }
2805
2806 for (y = yb; y <= ye; y += stepSize) {
2807 qglVertex2f(xb, y);
2808 qglVertex2f(xe, y);
2809 }
2810
2811 qglEnd();
2812 }
2813
2814 // draw minor blocks
2815 if ( m_fScale > .1 &&
2816 g_qeglobals.d_showgrid &&
2817 g_qeglobals.d_gridsize * m_fScale >= 4 &&
2818 !g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR].Compare( g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK] ) ) {
2819
2820 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR].ToFloatPtr());
2821
2822 qglBegin(GL_LINES);
2823 for (x = xb; x < xe; x += g_qeglobals.d_gridsize) {
2824 if (!((int)x & (startPos - 1))) {
2825 continue;
2826 }
2827
2828 qglVertex2f(x, yb);
2829 qglVertex2f(x, ye);
2830 }
2831
2832 for (y = yb; y < ye; y += g_qeglobals.d_gridsize) {
2833 if (!((int)y & (startPos - 1))) {
2834 continue;
2835 }
2836
2837 qglVertex2f(xb, y);
2838 qglVertex2f(xe, y);
2839 }
2840
2841 qglEnd();
2842 }
2843
2844
2845 // draw ZClip boundaries (if applicable)...
2846 //
2847 if (m_nViewType == XZ || m_nViewType == YZ)
2848 {
2849 if (g_pParentWnd->GetZWnd()->m_pZClip) // should always be the case at this point I think, but this is safer
2850 {
2851 if (g_pParentWnd->GetZWnd()->m_pZClip->IsEnabled())
2852 {
2853 qglColor3f(ZCLIP_COLOUR);
2854 qglLineWidth(2);
2855 qglBegin (GL_LINES);
2856
2857 qglVertex2f (xb, g_pParentWnd->GetZWnd()->m_pZClip->GetTop());
2858 qglVertex2f (xe, g_pParentWnd->GetZWnd()->m_pZClip->GetTop());
2859
2860 qglVertex2f (xb, g_pParentWnd->GetZWnd()->m_pZClip->GetBottom());
2861 qglVertex2f (xe, g_pParentWnd->GetZWnd()->m_pZClip->GetBottom());
2862
2863 qglEnd ();
2864 qglLineWidth(1);
2865 }
2866 }
2867 }
2868
2869
2870
2871
2872 // draw coordinate text if needed
2873 if (g_qeglobals.d_savedinfo.show_coordinates) {
2874 // glColor4f(0, 0, 0, 0);
2875 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT].ToFloatPtr());
2876
2877 float lastRaster = xb;
2878
2879 for (x = xb; x < xe; x += stepSize) {
2880 qglRasterPos2f(x, m_vOrigin[nDim2] + h - 10 / m_fScale);
2881 sprintf(text, "%i", (int)x);
2882 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
2883 }
2884
2885 for (y = yb; y < ye; y += stepSize) {
2886 qglRasterPos2f(m_vOrigin[nDim1] - w + 1, y);
2887 sprintf(text, "%i", (int)y);
2888 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
2889 }
2890
2891 if (Active()) {
2892 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME].ToFloatPtr());
2893 }
2894
2895 qglRasterPos2f(m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale);
2896
2897 char cView[20];
2898 if (m_nViewType == XY) {
2899 strcpy(cView, "XY Top");
2900 }
2901 else if (m_nViewType == XZ) {
2902 strcpy(cView, "XZ Front");
2903 }
2904 else {
2905 strcpy(cView, "YZ Side");
2906 }
2907
2908 qglCallLists(strlen(cView), GL_UNSIGNED_BYTE, cView);
2909 }
2910
2911 /*
2912 * if (true) { qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_GRIDMINOR]);
2913 * qglBegin (GL_LINES); qglVertex2f (x, yb); qglVertex2f (x, ye); qglEnd(); }
2914 */
2915 }
2916
2917 /*
2918 =======================================================================================================================
2919 XY_DrawBlockGrid
2920 =======================================================================================================================
2921 */
XY_DrawBlockGrid()2922 void CXYWnd::XY_DrawBlockGrid() {
2923 float x, y, xb, xe, yb, ye;
2924 int w, h;
2925 char text[32];
2926
2927 w = m_nWidth / 2 / m_fScale;
2928 h = m_nHeight / 2 / m_fScale;
2929
2930 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2931 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2932
2933 xb = m_vOrigin[nDim1] - w;
2934 if (xb < region_mins[nDim1]) {
2935 xb = region_mins[nDim1];
2936 }
2937
2938 xb = 1024 * floor(xb / 1024);
2939
2940 xe = m_vOrigin[nDim1] + w;
2941 if (xe > region_maxs[nDim1]) {
2942 xe = region_maxs[nDim1];
2943 }
2944
2945 xe = 1024 * ceil(xe / 1024);
2946
2947 yb = m_vOrigin[nDim2] - h;
2948 if (yb < region_mins[nDim2]) {
2949 yb = region_mins[nDim2];
2950 }
2951
2952 yb = 1024 * floor(yb / 1024);
2953
2954 ye = m_vOrigin[nDim2] + h;
2955 if (ye > region_maxs[nDim2]) {
2956 ye = region_maxs[nDim2];
2957 }
2958
2959 ye = 1024 * ceil(ye / 1024);
2960
2961 // draw major blocks
2962 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK].ToFloatPtr());
2963 qglLineWidth(0.5);
2964
2965 qglBegin(GL_LINES);
2966
2967 for (x = xb; x <= xe; x += 1024) {
2968 qglVertex2f(x, yb);
2969 qglVertex2f(x, ye);
2970 }
2971
2972 for (y = yb; y <= ye; y += 1024) {
2973 qglVertex2f(xb, y);
2974 qglVertex2f(xe, y);
2975 }
2976
2977 qglEnd();
2978 qglLineWidth(0.25);
2979
2980 // draw coordinate text if needed
2981 for (x = xb; x < xe; x += 1024) {
2982 for (y = yb; y < ye; y += 1024) {
2983 qglRasterPos2f(x + 512, y + 512);
2984 sprintf(text, "%i,%i", (int)floor(x / 1024), (int)floor(y / 1024));
2985 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
2986 }
2987 }
2988
2989 qglColor4f(0, 0, 0, 0);
2990 }
2991
GLColoredBoxWithLabel(float x,float y,float size,idVec4 color,const char * text,idVec4 textColor,float xofs,float yofs,float lineSize)2992 void GLColoredBoxWithLabel(float x, float y, float size, idVec4 color, const char *text, idVec4 textColor, float xofs, float yofs, float lineSize) {
2993 globalImages->BindNull();
2994 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2995 qglDisable(GL_CULL_FACE);
2996 qglDisable(GL_BLEND);
2997 qglColor4f(color[0], color[1], color[2], color[3]);
2998 qglBegin(GL_QUADS);
2999 qglVertex3f(x - size, y - size, 0);
3000 qglVertex3f(x + size, y - size, 0);
3001 qglVertex3f(x + size, y + size, 0);
3002 qglVertex3f(x - size, y + size, 0);
3003 qglEnd();
3004
3005 qglColor4f(textColor[0], textColor[1], textColor[2], textColor[3]);
3006 qglLineWidth(lineSize);
3007 qglRasterPos2f(x + xofs, y + yofs);
3008 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
3009 }
3010
3011 /*
3012 =======================================================================================================================
3013 =======================================================================================================================
3014 */
DrawRotateIcon()3015 void CXYWnd::DrawRotateIcon() {
3016 float x, y;
3017
3018 if (m_nViewType == XY) {
3019 x = g_vRotateOrigin[0];
3020 y = g_vRotateOrigin[1];
3021 }
3022 else if (m_nViewType == YZ) {
3023 x = g_vRotateOrigin[1];
3024 y = g_vRotateOrigin[2];
3025 }
3026 else {
3027 x = g_vRotateOrigin[0];
3028 y = g_vRotateOrigin[2];
3029 }
3030
3031 qglEnable(GL_BLEND);
3032 globalImages->BindNull();
3033 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3034 qglDisable(GL_CULL_FACE);
3035 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3036 qglColor4f( 0.8f, 0.1f, 0.9f, 0.25f );
3037
3038 qglBegin(GL_QUADS);
3039 qglVertex3f(x - 4, y - 4, 0);
3040 qglVertex3f(x + 4, y - 4, 0);
3041 qglVertex3f(x + 4, y + 4, 0);
3042 qglVertex3f(x - 4, y + 4, 0);
3043 qglEnd();
3044 qglDisable(GL_BLEND);
3045
3046 qglColor4f( 1.0f, 0.2f, 1.0f, 1.0f );
3047 qglBegin(GL_POINTS);
3048 qglVertex3f(x, y, 0);
3049 qglEnd();
3050
3051
3052 int w = m_nWidth / 2 / m_fScale;
3053 int h = m_nHeight / 2 / m_fScale;
3054 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
3055 int nDim2 = (m_nViewType == XY) ? 1 : 2;
3056 x = m_vOrigin[nDim1] - w + 35 / m_fScale;
3057 y = m_vOrigin[nDim2] + h - 40 / m_fScale;
3058 const char *p = "Rotate Z Axis";
3059 if (g_qeglobals.rotateAxis == 1) {
3060 p = "Rotate Y Axis";
3061 } else if (g_qeglobals.rotateAxis == 0) {
3062 p = "Rotate X Axis";
3063 }
3064 idStr str = p;
3065 if (g_qeglobals.flatRotation) {
3066 str += g_qeglobals.flatRotation == 2 ? " Flat [center] " : " Flat [ rot origin ] ";
3067 }
3068 qglRasterPos2f(x, y);
3069 qglCallLists(str.Length(), GL_UNSIGNED_BYTE, str.c_str());
3070 }
3071
3072 /*
3073 =======================================================================================================================
3074 =======================================================================================================================
3075 */
DrawCameraIcon()3076 void CXYWnd::DrawCameraIcon() {
3077 float x, y, a;
3078
3079 if (m_nViewType == XY) {
3080 x = g_pParentWnd->GetCamera()->Camera().origin[0];
3081 y = g_pParentWnd->GetCamera()->Camera().origin[1];
3082 a = g_pParentWnd->GetCamera()->Camera().angles[YAW] * idMath::M_DEG2RAD;
3083 }
3084 else if (m_nViewType == YZ) {
3085 x = g_pParentWnd->GetCamera()->Camera().origin[1];
3086 y = g_pParentWnd->GetCamera()->Camera().origin[2];
3087 a = g_pParentWnd->GetCamera()->Camera().angles[PITCH] * idMath::M_DEG2RAD;
3088 }
3089 else {
3090 x = g_pParentWnd->GetCamera()->Camera().origin[0];
3091 y = g_pParentWnd->GetCamera()->Camera().origin[2];
3092 a = g_pParentWnd->GetCamera()->Camera().angles[PITCH] * idMath::M_DEG2RAD;
3093 }
3094
3095 float scale = 1.0/m_fScale; //jhefty - keep the camera icon proportionally the same size
3096
3097 qglColor3f(0.0, 0.0, 1.0);
3098 qglBegin(GL_LINE_STRIP);
3099 qglVertex3f(x - 16*scale, y, 0);
3100 qglVertex3f(x, y + 8*scale, 0);
3101 qglVertex3f(x + 16*scale, y, 0);
3102 qglVertex3f(x, y - 8*scale, 0);
3103 qglVertex3f(x - 16*scale, y, 0);
3104 qglVertex3f(x + 16*scale, y, 0);
3105 qglEnd();
3106
3107 qglBegin(GL_LINE_STRIP);
3108 qglVertex3f(x + (48 * cos( a + idMath::PI * 0.25f )*scale), y + (48 * sin( a + idMath::PI * 0.25f )*scale), 0);
3109 qglVertex3f(x, y, 0);
3110 qglVertex3f(x + (48 * cos( a - idMath::PI * 0.25f )*scale), y + (48 * sin( a - idMath::PI * 0.25f )*scale), 0);
3111 qglEnd();
3112
3113 #if 0
3114
3115 char text[128];
3116 qglRasterPos2f(x + 64, y + 64);
3117 sprintf(text, "%f", g_pParentWnd->GetCamera()->Camera().angles[YAW]);
3118 qglCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
3119 #endif
3120 }
3121
3122 /*
3123 =======================================================================================================================
3124 =======================================================================================================================
3125 */
DrawZIcon(void)3126 void CXYWnd::DrawZIcon(void) {
3127 if (m_nViewType == XY) {
3128 float x = z.origin[0];
3129 float y = z.origin[1];
3130 qglEnable(GL_BLEND);
3131 globalImages->BindNull();
3132 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
3133 qglDisable(GL_CULL_FACE);
3134 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3135 qglColor4f(0.0, 0.0, 1.0, 0.25);
3136 qglBegin(GL_QUADS);
3137 qglVertex3f(x - 8, y - 8, 0);
3138 qglVertex3f(x + 8, y - 8, 0);
3139 qglVertex3f(x + 8, y + 8, 0);
3140 qglVertex3f(x - 8, y + 8, 0);
3141 qglEnd();
3142 qglDisable(GL_BLEND);
3143
3144 qglColor4f(0.0, 0.0, 1.0, 1);
3145
3146 qglBegin(GL_LINE_LOOP);
3147 qglVertex3f(x - 8, y - 8, 0);
3148 qglVertex3f(x + 8, y - 8, 0);
3149 qglVertex3f(x + 8, y + 8, 0);
3150 qglVertex3f(x - 8, y + 8, 0);
3151 qglEnd();
3152
3153 qglBegin(GL_LINE_STRIP);
3154 qglVertex3f(x - 4, y + 4, 0);
3155 qglVertex3f(x + 4, y + 4, 0);
3156 qglVertex3f(x - 4, y - 4, 0);
3157 qglVertex3f(x + 4, y - 4, 0);
3158 qglEnd();
3159 }
3160 }
3161
3162 /*
3163 =======================================================================================================================
3164 FilterBrush
3165 =======================================================================================================================
3166 */
FilterBrush(brush_t * pb)3167 bool FilterBrush(brush_t *pb) {
3168
3169 if (!pb->owner) {
3170 return false; // during construction
3171 }
3172
3173 if (pb->hiddenBrush) {
3174 return true;
3175 }
3176
3177 if ( pb->forceVisibile ) {
3178 return false;
3179 }
3180
3181 if (g_pParentWnd->GetZWnd()->m_pZClip) // ZClip class up and running? (and hence Z window built)
3182 {
3183 if (g_pParentWnd->GetZWnd()->m_pZClip->IsEnabled())
3184 {
3185 // ZClipping active...
3186 //
3187 if (pb->mins[2] > g_pParentWnd->GetZWnd()->m_pZClip->GetTop() // brush bottom edge is above clip top
3188 ||
3189 pb->maxs[2] < g_pParentWnd->GetZWnd()->m_pZClip->GetBottom()// brush top edge is below clip bottom
3190 )
3191 {
3192 return TRUE;
3193 }
3194 }
3195 }
3196
3197 if (g_qeglobals.d_savedinfo.exclude & (EXCLUDE_CAULK | EXCLUDE_VISPORTALS)) {
3198 //
3199 // filter out the brush only if all faces are caulk if not don't hide the whole
3200 // brush, proceed on a per-face basis (Cam_Draw) ++timo TODO: set this as a
3201 // preference .. show caulk: hide any brush with caulk // don't draw caulk faces
3202 //
3203 face_t *f;
3204 f = pb->brush_faces;
3205 while (f) {
3206 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) {
3207 if (!strstr(f->texdef.name, "caulk")) {
3208 break;
3209 }
3210 } else {
3211 if (strstr(f->texdef.name, "visportal")) {
3212 return true;
3213 }
3214 }
3215
3216 f = f->next;
3217 }
3218
3219 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) {
3220 if (!f) {
3221 return true;
3222 }
3223 }
3224
3225 // ++timo FIXME: .. same deal here?
3226 if (strstr(pb->brush_faces->texdef.name, "donotenter")) {
3227 return true;
3228 }
3229 }
3230
3231 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_HINT) {
3232 if (strstr(pb->brush_faces->texdef.name, "hint")) {
3233 return true;
3234 }
3235 }
3236
3237 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CLIP) {
3238 if (strstr(pb->brush_faces->texdef.name, "clip")) {
3239 return true;
3240 }
3241 }
3242
3243 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_TRIGGERS) {
3244 if (strstr(pb->brush_faces->texdef.name, "trig")) {
3245 return true;
3246 }
3247 }
3248
3249 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_NODRAW) {
3250 if (strstr(pb->brush_faces->texdef.name, "nodraw")) {
3251 return true;
3252 }
3253 }
3254
3255
3256 if (strstr(pb->brush_faces->texdef.name, "skip")) {
3257 return true;
3258 }
3259
3260 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_DYNAMICS) {
3261 if (pb->modelHandle > 0) {
3262 idRenderModel *model = pb->modelHandle;
3263 if ( dynamic_cast<idRenderModelLiquid*>(model) ) {
3264 return true;
3265 }
3266 }
3267 }
3268
3269 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_CURVES) {
3270 if (pb->pPatch) {
3271 return true;
3272 }
3273 }
3274
3275 if (pb->owner == world_entity) {
3276 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_WORLD) {
3277 return true;
3278 }
3279
3280 return false;
3281 }
3282 else {
3283 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_ENT ) {
3284 return ( idStr::Cmpn( pb->owner->eclass->name, "func_static", 10 ) != 0 );
3285 }
3286 }
3287
3288 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_LIGHTS && pb->owner->eclass->nShowFlags & ECLASS_LIGHT ) {
3289 return true;
3290 }
3291
3292 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_COMBATNODES && pb->owner->eclass->nShowFlags & ECLASS_COMBATNODE ) {
3293 return true;
3294 }
3295
3296 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS && pb->owner->eclass->nShowFlags & ECLASS_PATH) {
3297 return true;
3298 }
3299
3300 if ( g_qeglobals.d_savedinfo.exclude & EXCLUDE_MODELS && ( pb->owner->eclass->entityModel != NULL || pb->modelHandle > 0 ) ) {
3301 return true;
3302 }
3303
3304 return false;
3305 }
3306
3307 /*
3308 =======================================================================================================================
3309 PATH LINES �
3310 DrawPathLines Draws connections between entities. Needs to consider all entities, not just ones on screen, because
3311 the lines can be visible when neither end is. Called for both camera view and xy view.
3312 =======================================================================================================================
3313 */
DrawPathLines(void)3314 void DrawPathLines(void) {
3315 int i, k;
3316 idVec3 mid, mid1;
3317 entity_t *se, *te;
3318 brush_t *sb, *tb;
3319 const char *psz;
3320 idVec3 dir, s1, s2;
3321 float len, f;
3322 int arrows;
3323 int num_entities;
3324 const char *ent_target[MAX_MAP_ENTITIES];
3325 entity_t *ent_entity[MAX_MAP_ENTITIES];
3326
3327 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS) {
3328 return;
3329 }
3330
3331 num_entities = 0;
3332 for (te = entities.next; te != &entities && num_entities != MAX_MAP_ENTITIES; te = te->next) {
3333 for (int i = 0; i < 2048; i++) {
3334 if (i == 0) {
3335 ent_target[num_entities] = ValueForKey(te, "target");
3336 } else {
3337 ent_target[num_entities] = ValueForKey(te, va("target%i", i));
3338 }
3339 if (ent_target[num_entities][0]) {
3340 ent_entity[num_entities] = te;
3341 num_entities++;
3342 } else if (i > 16) {
3343 break;
3344 }
3345 }
3346 }
3347
3348 for (se = entities.next; se != &entities; se = se->next) {
3349 psz = ValueForKey(se, "name");
3350
3351 if (psz == NULL || psz[0] == '\0') {
3352 continue;
3353 }
3354
3355 sb = se->brushes.onext;
3356 if (sb == &se->brushes) {
3357 continue;
3358 }
3359
3360 for (k = 0; k < num_entities; k++) {
3361 if (strcmp(ent_target[k], psz)) {
3362 continue;
3363 }
3364
3365 te = ent_entity[k];
3366 tb = te->brushes.onext;
3367 if (tb == &te->brushes) {
3368 continue;
3369 }
3370
3371 mid = sb->owner->origin;
3372 mid1 = tb->owner->origin;
3373
3374 VectorSubtract(mid1, mid, dir);
3375 len = dir.Normalize();
3376 s1[0] = -dir[1] * 8 + dir[0] * 8;
3377 s2[0] = dir[1] * 8 + dir[0] * 8;
3378 s1[1] = dir[0] * 8 + dir[1] * 8;
3379 s2[1] = -dir[0] * 8 + dir[1] * 8;
3380
3381 qglColor3f(se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
3382
3383 qglBegin(GL_LINES);
3384 qglVertex3fv(mid.ToFloatPtr());
3385 qglVertex3fv(mid1.ToFloatPtr());
3386
3387 arrows = (int)(len / 256) + 1;
3388
3389 for (i = 0; i < arrows; i++) {
3390 f = len * (i + 0.5) / arrows;
3391
3392 mid1 = mid + (f * dir);
3393
3394 qglVertex3fv(mid1.ToFloatPtr());
3395 qglVertex3f(mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
3396 qglVertex3fv(mid1.ToFloatPtr());
3397 qglVertex3f(mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
3398 }
3399
3400 qglEnd();
3401 }
3402 }
3403
3404 return;
3405 }
3406
3407 //
3408 // =======================================================================================================================
3409 // can be greatly simplified but per usual i am in a hurry which is not an excuse, just a fact
3410 // =======================================================================================================================
3411 //
PaintSizeInfo(int nDim1,int nDim2,idVec3 vMinBounds,idVec3 vMaxBounds)3412 void CXYWnd::PaintSizeInfo(int nDim1, int nDim2, idVec3 vMinBounds, idVec3 vMaxBounds) {
3413 idVec3 vSize;
3414 VectorSubtract(vMaxBounds, vMinBounds, vSize);
3415
3416 qglColor3f
3417 (
3418 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
3419 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
3420 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65
3421 );
3422
3423 if (m_nViewType == XY) {
3424 qglBegin(GL_LINES);
3425
3426 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
3427 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3428
3429 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3430 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3431
3432 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
3433 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
3434
3435 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
3436 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
3437
3438 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
3439 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
3440
3441 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
3442 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
3443
3444 qglEnd();
3445
3446 qglRasterPos3f(Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
3447 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
3448 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3449
3450 qglRasterPos3f(vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
3451 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
3452 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3453
3454 qglRasterPos3f(vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
3455 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
3456 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3457 }
3458 else if (m_nViewType == XZ) {
3459 qglBegin(GL_LINES);
3460
3461 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
3462 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3463
3464 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3465 qglVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3466
3467 qglVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
3468 qglVertex3f(vMaxBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
3469
3470 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0, vMinBounds[nDim2]);
3471 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMinBounds[nDim2]);
3472
3473 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMinBounds[nDim2]);
3474 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMaxBounds[nDim2]);
3475
3476 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0, vMaxBounds[nDim2]);
3477 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0, vMaxBounds[nDim2]);
3478
3479 qglEnd();
3480
3481 qglRasterPos3f(Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
3482 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
3483 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3484
3485 qglRasterPos3f(vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
3486 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
3487 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3488
3489 qglRasterPos3f(vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
3490 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
3491 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3492 }
3493 else {
3494 qglBegin(GL_LINES);
3495
3496 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
3497 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3498
3499 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3500 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3501
3502 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
3503 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
3504
3505 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
3506 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
3507
3508 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
3509 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
3510
3511 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
3512 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
3513
3514 qglEnd();
3515
3516 qglRasterPos3f(0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
3517 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
3518 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3519
3520 qglRasterPos3f(0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
3521 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
3522 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3523
3524 qglRasterPos3f(0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
3525 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
3526 qglCallLists(g_strDim.GetLength(), GL_UNSIGNED_BYTE, g_strDim);
3527 }
3528 }
3529
3530 /* XY_Draw */
3531 long g_lCount = 0;
3532 long g_lTotal = 0;
3533 extern void DrawBrushEntityName(brush_t *b);
3534
3535 /*
3536 =======================================================================================================================
3537 =======================================================================================================================
3538 */
XY_Draw()3539 void CXYWnd::XY_Draw() {
3540 brush_t *brush;
3541 float w, h;
3542 entity_t *e;
3543 idVec3 mins, maxs;
3544 int drawn, culled;
3545 int i;
3546
3547 if (!active_brushes.next) {
3548 return; // not valid yet
3549 }
3550
3551 // clear
3552 m_bDirty = false;
3553
3554 GL_State( GLS_DEFAULT );
3555 qglViewport(0, 0, m_nWidth, m_nHeight);
3556 qglScissor(0, 0, m_nWidth, m_nHeight);
3557 qglClearColor
3558 (
3559 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
3560 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
3561 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],
3562 0
3563 );
3564
3565 qglDisable(GL_DEPTH_TEST);
3566 qglDisable(GL_CULL_FACE);
3567 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3568
3569 // set up viewpoint
3570 qglMatrixMode(GL_PROJECTION);
3571 qglLoadIdentity();
3572
3573 w = m_nWidth / 2 / m_fScale;
3574 h = m_nHeight / 2 / m_fScale;
3575
3576 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
3577 int nDim2 = (m_nViewType == XY) ? 1 : 2;
3578 mins[0] = m_vOrigin[nDim1] - w;
3579 maxs[0] = m_vOrigin[nDim1] + w;
3580 mins[1] = m_vOrigin[nDim2] - h;
3581 maxs[1] = m_vOrigin[nDim2] + h;
3582
3583 idBounds viewBounds( mins, maxs );
3584 viewBounds[0].z = -99999;
3585 viewBounds[1].z = 99999;
3586
3587 qglOrtho(mins[0], maxs[0], mins[1], maxs[1], MIN_WORLD_COORD, MAX_WORLD_COORD);
3588
3589 // draw stuff
3590 globalImages->BindNull();
3591 // now draw the grid
3592 qglLineWidth(0.25);
3593 XY_DrawGrid();
3594 qglLineWidth(0.5);
3595
3596 drawn = culled = 0;
3597
3598 if (m_nViewType != XY) {
3599 qglPushMatrix();
3600 if (m_nViewType == YZ) {
3601 qglRotatef(-90, 0, 1, 0); // put Z going up
3602 }
3603
3604 // else
3605 qglRotatef(-90, 1, 0, 0); // put Z going up
3606 }
3607
3608 e = world_entity;
3609
3610 for ( brush = active_brushes.next; brush != &active_brushes; brush = brush->next ) {
3611 if ( brush->forceVisibile || ( brush->owner->eclass->nShowFlags & ( ECLASS_LIGHT | ECLASS_PROJECTEDLIGHT ) ) ) {
3612 } else if ( brush->mins[nDim1] > maxs[0] || brush->mins[nDim2] > maxs[1] || brush->maxs[nDim1] < mins[0] || brush->maxs[nDim2] < mins[1] ) {
3613 culled++;
3614 continue; // off screen
3615 }
3616
3617 if ( FilterBrush(brush) ) {
3618 continue;
3619 }
3620
3621 drawn++;
3622
3623 if (brush->owner != e && brush->owner) {
3624 qglColor3fv(brush->owner->eclass->color.ToFloatPtr());
3625 }
3626 else {
3627 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES].ToFloatPtr());
3628 }
3629
3630 Brush_DrawXY( brush, m_nViewType );
3631 }
3632
3633 DrawPathLines();
3634
3635 // draw pointfile
3636 if (g_qeglobals.d_pointfile_display_list) {
3637 qglCallList(g_qeglobals.d_pointfile_display_list);
3638 }
3639
3640 if (!(m_nViewType == XY)) {
3641 qglPopMatrix();
3642 }
3643
3644 // draw block grid
3645 if (g_qeglobals.show_blocks) {
3646 XY_DrawBlockGrid();
3647 }
3648
3649 // now draw selected brushes
3650 if (m_nViewType != XY) {
3651 qglPushMatrix();
3652 if (m_nViewType == YZ) {
3653 qglRotatef(-90, 0, 1, 0); // put Z going up
3654 }
3655
3656 // else
3657 qglRotatef(-90, 1, 0, 0); // put Z going up
3658 }
3659
3660 qglPushMatrix();
3661 qglTranslatef
3662 (
3663 g_qeglobals.d_select_translate[0],
3664 g_qeglobals.d_select_translate[1],
3665 g_qeglobals.d_select_translate[2]
3666 );
3667
3668 if (RotateMode()) {
3669 qglColor3f( 0.8f, 0.1f, 0.9f );
3670 }
3671 else if (ScaleMode()) {
3672 qglColor3f( 0.1f, 0.8f, 0.1f );
3673 }
3674 else {
3675 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES].ToFloatPtr());
3676 }
3677
3678 if (g_PrefsDlg.m_bNoStipple == FALSE) {
3679 qglEnable(GL_LINE_STIPPLE);
3680 qglLineStipple(3, 0xaaaa);
3681 }
3682
3683 qglLineWidth(1);
3684
3685 idVec3 vMinBounds;
3686 idVec3 vMaxBounds;
3687 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = 999999.9f;
3688 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = -999999.9f;
3689
3690 int nSaveDrawn = drawn;
3691 bool bFixedSize = false;
3692 for (brush = selected_brushes.next; brush != &selected_brushes; brush = brush->next) {
3693 drawn++;
3694 Brush_DrawXY(brush, m_nViewType, true);
3695
3696 if (!bFixedSize) {
3697 if (brush->owner->eclass->fixedsize) {
3698 bFixedSize = true;
3699 }
3700
3701 if (g_PrefsDlg.m_bSizePaint) {
3702 for (i = 0; i < 3; i++) {
3703 if (brush->mins[i] < vMinBounds[i]) {
3704 vMinBounds[i] = brush->mins[i];
3705 }
3706
3707 if (brush->maxs[i] > vMaxBounds[i]) {
3708 vMaxBounds[i] = brush->maxs[i];
3709 }
3710 }
3711 }
3712 }
3713 }
3714
3715 if (g_PrefsDlg.m_bNoStipple == FALSE) {
3716 qglDisable(GL_LINE_STIPPLE);
3717 }
3718
3719 qglLineWidth(0.5);
3720
3721 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint) {
3722 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
3723 }
3724
3725 // edge / vertex flags
3726 if (g_qeglobals.d_select_mode == sel_vertex) {
3727 qglPointSize(4);
3728 qglColor3f(0, 1, 0);
3729 qglBegin(GL_POINTS);
3730 for (i = 0; i < g_qeglobals.d_numpoints; i++) {
3731 qglVertex3fv(g_qeglobals.d_points[i].ToFloatPtr());
3732 }
3733
3734 qglEnd();
3735 qglPointSize(1);
3736 }
3737 else if (g_qeglobals.d_select_mode == sel_edge) {
3738 float *v1, *v2;
3739
3740 qglPointSize(4);
3741 qglColor3f(0, 0, 1);
3742 qglBegin(GL_POINTS);
3743 for (i = 0; i < g_qeglobals.d_numedges; i++) {
3744 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1].ToFloatPtr();
3745 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2].ToFloatPtr();
3746 qglVertex3f((v1[0] + v2[0]) * 0.5, (v1[1] + v2[1]) * 0.5, (v1[2] + v2[2]) * 0.5);
3747 }
3748
3749 qglEnd();
3750 qglPointSize(1);
3751 }
3752
3753 g_splineList->draw (static_cast<bool>(g_qeglobals.d_select_mode == sel_editpoint || g_qeglobals.d_select_mode == sel_addpoint));
3754
3755 if (g_pParentWnd->GetNurbMode() && g_pParentWnd->GetNurb()->GetNumValues()) {
3756 int maxage = g_pParentWnd->GetNurb()->GetNumValues();
3757 int time = 0;
3758 qglColor3f(0, 0, 1);
3759 qglPointSize(1);
3760 qglBegin(GL_POINTS);
3761 g_pParentWnd->GetNurb()->SetOrder(3);
3762 for (i = 0; i < 100; i++) {
3763 idVec2 v = g_pParentWnd->GetNurb()->GetCurrentValue(time);
3764 qglVertex3f(v.x, v.y, 0.0f);
3765 time += 10;
3766 }
3767 qglEnd();
3768 qglPointSize(4);
3769 qglColor3f(0, 0, 1);
3770 qglBegin(GL_POINTS);
3771 for (i = 0; i < maxage; i++) {
3772 idVec2 v = g_pParentWnd->GetNurb()->GetValue(i);
3773 qglVertex3f(v.x, v.y, 0.0f);
3774 }
3775 qglEnd();
3776 qglPointSize(1);
3777 }
3778
3779 qglPopMatrix();
3780
3781 qglTranslatef
3782 (
3783 -g_qeglobals.d_select_translate[0],
3784 -g_qeglobals.d_select_translate[1],
3785 -g_qeglobals.d_select_translate[2]
3786 );
3787
3788 if (!(m_nViewType == XY)) {
3789 qglPopMatrix();
3790 }
3791
3792 // area selection hack
3793 if (g_qeglobals.d_select_mode == sel_area) {
3794 qglEnable(GL_BLEND);
3795 qglPolygonMode ( GL_FRONT_AND_BACK , GL_FILL );
3796 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3797 qglColor4f(0.0, 0.0, 1.0, 0.25);
3798 qglRectf
3799 (
3800 g_qeglobals.d_vAreaTL[nDim1],
3801 g_qeglobals.d_vAreaTL[nDim2],
3802 g_qeglobals.d_vAreaBR[nDim1],
3803 g_qeglobals.d_vAreaBR[nDim2]
3804 );
3805 qglDisable(GL_BLEND);
3806 qglPolygonMode ( GL_FRONT_AND_BACK , GL_LINE );
3807 qglColor3f(1.0f, 1.0f, 1.0f);
3808 qglRectf
3809 (
3810 g_qeglobals.d_vAreaTL[nDim1],
3811 g_qeglobals.d_vAreaTL[nDim2],
3812 g_qeglobals.d_vAreaBR[nDim1],
3813 g_qeglobals.d_vAreaBR[nDim2]
3814 );
3815
3816 }
3817
3818 // now draw camera point
3819 DrawCameraIcon();
3820 DrawZIcon();
3821
3822 if (RotateMode()) {
3823 DrawRotateIcon();
3824 }
3825
3826 /// Draw a "precision crosshair" if enabled
3827 if( m_precisionCrosshairMode != PRECISION_CROSSHAIR_NONE )
3828 DrawPrecisionCrosshair();
3829
3830 qglFlush();
3831
3832 // QE_CheckOpenGLForErrors();
3833 }
3834
3835
3836 /*
3837 =======================================================================================================================
3838 =======================================================================================================================
3839 */
GetOrigin()3840 idVec3 &CXYWnd::GetOrigin() {
3841 return m_vOrigin;
3842 }
3843
3844 /*
3845 =======================================================================================================================
3846 =======================================================================================================================
3847 */
SetOrigin(idVec3 org)3848 void CXYWnd::SetOrigin(idVec3 org) {
3849 m_vOrigin[0] = org[0];
3850 m_vOrigin[1] = org[1];
3851 m_vOrigin[2] = org[2];
3852 }
3853
3854 /*
3855 =======================================================================================================================
3856 =======================================================================================================================
3857 */
OnSize(UINT nType,int cx,int cy)3858 void CXYWnd::OnSize(UINT nType, int cx, int cy) {
3859 CWnd::OnSize(nType, cx, cy);
3860
3861 CRect rect;
3862 GetClientRect(rect);
3863 m_nWidth = rect.Width();
3864 m_nHeight = rect.Height();
3865 InvalidateRect(NULL, false);
3866 }
3867
3868 brush_t hold_brushes;
3869
3870 /*
3871 =======================================================================================================================
3872 =======================================================================================================================
3873 */
Clip()3874 void CXYWnd::Clip() {
3875 if (ClipMode()) {
3876 hold_brushes.next = &hold_brushes;
3877 ProduceSplitLists();
3878
3879 // brush_t* pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
3880 brush_t *pList;
3881 if (g_PrefsDlg.m_bSwitchClip) {
3882 pList = ((m_nViewType == XZ) ? g_bSwitch : !g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
3883 }
3884 else {
3885 pList = ((m_nViewType == XZ) ? !g_bSwitch : g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
3886 }
3887
3888 if (pList->next != pList) {
3889 Brush_CopyList(pList, &hold_brushes);
3890 CleanList(&g_brFrontSplits);
3891 CleanList(&g_brBackSplits);
3892 Select_Delete();
3893 Brush_CopyList(&hold_brushes, &selected_brushes);
3894 if (RogueClipMode()) {
3895 RetainClipMode(false);
3896 }
3897 else {
3898 RetainClipMode(true);
3899 }
3900
3901 Sys_UpdateWindows(W_ALL);
3902 }
3903 }
3904 else if (PathMode()) {
3905 FinishSmartCreation();
3906 if (g_pPathFunc) {
3907 g_pPathFunc(true, g_nPathCount);
3908 }
3909
3910 g_pPathFunc = NULL;
3911 g_nPathCount = 0;
3912 g_bPathMode = false;
3913 }
3914 }
3915
3916 /*
3917 =======================================================================================================================
3918 =======================================================================================================================
3919 */
SplitClip()3920 void CXYWnd::SplitClip() {
3921 ProduceSplitLists();
3922 if ((g_brFrontSplits.next != &g_brFrontSplits) && (g_brBackSplits.next != &g_brBackSplits)) {
3923 Select_Delete();
3924 Brush_CopyList(&g_brFrontSplits, &selected_brushes);
3925 Brush_CopyList(&g_brBackSplits, &selected_brushes);
3926 CleanList(&g_brFrontSplits);
3927 CleanList(&g_brBackSplits);
3928 if (RogueClipMode()) {
3929 RetainClipMode(false);
3930 }
3931 else {
3932 RetainClipMode(true);
3933 }
3934 }
3935 }
3936
3937 /*
3938 =======================================================================================================================
3939 =======================================================================================================================
3940 */
FlipClip()3941 void CXYWnd::FlipClip() {
3942 g_bSwitch = !g_bSwitch;
3943 Sys_UpdateWindows(XY | W_CAMERA_IFON);
3944 }
3945
3946 //
3947 // =======================================================================================================================
3948 // makes sure the selected brush or camera is in view
3949 // =======================================================================================================================
3950 //
PositionView()3951 void CXYWnd::PositionView() {
3952 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
3953 int nDim2 = (m_nViewType == XY) ? 1 : 2;
3954 brush_t *b = selected_brushes.next;
3955 if (b && b->next != b) {
3956 m_vOrigin[nDim1] = b->mins[nDim1];
3957 m_vOrigin[nDim2] = b->mins[nDim2];
3958 }
3959 else {
3960 m_vOrigin[nDim1] = g_pParentWnd->GetCamera()->Camera().origin[nDim1];
3961 m_vOrigin[nDim2] = g_pParentWnd->GetCamera()->Camera().origin[nDim2];
3962 }
3963 }
3964
3965 /*
3966 =======================================================================================================================
3967 =======================================================================================================================
3968 */
VectorCopyXY(const idVec3 & in,idVec3 & out)3969 void CXYWnd::VectorCopyXY(const idVec3 &in, idVec3 &out) {
3970 if (m_nViewType == XY) {
3971 out[0] = in[0];
3972 out[1] = in[1];
3973 }
3974 else if (m_nViewType == XZ) {
3975 out[0] = in[0];
3976 out[2] = in[2];
3977 }
3978 else {
3979 out[1] = in[1];
3980 out[2] = in[2];
3981 }
3982 }
3983
3984 /*
3985 =======================================================================================================================
3986 =======================================================================================================================
3987 */
OnDestroy()3988 void CXYWnd::OnDestroy() {
3989 CWnd::OnDestroy();
3990
3991 // delete this;
3992 }
3993
3994 /*
3995 =======================================================================================================================
3996 =======================================================================================================================
3997 */
SetViewType(int n)3998 void CXYWnd::SetViewType(int n) {
3999 m_nViewType = n;
4000 char *p = "YZ Side";
4001 if (m_nViewType == XY) {
4002 p = "XY Top";
4003 } else if (m_nViewType == XZ) {
4004 p = "XZ Front";
4005 }
4006 SetWindowText(p);
4007 };
4008
4009 /*
4010 =======================================================================================================================
4011 =======================================================================================================================
4012 */
Redraw(unsigned int nBits)4013 void CXYWnd::Redraw(unsigned int nBits) {
4014 m_nUpdateBits = nBits;
4015 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
4016 m_nUpdateBits = W_XY;
4017 }
4018
4019 /*
4020 =======================================================================================================================
4021 =======================================================================================================================
4022 */
RotateMode()4023 bool CXYWnd::RotateMode() {
4024 return g_bRotateMode;
4025 }
4026
4027 /*
4028 =======================================================================================================================
4029 =======================================================================================================================
4030 */
ScaleMode()4031 bool CXYWnd::ScaleMode() {
4032 return g_bScaleMode;
4033 }
4034
4035 /*
4036 =======================================================================================================================
4037 =======================================================================================================================
4038 */
4039 extern bool Select_OnlyModelsSelected();
SetRotateMode(bool bMode)4040 bool CXYWnd::SetRotateMode(bool bMode) {
4041 if (bMode && selected_brushes.next != &selected_brushes) {
4042 g_bRotateMode = true;
4043 if (Select_OnlyModelsSelected()) {
4044 Select_GetTrueMid(g_vRotateOrigin);
4045 } else {
4046 Select_GetMid(g_vRotateOrigin);
4047 }
4048 g_vRotation.Zero();
4049 Select_InitializeRotation();
4050 }
4051 else {
4052 if (bMode) {
4053 Sys_Status("Need a brush selected to turn on Mouse Rotation mode\n");
4054 }
4055
4056 g_bRotateMode = false;
4057 Select_FinalizeRotation();
4058 }
4059
4060 RedrawWindow();
4061 return g_bRotateMode;
4062 }
4063
4064 /*
4065 =======================================================================================================================
4066 =======================================================================================================================
4067 */
SetScaleMode(bool bMode)4068 void CXYWnd::SetScaleMode(bool bMode) {
4069 g_bScaleMode = bMode;
4070 RedrawWindow();
4071 }
4072
4073 //
4074 // =======================================================================================================================
4075 // xy - z xz - y yz - x
4076 // =======================================================================================================================
4077 //
OnSelectMouserotate()4078 void CXYWnd::OnSelectMouserotate() {
4079 // TODO: Add your command handler code here
4080 }
4081
4082 /*
4083 =======================================================================================================================
4084 =======================================================================================================================
4085 */
CleanCopyEntities()4086 void CleanCopyEntities() {
4087 entity_t *pe = g_enClipboard.next;
4088 while (pe != NULL && pe != &g_enClipboard) {
4089 entity_t *next = pe->next;
4090 pe->epairs.Clear();
4091
4092 Entity_Free(pe);
4093 pe = next;
4094 }
4095
4096 g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
4097 }
4098
4099 /*
4100 =======================================================================================================================
4101 =======================================================================================================================
4102 */
Entity_CopyClone(entity_t * e)4103 entity_t *Entity_CopyClone(entity_t *e) {
4104 entity_t *n;
4105
4106 n = Entity_New();
4107 n->brushes.onext = n->brushes.oprev = &n->brushes;
4108 n->eclass = e->eclass;
4109 n->rotation = e->rotation;
4110
4111 // add the entity to the entity list
4112 n->next = g_enClipboard.next;
4113 g_enClipboard.next = n;
4114 n->next->prev = n;
4115 n->prev = &g_enClipboard;
4116
4117 n->epairs = e->epairs;
4118
4119 return n;
4120 }
4121
4122 /*
4123 =======================================================================================================================
4124 =======================================================================================================================
4125 */
OnList(entity_t * pFind,CPtrArray * pList)4126 bool OnList(entity_t *pFind, CPtrArray *pList) {
4127 int nSize = pList->GetSize();
4128 while (nSize-- > 0) {
4129 entity_t *pEntity = reinterpret_cast < entity_t * > (pList->GetAt(nSize));
4130 if (pEntity == pFind) {
4131 return true;
4132 }
4133 }
4134
4135 return false;
4136 }
4137
4138 /*
4139 =======================================================================================================================
4140 =======================================================================================================================
4141 */
Copy()4142 void CXYWnd::Copy()
4143 {
4144 #if 1
4145 CWaitCursor WaitCursor;
4146 g_Clipboard.SetLength(0);
4147 g_PatchClipboard.SetLength(0);
4148
4149 Map_SaveSelected(&g_Clipboard, &g_PatchClipboard);
4150
4151 bool bClipped = false;
4152 UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
4153 if (nClipboard > 0) {
4154 if (OpenClipboard()) {
4155 ::EmptyClipboard();
4156
4157 long lSize = g_Clipboard.GetLength();
4158 HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, lSize + sizeof (long));
4159 if (h != NULL) {
4160 unsigned char *cp = reinterpret_cast < unsigned char * > (::GlobalLock(h));
4161 memcpy(cp, &lSize, sizeof (long));
4162 cp += sizeof (long);
4163 g_Clipboard.SeekToBegin();
4164 g_Clipboard.Read(cp, lSize);
4165 ::GlobalUnlock(h);
4166 ::SetClipboardData(nClipboard, h);
4167 ::CloseClipboard();
4168 bClipped = true;
4169 }
4170 }
4171 }
4172
4173 if (!bClipped) {
4174 common->Printf("Unable to register Windows clipboard formats, copy/paste between editors will not be possible");
4175 }
4176
4177 /*
4178 * CString strOut; ::GetTempPath(1024, strOut.GetBuffer(1024));
4179 * strOut.ReleaseBuffer(); AddSlash(strOut); strOut += "RadiantClipboard.$$$";
4180 * Map_SaveSelected(strOut.GetBuffer(0));
4181 */
4182 #else
4183 CPtrArray holdArray;
4184 CleanList(&g_brClipboard);
4185 CleanCopyEntities();
4186 for (brush_t * pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next) {
4187 if (pBrush->owner == world_entity) {
4188 brush_t *pClone = Brush_Clone(pBrush);
4189 pClone->owner = NULL;
4190 Brush_AddToList(pClone, &g_brClipboard);
4191 }
4192 else {
4193 if (!OnList(pBrush->owner, &holdArray)) {
4194 entity_t *e = pBrush->owner;
4195 holdArray.Add(reinterpret_cast < void * > (e));
4196
4197 entity_t *pEClone = Entity_CopyClone(e);
4198 for (brush_t * pEB = e->brushes.onext; pEB != &e->brushes; pEB = pEB->onext) {
4199 brush_t *pClone = Brush_Clone(pEB);
4200
4201 // Brush_AddToList (pClone, &g_brClipboard);
4202 Entity_LinkBrush(pEClone, pClone);
4203 Brush_Build(pClone);
4204 }
4205 }
4206 }
4207 }
4208 #endif
4209 }
4210
4211 /*
4212 =======================================================================================================================
4213 =======================================================================================================================
4214 */
Undo()4215 void CXYWnd::Undo() {
4216 /*
4217 * if (g_brUndo.next != &g_brUndo) { g_bScreenUpdates = false; Select_Delete();
4218 * for (brush_t* pBrush = g_brUndo.next ; pBrush != NULL && pBrush != &g_brUndo ;
4219 * pBrush=pBrush->next) { brush_t* pClone = Brush_Clone(pBrush); Brush_AddToList
4220 * (pClone, &active_brushes); Entity_LinkBrush (pBrush->pUndoOwner, pClone);
4221 * Brush_Build(pClone); Select_Brush(pClone); } CleanList(&g_brUndo);
4222 * g_bScreenUpdates = true; Sys_UpdateWindows(W_ALL); } else common->Printf("Nothing
4223 * to undo.../n");
4224 */
4225 }
4226
4227 /*
4228 =======================================================================================================================
4229 =======================================================================================================================
4230 */
UndoClear()4231 void CXYWnd::UndoClear() {
4232 /* CleanList(&g_brUndo); */
4233 }
4234
4235 /*
4236 =======================================================================================================================
4237 =======================================================================================================================
4238 */
UndoCopy()4239 void CXYWnd::UndoCopy() {
4240 /*
4241 * CleanList(&g_brUndo); for (brush_t* pBrush = selected_brushes.next ; pBrush !=
4242 * NULL && pBrush != &selected_brushes ; pBrush=pBrush->next) { brush_t* pClone =
4243 * Brush_Clone(pBrush); pClone->pUndoOwner = pBrush->owner; Brush_AddToList
4244 * (pClone, &g_brUndo); }
4245 */
4246 }
4247
4248 /*
4249 =======================================================================================================================
4250 =======================================================================================================================
4251 */
UndoAvailable()4252 bool CXYWnd::UndoAvailable() {
4253 return(g_brUndo.next != &g_brUndo);
4254 }
4255
4256 /*
4257 =======================================================================================================================
4258 =======================================================================================================================
4259 */
Paste()4260 void CXYWnd::Paste()
4261 {
4262 #if 1
4263
4264 CWaitCursor WaitCursor;
4265 bool bPasted = false;
4266 UINT nClipboard = ::RegisterClipboardFormat("RadiantClippings");
4267 if (nClipboard > 0 && OpenClipboard() && ::IsClipboardFormatAvailable(nClipboard)) {
4268 HANDLE h = ::GetClipboardData(nClipboard);
4269 if (h) {
4270 g_Clipboard.SetLength(0);
4271
4272 unsigned char *cp = reinterpret_cast < unsigned char * > (::GlobalLock(h));
4273 long lSize = 0;
4274 memcpy(&lSize, cp, sizeof (long));
4275 cp += sizeof (long);
4276 g_Clipboard.Write(cp, lSize);
4277 }
4278
4279 ::GlobalUnlock(h);
4280 ::CloseClipboard();
4281 }
4282
4283 if (g_Clipboard.GetLength() > 0) {
4284 g_Clipboard.SeekToBegin();
4285
4286 int nLen = g_Clipboard.GetLength();
4287 char *pBuffer = new char[nLen + 1];
4288 memset(pBuffer, 0, sizeof(*pBuffer) * (nLen + 1));
4289 g_Clipboard.Read(pBuffer, nLen);
4290 pBuffer[nLen] = '\0';
4291 Map_ImportBuffer(pBuffer, !(GetAsyncKeyState(VK_SHIFT) & 0x8000));
4292 delete[] pBuffer;
4293 }
4294
4295 #if 0
4296 if (g_PatchClipboard.GetLength() > 0) {
4297 g_PatchClipboard.SeekToBegin();
4298
4299 int nLen = g_PatchClipboard.GetLength();
4300 char *pBuffer = new char[nLen + 1];
4301 g_PatchClipboard.Read(pBuffer, nLen);
4302 pBuffer[nLen] = '\0';
4303 Patch_ReadBuffer(pBuffer, true);
4304 delete[] pBuffer;
4305 }
4306 #endif
4307 #else
4308 if (g_brClipboard.next != &g_brClipboard || g_enClipboard.next != &g_enClipboard) {
4309 Select_Deselect();
4310
4311 for (brush_t * pBrush = g_brClipboard.next; pBrush != NULL && pBrush != &g_brClipboard; pBrush = pBrush->next) {
4312 brush_t *pClone = Brush_Clone(pBrush);
4313
4314 // pClone->owner = pBrush->owner;
4315 if (pClone->owner == NULL) {
4316 Entity_LinkBrush(world_entity, pClone);
4317 }
4318
4319 Brush_AddToList(pClone, &selected_brushes);
4320 Brush_Build(pClone);
4321 }
4322
4323 for
4324 (
4325 entity_t * pEntity = g_enClipboard.next;
4326 pEntity != NULL && pEntity != &g_enClipboard;
4327 pEntity = pEntity->next
4328 ) {
4329 entity_t *pEClone = Entity_Clone(pEntity);
4330 for (brush_t * pEB = pEntity->brushes.onext; pEB != &pEntity->brushes; pEB = pEB->onext) {
4331 brush_t *pClone = Brush_Clone(pEB);
4332 Brush_AddToList(pClone, &selected_brushes);
4333 Entity_LinkBrush(pEClone, pClone);
4334 Brush_Build(pClone);
4335 if (pClone->owner && pClone->owner != world_entity) {
4336 g_Inspectors->UpdateEntitySel(pClone->owner->eclass);
4337 }
4338 }
4339 }
4340
4341 Sys_UpdateWindows(W_ALL);
4342 }
4343 else {
4344 common->Printf("Nothing to paste.../n");
4345 }
4346 #endif
4347 }
4348
4349 /*
4350 =======================================================================================================================
4351 =======================================================================================================================
4352 */
Rotation()4353 idVec3 &CXYWnd::Rotation() {
4354 return g_vRotation;
4355 }
4356
4357 /*
4358 =======================================================================================================================
4359 =======================================================================================================================
4360 */
RotateOrigin()4361 idVec3 &CXYWnd::RotateOrigin() {
4362 return g_vRotateOrigin;
4363 }
4364
4365 /*
4366 =======================================================================================================================
4367 =======================================================================================================================
4368 */
OnTimer(UINT nIDEvent)4369 void CXYWnd::OnTimer(UINT nIDEvent) {
4370 if (nIDEvent == 100) {
4371 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
4372 int nDim2 = (m_nViewType == XY) ? 1 : 2;
4373 m_vOrigin[nDim1] += m_ptDragAdj.x / m_fScale;
4374 m_vOrigin[nDim2] -= m_ptDragAdj.y / m_fScale;
4375 Sys_UpdateWindows(W_XY | W_CAMERA);
4376
4377 // int nH = (m_ptDrag.y == 0) ? -1 : m_ptDrag.y;
4378 m_ptDrag += m_ptDragAdj;
4379 m_ptDragTotal += m_ptDragAdj;
4380 XY_MouseMoved(m_ptDrag.x, m_nHeight - 1 - m_ptDrag.y, m_nScrollFlags);
4381
4382 //
4383 // m_vOrigin[nDim1] -= m_ptDrag.x / m_fScale; m_vOrigin[nDim1] -= m_ptDrag.x /
4384 // m_fScale;
4385 //
4386 }
4387 }
4388
4389 /*
4390 =======================================================================================================================
4391 =======================================================================================================================
4392 */
OnKeyUp(UINT nChar,UINT nRepCnt,UINT nFlags)4393 void CXYWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
4394 g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
4395
4396 // CWnd::OnKeyUp(nChar, nRepCnt, nFlags);
4397 }
4398
4399 /*
4400 =======================================================================================================================
4401 =======================================================================================================================
4402 */
OnNcCalcSize(BOOL bCalcValidRects,NCCALCSIZE_PARAMS FAR * lpncsp)4403 void CXYWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR *lpncsp) {
4404 CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
4405 }
4406
4407 /*
4408 =======================================================================================================================
4409 =======================================================================================================================
4410 */
OnKillFocus(CWnd * pNewWnd)4411 void CXYWnd::OnKillFocus(CWnd *pNewWnd) {
4412 CWnd::OnKillFocus(pNewWnd);
4413 SendMessage(WM_NCACTIVATE, FALSE, 0);
4414 }
4415
4416 /*
4417 =======================================================================================================================
4418 =======================================================================================================================
4419 */
OnSetFocus(CWnd * pOldWnd)4420 void CXYWnd::OnSetFocus(CWnd *pOldWnd) {
4421 CWnd::OnSetFocus(pOldWnd);
4422 SendMessage(WM_NCACTIVATE, TRUE, 0);
4423 }
4424
4425 /*
4426 =======================================================================================================================
4427 =======================================================================================================================
4428 */
OnClose()4429 void CXYWnd::OnClose() {
4430 CWnd::OnClose();
4431 }
4432
4433 //
4434 // =======================================================================================================================
4435 // should be static as should be the rotate scale stuff
4436 // =======================================================================================================================
4437 //
AreaSelectOK()4438 bool CXYWnd::AreaSelectOK() {
4439 return RotateMode() ? false : ScaleMode() ? false : true;
4440 }
4441
4442 /*
4443 =======================================================================================================================
4444 =======================================================================================================================
4445 */
OnEraseBkgnd(CDC * pDC)4446 BOOL CXYWnd::OnEraseBkgnd(CDC *pDC) {
4447 return TRUE;
4448
4449 // return CWnd::OnEraseBkgnd(pDC);
4450 }
4451
4452 extern void AssignModel();
OnDropNewmodel()4453 void CXYWnd::OnDropNewmodel()
4454 {
4455 CPoint point;
4456 GetCursorPos(&point);
4457 CreateRightClickEntity(this, m_ptDown.x, m_ptDown.y, "func_static");
4458 g_Inspectors->SetMode(W_ENTITY);
4459 g_Inspectors->AssignModel();
4460 }
4461
OnMouseWheel(UINT nFlags,short zDelta,CPoint pt)4462 BOOL CXYWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
4463 {
4464 if (zDelta > 0) {
4465 g_pParentWnd->OnViewZoomin();
4466 } else {
4467 g_pParentWnd->OnViewZoomout();
4468 }
4469 return TRUE;
4470 }
4471
4472
4473
4474
4475 //---------------------------------------------------------------------------
4476 // CyclePrecisionCrosshairMode
4477 //
4478 // Called when the user presses the "cycle precision cursor mode" key.
4479 // Cycles the precision cursor among the following three modes:
4480 // PRECISION_CURSOR_NONE
4481 // PRECISION_CURSOR_SNAP
4482 // PRECISION_CURSOR_FREE
4483 //---------------------------------------------------------------------------
CyclePrecisionCrosshairMode(void)4484 void CXYWnd::CyclePrecisionCrosshairMode( void )
4485 {
4486 common->Printf("TODO: Make DrawPrecisionCrosshair work..." );
4487
4488 /// Cycle to next mode, wrap if necessary
4489 m_precisionCrosshairMode ++;
4490 if( m_precisionCrosshairMode >= PRECISION_CROSSHAIR_MAX )
4491 m_precisionCrosshairMode = PRECISION_CROSSHAIR_NONE;
4492 Sys_UpdateWindows( W_XY );
4493 }
4494
4495 //---------------------------------------------------------------------------
4496 // DrawPrecisionCrosshair
4497 //
4498 // Draws a precision crosshair beneath the cursor in the 2d (XY) view,
4499 // depending on one of the following values for m_precisionCrosshairMode:
4500 //
4501 // PRECISION_CROSSHAIR_NONE No crosshair is drawn. Do not force refresh of XY view.
4502 // PRECISION_CROSSHAIR_SNAP Crosshair snaps to grid size. Force refresh of XY view.
4503 // PRECISION_CROSSHAIR_FREE Crosshair does not snap to grid. Force refresh of XY view.
4504 //---------------------------------------------------------------------------
DrawPrecisionCrosshair(void)4505 void CXYWnd::DrawPrecisionCrosshair( void )
4506 {
4507 // FIXME: m_mouseX, m_mouseY, m_axisHoriz, m_axisVert, etc... are never set
4508 return;
4509
4510 idVec3 mouse3dPos (0.0f, 0.0f, 0.0f);
4511 float x, y;
4512 idVec4 crossEndColor (1.0f, 0.0f, 1.0f, 1.0f); // the RGBA color of the precision crosshair at its ends
4513 idVec4 crossMidColor; // the RGBA color of the precision crosshair at the crossing point
4514
4515 /// Transform the mouse coordinates into axis-correct map-coordinates
4516 if( m_precisionCrosshairMode == PRECISION_CROSSHAIR_SNAP )
4517 SnapToPoint( m_mouseX, m_mouseY, mouse3dPos );
4518 else
4519 XY_ToPoint( m_mouseX, m_mouseY, mouse3dPos );
4520 x = mouse3dPos[ m_axisHoriz ];
4521 y = mouse3dPos[ m_axisVert ];
4522
4523 /// Use the color specified by the user
4524
4525 crossEndColor[0] = g_qeglobals.d_savedinfo.colors[ COLOR_PRECISION_CROSSHAIR ][0];
4526 crossEndColor[1] = g_qeglobals.d_savedinfo.colors[ COLOR_PRECISION_CROSSHAIR ][1];
4527 crossEndColor[2] = g_qeglobals.d_savedinfo.colors[ COLOR_PRECISION_CROSSHAIR ][2];
4528 crossEndColor[3] = 1.0f;
4529
4530 crossMidColor = crossEndColor;
4531
4532 if( m_precisionCrosshairMode == PRECISION_CROSSHAIR_FREE )
4533 crossMidColor[ 3 ] = 0.0f; // intersection-color is 100% transparent (alpha = 0.0f)
4534
4535 /// Set up OpenGL states (for drawing smooth-shaded plain-colored lines)
4536 qglEnable( GL_BLEND );
4537 qglDisable( GL_TEXTURE_2D );
4538 qglShadeModel( GL_SMOOTH );
4539 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
4540
4541 /// Draw a fullscreen-sized crosshair over the cursor
4542 qglBegin( GL_LINES );
4543 {
4544 /// Draw the horizontal precision line (in two pieces)
4545 qglColor4fv( crossEndColor.ToFloatPtr() );
4546 qglVertex2f( m_mcLeft, y );
4547 qglColor4fv( crossMidColor.ToFloatPtr() );
4548 qglVertex2f( x, y );
4549 qglColor4fv( crossMidColor.ToFloatPtr() );
4550 qglVertex2f( x, y );
4551 qglColor4fv( crossEndColor.ToFloatPtr() );
4552 qglVertex2f( m_mcRight, y );
4553
4554 /// Draw the vertical precision line (in two pieces)
4555 qglColor4fv( crossEndColor.ToFloatPtr() );
4556 qglVertex2f( x, m_mcTop );
4557 qglColor4fv( crossMidColor.ToFloatPtr() );
4558 qglVertex2f( x, y );
4559 qglColor4fv( crossMidColor.ToFloatPtr() );
4560 qglVertex2f( x, y );
4561 qglColor4fv( crossEndColor.ToFloatPtr() );
4562 qglVertex2f( x, m_mcBottom );
4563 }
4564 qglEnd(); // GL_LINES
4565
4566 // Radiant was in opaque, flat-shaded mode by default; restore this to prevent possible slowdown
4567 qglShadeModel( GL_FLAT );
4568 qglDisable( GL_BLEND );
4569 }
4570