2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
25 // Leonardo Zide (leo@lokigames.com)
\r
29 #include <gtk/gtk.h>
\r
34 #include <gdk/gdkwin32.h>
\r
37 // =============================================================================
\r
42 CString g_strStatus;
\r
43 bool g_bCrossHairs = false;
\r
48 bool g_bRogueClipMode;
\r
53 ClipPoint* g_pMovingClip;
\r
54 brush_t g_brFrontSplits;
\r
55 brush_t g_brBackSplits;
\r
57 brush_t g_brClipboard;
\r
59 entity_t g_enClipboard;
\r
61 vec3_t g_vRotateOrigin;
\r
65 ClipPoint g_PathPoints[256]; // this limit isn't enforced?
\r
66 ClipPoint* g_pMovingPath;
\r
73 ClipPoint g_PointPoints[512];
\r
74 ClipPoint* g_pMovingPoint;
\r
78 const int XY_LEFT = 0x01;
\r
79 const int XY_RIGHT = 0x02;
\r
80 const int XY_UP = 0x04;
\r
81 const int XY_DOWN = 0x08;
\r
83 PFNPathCallback* g_pPathFunc = NULL;
\r
85 static unsigned s_stipple[32] =
\r
87 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
88 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
89 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
90 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
91 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
92 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
93 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
94 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
\r
97 void AcquirePath(int nCount, PFNPathCallback* pFunc)
\r
100 g_nPathLimit = nCount;
\r
101 g_pPathFunc = pFunc;
\r
102 g_bPathMode = true;
\r
106 CPtrArray g_ptrMenus;
\r
108 MemStream g_Clipboard(4096);
\r
109 MemStream g_PatchClipboard(4096);
\r
113 extern bool g_bWaitCursor;
\r
117 GtkWidget* XYWnd::m_mnuDrop = NULL;
\r
119 extern int g_nPatchClickedView;
\r
121 // =============================================================================
\r
122 // global functions
\r
124 // this is disabled, and broken
\r
125 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394
\r
129 long width, height;
\r
130 width = g_pParentWnd->ActiveXY()->Width();
\r
131 height = g_pParentWnd->ActiveXY()->Height();
\r
132 unsigned char* img;
\r
133 const char* filename;
\r
135 filename = file_dialog (g_pParentWnd->m_pWidget, FALSE, "Save Image", NULL, FILTER_BMP);
\r
139 g_pParentWnd->ActiveXY()->MakeCurrent();
\r
140 img = (unsigned char*)malloc (width*height*3);
\r
141 qglReadPixels (0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,img);
\r
144 fp = fopen(filename, "wb");
\r
147 unsigned short bits;
\r
148 unsigned long cmap, bfSize;
\r
152 bfSize = 54 + width*height*3;
\r
154 long byteswritten = 0;
\r
155 long pixoff = 54 + cmap*4;
\r
157 char m1 ='B', m2 ='M';
\r
158 fwrite(&m1, 1, 1, fp); byteswritten++; // B
\r
159 fwrite(&m2, 1, 1, fp); byteswritten++; // M
\r
160 fwrite(&bfSize, 4, 1, fp); byteswritten+=4;// bfSize
\r
161 fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved1
\r
162 fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved2
\r
163 fwrite(&pixoff, 4, 1, fp); byteswritten+=4;// bfOffBits
\r
165 unsigned long biSize = 40, compress = 0, size = 0;
\r
167 unsigned short planes = 1;
\r
168 fwrite(&biSize, 4, 1, fp); byteswritten+=4;// biSize
\r
169 fwrite(&width, 4, 1, fp); byteswritten+=4;// biWidth
\r
170 fwrite(&height, 4, 1, fp); byteswritten+=4;// biHeight
\r
171 fwrite(&planes, 2, 1, fp); byteswritten+=2;// biPlanes
\r
172 fwrite(&bits, 2, 1, fp); byteswritten+=2;// biBitCount
\r
173 fwrite(&compress, 4, 1, fp);byteswritten+=4;// biCompression
\r
174 fwrite(&size, 4, 1, fp); byteswritten+=4;// biSizeImage
\r
175 fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biXPelsPerMeter
\r
176 fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biYPelsPerMeter
\r
177 fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrUsed
\r
178 fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrImportant
\r
180 unsigned long widthDW = (((width*24) + 31) / 32 * 4);
\r
181 long row, row_size = width*3;
\r
182 for (row = 0; row < height; row++)
\r
184 unsigned char* buf = img+row*row_size;
\r
188 for (col = 0; col < row_size; col += 3)
\r
190 putc(buf[col+2], fp);
\r
191 putc(buf[col+1], fp);
\r
192 putc(buf[col], fp);
\r
194 byteswritten += row_size;
\r
196 unsigned long count;
\r
197 for (count = row_size; count < widthDW; count++)
\r
199 putc(0, fp); // dummy
\r
211 float ptSum(vec3_t pt)
\r
213 return pt[0] + pt[1] + pt[2];
\r
216 float Betwixt(float f1, float f2)
\r
219 return f2 + ((f1 - f2) / 2);
\r
221 return f1 + ((f2 - f1) / 2);
\r
224 void CleanList(brush_t* pList)
\r
226 brush_t* pBrush = pList->next;
\r
227 while (pBrush != NULL && pBrush != pList)
\r
229 brush_t* pNext = pBrush->next;
\r
230 Brush_Free(pBrush);
\r
235 void Brush_CopyList (brush_t* pFrom, brush_t* pTo)
\r
237 brush_t* pBrush = pFrom->next;
\r
238 while (pBrush != NULL && pBrush != pFrom)
\r
240 brush_t* pNext = pBrush->next;
\r
241 Brush_RemoveFromList(pBrush);
\r
242 Brush_AddToList(pBrush, pTo);
\r
247 float fDiff(float f1, float f2)
\r
256 =============================================================
\r
260 =============================================================
\r
267 Draws connections between entities.
\r
268 Needs to consider all entities, not just ones on screen,
\r
269 because the lines can be visible when neither end is.
\r
270 Called for both camera view and xy view.
\r
273 void DrawPathLines (void)
\r
280 vec3_t dir, s1, s2;
\r
284 const char *ent_target[MAX_MAP_ENTITIES];
\r
285 entity_t *ent_entity[MAX_MAP_ENTITIES];
\r
287 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
\r
293 for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
\r
295 ent_target[num_entities] = ValueForKey (te, "target");
\r
296 if (ent_target[num_entities][0])
\r
298 ent_entity[num_entities] = te;
\r
303 for (se = entities.next ; se != &entities ; se = se->next)
\r
305 psz = ValueForKey(se, "targetname");
\r
307 if (psz == NULL || psz[0] == '\0')
\r
310 sb = se->brushes.onext;
\r
311 if (sb == &se->brushes)
\r
314 for (k=0 ; k<num_entities ; k++)
\r
316 if (strcmp (ent_target[k], psz))
\r
319 te = ent_entity[k];
\r
320 tb = te->brushes.onext;
\r
321 if (tb == &te->brushes)
\r
324 for (i=0 ; i<3 ; i++)
\r
325 mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
\r
327 for (i=0 ; i<3 ; i++)
\r
328 mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
\r
330 VectorSubtract (mid1, mid, dir);
\r
331 len = VectorNormalize (dir, dir);
\r
332 s1[0] = -dir[1]*8 + dir[0]*8;
\r
333 s2[0] = dir[1]*8 + dir[0]*8;
\r
334 s1[1] = dir[0]*8 + dir[1]*8;
\r
335 s2[1] = -dir[0]*8 + dir[1]*8;
\r
337 qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
\r
339 qglBegin(GL_LINES);
\r
341 qglVertex3fv(mid1);
\r
343 arrows = (int)(len / 256) + 1;
\r
345 for (i=0 ; i<arrows ; i++)
\r
347 f = len * (i + 0.5) / arrows;
\r
349 for (j=0 ; j<3 ; j++)
\r
350 mid1[j] = mid[j] + f*dir[j];
\r
351 qglVertex3fv (mid1);
\r
352 qglVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
\r
353 qglVertex3fv (mid1);
\r
354 qglVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
\r
362 extern void AssignModel();
\r
364 void CreateEntityFromName(const char* name, const vec3_t origin)
\r
368 if (stricmp(name, "worldspawn") == 0)
\r
370 gtk_MessageBox(g_pParentWnd->m_pWidget, "Can't create an entity with worldspawn.", "info", 0);
\r
374 e = Entity_Alloc();
\r
375 SetKeyValue(e, "classname", name);
\r
377 if(e->eclass->fixedsize)
\r
380 b = Brush_Create(e->eclass->mins, e->eclass->maxs, &e->eclass->texdef);
\r
381 Entity_LinkBrush(e, b);
\r
382 Brush_AddToList(b, &active_brushes);
\r
384 Brush_Move(b, origin, true);
\r
388 Select_GroupEntity(e);
\r
389 if(e->brushes.onext == &e->brushes)
\r
391 Sys_FPrintf(SYS_ERR, "CreateEntityFromName: selection could not be grouped\n");
\r
397 Entity_AddToList(e, &entities);
\r
400 Select_Deselect ();
\r
402 // tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box
\r
403 // see SF bug 105383
\r
405 if (g_pGameDescription->mGameFile == "hl.game")
\r
407 // FIXME - Hydra: really we need a combined light AND color dialog for halflife.
\r
408 if ((stricmp(name, "light") == 0) ||
\r
409 (stricmp(name, "light_environment") == 0) ||
\r
410 (stricmp(name, "light_spot") == 0) )
\r
412 int intensity = g_PrefsDlg.m_iLastLightIntensity;
\r
414 // Create and show the dialog box
\r
416 // pWnd = prompt.GetDlgItem( IDC_EDIT1 );
\r
417 // prompt.GotoDlgCtrl( pWnd );
\r
418 if (DoLightIntensityDlg (&intensity) == IDOK)
\r
420 g_PrefsDlg.m_iLastLightIntensity = intensity;
\r
422 sprintf( buf, "255 255 255 %d", intensity );
\r
423 SetKeyValue(e, "_light", buf);
\r
429 if (stricmp(name, "light") == 0)
\r
431 int intensity = g_PrefsDlg.m_iLastLightIntensity;
\r
433 // Create and show the dialog box
\r
435 // pWnd = prompt.GetDlgItem( IDC_EDIT1 );
\r
436 // prompt.GotoDlgCtrl( pWnd );
\r
437 if (DoLightIntensityDlg (&intensity) == IDOK)
\r
439 g_PrefsDlg.m_iLastLightIntensity = intensity;
\r
441 sprintf( buf, "%d", intensity );
\r
442 SetKeyValue(e, "light", buf);
\r
446 Select_Brush (e->brushes.onext);
\r
448 if ( (stricmp(name, "misc_model") == 0) || (stricmp(name, "misc_gamemodel") == 0) || (strcmpi(name, "model_static") == 0) )
\r
450 SetInspectorMode(W_ENTITY);
\r
455 void CreateRightClickEntity(XYWnd* pWnd, int x, int y, char* pName)
\r
457 int height = pWnd->GetWidget()->allocation.height;
\r
459 pWnd->SnapToPoint (x, height - 1 - y, point);
\r
461 int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
\r
462 float fWorkMid = (g_qeglobals.d_work_min[nDim] + g_qeglobals.d_work_max[nDim]) * 0.5;
\r
463 point[nDim] = g_qeglobals.d_gridsize * ((int)(fWorkMid/g_qeglobals.d_gridsize));
\r
465 CreateEntityFromName(pName, point);
\r
469 brush_t* CreateSmartBrush(vec3_t v)
\r
475 for (i=0 ; i<3 ; i++)
\r
477 mins[i] = v[i] - 16;
\r
478 maxs[i] = v[i] + 16;
\r
481 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
\r
485 Brush_AddToList(n, &selected_brushes);
\r
486 //Entity_LinkBrush(world_entity, n);
\r
491 CString g_strSmartEntity;
\r
494 bool g_bSmartWaiting;
\r
495 void _SmartPointDone(bool b, int n)
\r
497 g_bSmartWaiting = false;
\r
500 void CreateSmartEntity(XYWnd* pWnd, int x, int y, const char* pName)
\r
504 g_strSmartEntity = pName;
\r
505 if (g_strSmartEntity.Find("Smart_Train") >= 0)
\r
507 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");
\r
508 g_bPathMode = true;
\r
514 if (g_strSmartEntity.Find("Smart_Monster...") >= 0)
\r
516 g_bPathMode = true;
\r
521 if (g_strSmartEntity.Find("Smart_Rotating") >= 0)
\r
523 g_bSmartWaiting = true;
\r
524 ShowInfoDialog("Left click to specify the rotation origin");
\r
525 AcquirePath(1, &_SmartPointDone);
\r
526 while (g_bSmartWaiting)
\r
527 gtk_main_iteration ();
\r
530 g_bScreenUpdates = false;
\r
531 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
\r
532 array.Add(reinterpret_cast<void*>(selected_brushes.next));
\r
534 brush_t* pBrush = CreateSmartBrush(g_PathPoints[0]);
\r
537 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(0)));
\r
538 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(1)));
\r
540 g_bScreenUpdates = true;
\r
544 void FinishSmartCreation()
\r
548 // brush_t* pEntities = NULL;
\r
551 if (g_strSmartEntity.Find("Smart_Train") >= 0)
\r
553 g_bScreenUpdates = false;
\r
554 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
\r
555 array.Add(reinterpret_cast<void*>(selected_brushes.next));
\r
556 for (n = 0; n < g_nPathCount; n++)
\r
559 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_PathPoints[n].m_ptScreenX,
\r
560 g_PathPoints[n].m_ptScreenY, "path_corner");
\r
561 array.Add(reinterpret_cast<void*>(selected_brushes.next));
\r
564 for (n = 0; n < g_nPathCount; n++)
\r
567 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n)));
\r
568 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n+1)));
\r
571 g_bScreenUpdates = true;
\r
575 g_bPathMode = false;
\r
576 Sys_UpdateWindows(W_ALL);
\r
579 void CleanCopyEntities()
\r
581 entity_t* pe = g_enClipboard.next;
\r
582 while (pe != NULL && pe != &g_enClipboard)
\r
584 entity_t* next = pe->next;
\r
585 epair_t* enext = NULL;
\r
586 for (epair_t* ep = pe->epairs ; ep ; ep=enext)
\r
596 g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
\r
599 entity_t *Entity_CopyClone (entity_t *e)
\r
604 n = (entity_t*)qmalloc(sizeof(*n));
\r
605 n->brushes.onext = n->brushes.oprev = &n->brushes;
\r
606 n->eclass = e->eclass;
\r
608 // add the entity to the entity list
\r
609 n->next = g_enClipboard.next;
\r
610 g_enClipboard.next = n;
\r
612 n->prev = &g_enClipboard;
\r
614 for (ep = e->epairs ; ep ; ep=ep->next)
\r
616 np = (epair_t*)qmalloc(sizeof(*np));
\r
617 np->key = copystring(ep->key);
\r
618 np->value = copystring(ep->value);
\r
619 np->next = n->epairs;
\r
625 bool OnList(entity_t* pFind, CPtrArray* pList)
\r
627 int nSize = pList->GetSize();
\r
628 while (nSize-- > 0)
\r
630 entity_t* pEntity = reinterpret_cast<entity_t*>(pList->GetAt(nSize));
\r
631 if (pEntity == pFind)
\r
637 // =============================================================================
\r
641 : GLWindow (FALSE), m_XORRectangle(m_pWidget)
\r
643 g_brClipboard.next = &g_brClipboard;
\r
644 g_brUndo.next = &g_brUndo;
\r
646 g_bRotateMode = false;
\r
647 g_bClipMode = false;
\r
648 g_bRogueClipMode = false;
\r
650 g_pMovingClip = (ClipPoint*)NULL;
\r
651 g_pMovingPath = (ClipPoint*)NULL;
\r
652 g_brFrontSplits.next = &g_brFrontSplits;
\r
653 g_brBackSplits.next = &g_brBackSplits;
\r
655 //m_bTiming = true;
\r
657 m_bRButtonDown = false;
\r
658 m_nUpdateBits = W_XY;
\r
659 g_bPathMode = false;
\r
662 m_nButtonstate = 0;
\r
663 // m_mnuDrop = (GtkWidget*)NULL;
\r
667 vec3_t& XYWnd::Rotation()
\r
669 return g_vRotation;
\r
672 vec3_t& XYWnd::RotateOrigin()
\r
674 return g_vRotateOrigin;
\r
682 void XYWnd::XY_Overlay()
\r
686 static vec3_t lastz;
\r
687 static vec3_t lastcamera;
\r
689 qglViewport(0, 0, m_nWidth, m_nHeight);
\r
692 // set up viewpoint
\r
694 qglMatrixMode(GL_PROJECTION);
\r
695 qglLoadIdentity ();
\r
697 w = (int)(m_nWidth / 2 / m_fScale);
\r
698 h = (int)(m_nHeight / 2 / m_fScale);
\r
700 qglOrtho (m_vOrigin[0] - w, m_vOrigin[0] + w , m_vOrigin[1] - h, m_vOrigin[1] + h, g_MinWorldCoord, g_MaxWorldCoord);
\r
702 // erase the old camera and z checker positions
\r
703 // if the entire xy hasn't been redrawn
\r
707 qglReadBuffer (GL_BACK);
\r
708 qglDrawBuffer (GL_FRONT);
\r
710 qglRasterPos2f (lastz[0]-9, lastz[1]-9);
\r
711 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
\r
712 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
\r
714 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
\r
715 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
\r
716 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
\r
721 // save off underneath where we are about to draw
\r
723 VectorCopy (z.origin, lastz);
\r
724 VectorCopy (g_pParentWnd->GetCamWnd()->Camera()->origin, lastcamera);
\r
726 qglReadBuffer (GL_FRONT);
\r
727 qglDrawBuffer (GL_BACK);
\r
729 qglRasterPos2f (lastz[0]-9, lastz[1]-9);
\r
730 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
\r
731 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
\r
733 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
\r
734 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
\r
735 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
\r
738 // draw the new icons
\r
740 qglDrawBuffer (GL_FRONT);
\r
742 qglShadeModel (GL_FLAT);
\r
743 qglDisable(GL_TEXTURE_2D);
\r
744 qglDisable(GL_TEXTURE_1D);
\r
745 qglDisable(GL_DEPTH_TEST);
\r
746 qglDisable(GL_BLEND);
\r
747 qglColor3f(0, 0, 0);
\r
752 qglDrawBuffer (GL_BACK);
\r
756 vec3_t& XYWnd::GetOrigin()
\r
761 void XYWnd::SetOrigin(vec3_t org)
\r
763 m_vOrigin[0] = org[0];
\r
764 m_vOrigin[1] = org[1];
\r
765 m_vOrigin[2] = org[2];
\r
768 void XYWnd::OnSize(int cx, int cy)
\r
774 brush_t hold_brushes;
\r
780 hold_brushes.next = &hold_brushes;
\r
781 ProduceSplitLists();
\r
783 if (g_PrefsDlg.m_bSwitchClip)
\r
784 pList = (!g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
\r
786 pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
\r
788 if (pList->next != pList)
\r
790 Brush_CopyList(pList, &hold_brushes);
\r
791 CleanList(&g_brFrontSplits);
\r
792 CleanList(&g_brBackSplits);
\r
794 Brush_CopyList(&hold_brushes, &selected_brushes);
\r
795 if (RogueClipMode())
\r
796 RetainClipMode(false);
\r
798 RetainClipMode(true);
\r
799 Sys_UpdateWindows(W_ALL);
\r
802 else if (PathMode())
\r
804 FinishSmartCreation();
\r
806 g_pPathFunc(true, g_nPathCount);
\r
807 g_pPathFunc = NULL;
\r
809 g_bPathMode = false;
\r
813 void XYWnd::SplitClip()
\r
815 ProduceSplitLists();
\r
816 if ((g_brFrontSplits.next != &g_brFrontSplits) &&
\r
817 (g_brBackSplits.next != &g_brBackSplits))
\r
820 Brush_CopyList(&g_brFrontSplits, &selected_brushes);
\r
821 Brush_CopyList(&g_brBackSplits, &selected_brushes);
\r
822 CleanList(&g_brFrontSplits);
\r
823 CleanList(&g_brBackSplits);
\r
824 if (RogueClipMode())
\r
825 RetainClipMode(false);
\r
827 RetainClipMode(true);
\r
831 void XYWnd::FlipClip()
\r
833 g_bSwitch = !g_bSwitch;
\r
834 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
837 // makes sure the selected brush or camera is in view
\r
838 void XYWnd::PositionView()
\r
840 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
841 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
842 brush_t* b = selected_brushes.next;
\r
843 if (b && b->next != b)
\r
845 Select_GetMid (m_vOrigin);
\r
849 m_vOrigin[nDim1] = g_pParentWnd->GetCamWnd()->Camera()->origin[nDim1];
\r
850 m_vOrigin[nDim2] = g_pParentWnd->GetCamWnd()->Camera()->origin[nDim2];
\r
854 void XYWnd::VectorCopyXY(vec3_t in, vec3_t out)
\r
856 if (m_nViewType == XY)
\r
861 else if (m_nViewType == XZ)
\r
873 void XYWnd::RetainClipMode(bool bMode)
\r
875 bool bSave = g_bRogueClipMode;
\r
876 SetClipMode(bMode);
\r
878 g_bRogueClipMode = bSave;
\r
880 g_bRogueClipMode = false;
\r
883 void XYWnd::SetClipMode(bool bMode)
\r
885 g_bClipMode = bMode;
\r
886 g_bRogueClipMode = false;
\r
892 CleanList(&g_brFrontSplits);
\r
893 CleanList(&g_brBackSplits);
\r
894 g_brFrontSplits.next = &g_brFrontSplits;
\r
895 g_brBackSplits.next = &g_brBackSplits;
\r
897 // ydnar: set clipper points based on first selected patch mesh
\r
898 if( selected_brushes.next != &selected_brushes )
\r
900 bool found = false;
\r
901 for( brush_t *pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next )
\r
903 if( pb->patchBrush )
\r
906 VectorCopy( pb->pPatch->ctrl[ 0 ][ 0 ].xyz, g_Clip1.m_ptClip );
\r
907 VectorCopy( pb->pPatch->ctrl[ pb->pPatch->width - 1 ][ pb->pPatch->height - 1 ].xyz, g_Clip2.m_ptClip );
\r
908 VectorCopy( pb->pPatch->ctrl[ pb->pPatch->width - 1 ][ 0 ].xyz, g_Clip3.m_ptClip );
\r
909 g_Clip1.Set( true );
\r
910 g_Clip2.Set( true );
\r
911 g_Clip3.Set( true );
\r
918 // SetClipMode( true );
\r
919 Sys_UpdateWindows( XY | W_CAMERA_IFON );
\r
928 g_pMovingClip = NULL;
\r
930 CleanList(&g_brFrontSplits);
\r
931 CleanList(&g_brBackSplits);
\r
932 g_brFrontSplits.next = &g_brFrontSplits;
\r
933 g_brBackSplits.next = &g_brBackSplits;
\r
934 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
938 bool XYWnd::ClipMode()
\r
940 return g_bClipMode;
\r
943 bool XYWnd::RogueClipMode()
\r
945 return g_bRogueClipMode;
\r
948 bool XYWnd::PathMode()
\r
950 return g_bPathMode;
\r
953 bool XYWnd::PointMode()
\r
955 return g_bPointMode;
\r
958 void XYWnd::SetPointMode(bool b)
\r
965 void XYWnd::SetViewType(int n)
\r
968 if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
\r
970 char* str = "YZ Side";
\r
971 if (m_nViewType == XY)
\r
973 else if (m_nViewType == XZ)
\r
976 if (m_pParent != NULL)
\r
977 gtk_window_set_title (GTK_WINDOW (m_pParent), str);
\r
981 void XYWnd::Redraw(unsigned int nBits)
\r
983 m_nUpdateBits = nBits;
\r
984 gtk_widget_queue_draw(m_pWidget);
\r
985 m_nUpdateBits = W_XY;
\r
988 bool XYWnd::RotateMode()
\r
990 return g_bRotateMode;
\r
993 bool XYWnd::ScaleMode()
\r
995 return g_bScaleMode;
\r
998 bool XYWnd::SetRotateMode(bool bMode)
\r
1000 if (bMode && selected_brushes.next != &selected_brushes)
\r
1002 g_bRotateMode = true;
\r
1003 Select_GetTrueMid(g_vRotateOrigin);
\r
1004 g_vRotation[0] = g_vRotation[1] = g_vRotation[2] = 0.0;
\r
1009 Sys_Printf("Need a brush selected to turn on Mouse Rotation mode\n");
\r
1010 g_bRotateMode = false;
\r
1013 return g_bRotateMode;
\r
1016 void XYWnd::SetScaleMode(bool bMode)
\r
1018 g_bScaleMode = bMode;
\r
1022 rectangle_t rectangle_from_area_xy()
\r
1024 XYWnd* xy = g_pParentWnd->ActiveXY();
\r
1025 int nDim1 = (xy->GetViewType() == YZ) ? 1 : 0;
\r
1026 int nDim2 = (xy->GetViewType() == XY) ? 1 : 2;
\r
1027 float origin_left = xy->GetOrigin()[nDim1] - (xy->Width() / 2) / xy->Scale();
\r
1028 float origin_bottom = xy->GetOrigin()[nDim2] - (xy->Height() / 2) / xy->Scale();
\r
1029 float left = MIN(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1]) - origin_left;
\r
1030 float top = MAX(g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2]) - origin_bottom;
\r
1031 float right = MAX(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1]) - origin_left;
\r
1032 float bottom = MIN(g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2]) - origin_bottom;
\r
1033 left *= xy->Scale();
\r
1034 top *= xy->Scale();
\r
1035 right *= xy->Scale();
\r
1036 bottom *= xy->Scale();
\r
1037 return rectangle_t(left, bottom, right - left, top - bottom);
\r
1040 void update_xor_rectangle_xy(XORRectangle& xor_rectangle)
\r
1042 rectangle_t rectangle;
\r
1043 if ((g_qeglobals.d_select_mode == sel_area))
\r
1044 rectangle = rectangle_from_area_xy();
\r
1045 xor_rectangle.set(rectangle);
\r
1048 void XYWnd::OnMouseMove(guint32 nFlags, int pointx, int pointy)
\r
1050 // plugin entities
\r
1051 // TODO TTimo handle return code
\r
1052 DispatchOnMouseMove (nFlags, pointx, pointy);
\r
1057 if (g_PrefsDlg.m_bChaseMouse == TRUE &&
\r
1058 (pointx < 0 || pointy < 0 || pointx > m_nWidth || pointy > m_nHeight) &&
\r
1061 float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
\r
1062 //m_ptDrag = point;
\r
1068 m_ptDragAdjX = (int)(-fAdjustment);
\r
1070 else if (pointx > m_nWidth)
\r
1072 m_ptDragAdjX = (int)(fAdjustment);
\r
1077 m_ptDragAdjY = (int)(-fAdjustment);
\r
1079 else if (pointy > m_nHeight)
\r
1081 m_ptDragAdjY = (int)(fAdjustment);
\r
1087 m_ptDragX = pointx;
\r
1088 m_ptDragY = pointy;
\r
1089 m_ptDragTotalX = 0;
\r
1090 m_ptDragTotalY = 0;
\r
1098 pressx -= m_ptDragTotalX;
\r
1099 pressy += m_ptDragTotalY;
\r
1102 bool bCrossHair = false;
\r
1103 if (!m_bRButtonDown)
\r
1105 tdp[0] = tdp[1] = tdp[2] = 0.0;
\r
1106 SnapToPoint (pointx, m_nHeight - 1 - pointy , tdp);
\r
1108 g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]);
\r
1109 g_pParentWnd->SetStatusText(1, g_strStatus);
\r
1111 // i need to generalize the point code.. having 3 flavors pretty much sucks..
\r
1112 // once the new curve stuff looks like it is going to stick i will
\r
1113 // rationalize this down to a single interface..
\r
1116 if (g_pMovingPoint && HasCapture ())
\r
1118 bCrossHair = true;
\r
1119 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingPoint->m_ptClip);
\r
1120 g_pMovingPoint->UpdatePointPtr();
\r
1121 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
1125 g_pMovingPoint = NULL;
\r
1126 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
1127 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
1128 for (int n = 0; n < g_nPointCount; n++)
\r
1130 if ( fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
\r
1131 fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
\r
1133 bCrossHair = true;
\r
1134 g_pMovingPoint = &g_PointPoints[n];
\r
1139 else if (ClipMode())
\r
1141 if (g_pMovingClip && HasCapture ())
\r
1143 bCrossHair = true;
\r
1144 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingClip->m_ptClip);
\r
1145 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
1149 g_pMovingClip = NULL;
\r
1150 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
1151 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
1152 if (g_Clip1.Set())
\r
1154 if ( fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
\r
1155 fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3 )
\r
1157 bCrossHair = true;
\r
1158 g_pMovingClip = &g_Clip1;
\r
1161 if (g_Clip2.Set())
\r
1163 if ( fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
\r
1164 fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3 )
\r
1166 bCrossHair = true;
\r
1167 g_pMovingClip = &g_Clip2;
\r
1170 if (g_Clip3.Set())
\r
1172 if ( fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
\r
1173 fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3 )
\r
1175 bCrossHair = true;
\r
1176 g_pMovingClip = &g_Clip3;
\r
1180 if (bCrossHair == false)
\r
1181 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
\r
1183 else if (PathMode())
\r
1185 if (g_pMovingPath && HasCapture ())
\r
1187 bCrossHair = true;
\r
1188 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingPath->m_ptClip);
\r
1189 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
1193 g_pMovingPath = NULL;
\r
1194 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
1195 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
1196 for (int n = 0; n < g_nPathCount; n++)
\r
1198 if ( fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
\r
1199 fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
\r
1201 bCrossHair = true;
\r
1202 g_pMovingPath = &g_PathPoints[n];
\r
1209 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
\r
1214 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
\r
1217 if ((nFlags & MK_RBUTTON) == 0)
\r
1219 if (bCrossHair && !g_bWaitCursor)
\r
1221 GdkCursor *cursor;
\r
1222 cursor = gdk_cursor_new (GDK_CROSSHAIR);
\r
1223 gdk_window_set_cursor (m_pWidget->window, cursor);
\r
1224 gdk_cursor_unref (cursor);
\r
1228 gdk_window_set_cursor (m_pWidget->window, NULL);
\r
1232 update_xor_rectangle_xy(m_XORRectangle);
\r
1235 void XYWnd::OnMouseWheel(bool bUp)
\r
1238 g_pParentWnd->OnViewZoomin ();
\r
1240 g_pParentWnd->OnViewZoomout ();
\r
1242 int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
\r
1243 Sys_UpdateWindows (nUpdate);
\r
1244 g_pParentWnd->OnTimer ();
\r
1247 void XYWnd::OnTimer ()
\r
1249 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
1250 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
1251 m_vOrigin[nDim1] += m_ptDragAdjX / m_fScale;
\r
1252 m_vOrigin[nDim2] -= m_ptDragAdjY / m_fScale;
\r
1253 Sys_UpdateWindows(W_XY | W_CAMERA);
\r
1254 m_ptDragX += m_ptDragAdjX;
\r
1255 m_ptDragY += m_ptDragAdjY;
\r
1256 m_ptDragTotalX += m_ptDragAdjX;
\r
1257 m_ptDragTotalY += m_ptDragAdjY;
\r
1258 XY_MouseMoved (m_ptDragX, m_nHeight - 1 - m_ptDragY , m_nScrollFlags);
\r
1261 void XYWnd::OnLButtonDown(guint32 flags, int pointx, int pointy)
\r
1263 g_pParentWnd->SetActiveXY(this);
\r
1266 // plugin entities
\r
1267 if (DispatchOnLButtonDown(flags, pointx, pointy))
\r
1270 if (ClipMode() && !RogueClipMode())
\r
1272 DropClipPoint(flags, pointx, pointy);
\r
1274 else if (PathMode())
\r
1276 DropPathPoint(flags, pointx, pointy);
\r
1278 else OriginalButtonDown(flags, pointx, pointy);
\r
1281 void XYWnd::OnMButtonDown(guint32 flags, int pointx, int pointy)
\r
1283 OriginalButtonDown(flags, pointx, pointy);
\r
1286 void XYWnd::OnRButtonDown(guint32 flags, int pointx, int pointy)
\r
1288 g_pParentWnd->SetActiveXY(this);
\r
1289 m_ptDownX = pointx;
\r
1290 m_ptDownY = pointy;
\r
1291 m_bRButtonDown = true;
\r
1293 if (g_PrefsDlg.m_nMouseButtons == 3) // 3 button mouse
\r
1295 if (flags & MK_CONTROL)
\r
1297 if (ClipMode()) // already there?
\r
1298 DropClipPoint(flags, pointx, pointy);
\r
1301 SetClipMode(true);
\r
1302 g_bRogueClipMode = true;
\r
1303 DropClipPoint(flags, pointx, pointy);
\r
1308 OriginalButtonDown(flags, pointx, pointy);
\r
1311 void XYWnd::OnLButtonUp(guint32 flags, int pointx, int pointy)
\r
1313 // plugin entities
\r
1314 if (DispatchOnLButtonUp(flags, pointx, pointy))
\r
1319 if (g_pMovingClip)
\r
1322 g_pMovingClip = NULL;
\r
1325 OriginalButtonUp(flags, pointx, pointy);
\r
1328 void XYWnd::OnMButtonUp(guint32 flags, int pointx, int pointy)
\r
1330 OriginalButtonUp(flags, pointx, pointy);
\r
1333 void XYWnd::OnRButtonUp(guint32 flags, int pointx, int pointy)
\r
1335 m_bRButtonDown = false;
\r
1336 if ((pointx == m_ptDownX) && (pointy == m_ptDownY)) // mouse didn't move
\r
1339 if (Sys_AltDown ())
\r
1341 if (flags & MK_CONTROL)
\r
1343 if (flags & MK_SHIFT)
\r
1348 OriginalButtonUp(flags, pointx, pointy);
\r
1351 void XYWnd::XY_MouseDown (int x, int y, int buttons)
\r
1354 vec3_t origin, dir, right, up;
\r
1356 m_nButtonstate = buttons;
\r
1359 VectorCopy (vec3_origin, m_vPressdelta);
\r
1361 VectorClear(point);
\r
1362 XY_ToPoint (x, y, point);
\r
1364 VectorCopy (point, origin);
\r
1366 VectorClear (dir);
\r
1367 if (m_nViewType == XY) // view facing dir = negative Z
\r
1369 origin[2] = g_MaxWorldCoord;
\r
1371 right[0] = 1 / m_fScale;
\r
1375 up[1] = 1 / m_fScale;
\r
1378 else if (m_nViewType == XZ)
\r
1380 origin[1] = g_MinWorldCoord; // view facing dir = positive Y
\r
1382 right[0] = 1 / m_fScale;
\r
1387 up[2] = 1 / m_fScale;
\r
1389 else // if (m_nViewType == YZ) // view facing dir = negative X
\r
1391 origin[0] = g_MaxWorldCoord;
\r
1394 right[1] = 1 / m_fScale;
\r
1398 up[2] = 1 / m_fScale;
\r
1401 m_bPress_selection = (selected_brushes.next != &selected_brushes);
\r
1403 Sys_GetCursorPos(&m_ptCursorX, &m_ptCursorY);
\r
1405 // lbutton = manipulate selection
\r
1406 // shift-LBUTTON = select
\r
1407 if ( (buttons == MK_LBUTTON)
\r
1408 || (buttons == (MK_LBUTTON | MK_SHIFT))
\r
1409 || (buttons == (MK_LBUTTON | MK_CONTROL))
\r
1410 || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
\r
1412 Patch_SetView( (m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
\r
1413 Drag_Begin (x, y, buttons, right, up, origin, dir);
\r
1417 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
\r
1419 // control mbutton = move camera
\r
1420 if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
\r
1422 VectorCopyXY(point, g_pParentWnd->GetCamWnd()->Camera()->origin);
\r
1423 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
\r
1426 // mbutton = angle camera
\r
1427 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
\r
1428 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
\r
1430 VectorSubtract (point, g_pParentWnd->GetCamWnd()->Camera()->origin, point);
\r
1432 int n1 = (m_nViewType == XY) ? 1 : 2;
\r
1433 int n2 = (m_nViewType == YZ) ? 1 : 0;
\r
1434 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
\r
1435 if (point[n1] || point[n2])
\r
1437 g_pParentWnd->GetCamWnd()->Camera()->angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
\r
1438 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
\r
1442 // shift mbutton = move z checker
\r
1443 if (m_nButtonstate == (MK_SHIFT | nMouseButton))
\r
1445 if (RotateMode() || g_bPatchBendMode)
\r
1447 SnapToPoint (x, y, point);
\r
1448 VectorCopyXY(point, g_vRotateOrigin);
\r
1449 if (g_bPatchBendMode)
\r
1451 VectorCopy(point, g_vBendOrigin);
\r
1453 Sys_UpdateWindows (W_XY);
\r
1458 SnapToPoint (x, y, point);
\r
1459 if (m_nViewType == XY)
\r
1461 z.origin[0] = point[0];
\r
1462 z.origin[1] = point[1];
\r
1464 else if (m_nViewType == YZ)
\r
1466 z.origin[0] = point[1];
\r
1467 z.origin[1] = point[2];
\r
1471 z.origin[0] = point[0];
\r
1472 z.origin[1] = point[2];
\r
1474 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
\r
1479 update_xor_rectangle_xy(m_XORRectangle);
\r
1482 void XYWnd::XY_MouseUp(int x, int y, int buttons)
\r
1484 Drag_MouseUp (buttons);
\r
1485 if (!m_bPress_selection)
\r
1486 Sys_UpdateWindows (W_ALL);
\r
1487 m_nButtonstate = 0;
\r
1489 gdk_window_set_cursor (m_pWidget->window, NULL);
\r
1491 update_xor_rectangle_xy(m_XORRectangle);
\r
1494 qboolean XYWnd::DragDelta (int x, int y, vec3_t move)
\r
1496 vec3_t xvec, yvec, delta;
\r
1499 xvec[0] = 1 / m_fScale;
\r
1500 xvec[1] = xvec[2] = 0;
\r
1501 yvec[1] = 1 / m_fScale;
\r
1502 yvec[0] = yvec[2] = 0;
\r
1504 for (i=0 ; i<3 ; i++)
\r
1506 delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
\r
1507 if (!g_PrefsDlg.m_bNoClamp)
\r
1509 delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
1512 VectorSubtract (delta, m_vPressdelta, move);
\r
1513 VectorCopy (delta, m_vPressdelta);
\r
1515 if (move[0] || move[1] || move[2])
\r
1520 void XYWnd::HandleDrop()
\r
1522 if (g_PrefsDlg.m_bRightClick == false)
\r
1525 if (m_mnuDrop == NULL) // first time, load it up
\r
1527 int nID = ID_ENTITY_START;
\r
1528 GtkWidget *menu, *menu_in_menu, *item, *submenu, *submenu_root;
\r
1530 menu = m_mnuDrop = gtk_menu_new ();
\r
1532 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Select");
\r
1533 create_menu_item_with_mnemonic (menu_in_menu, "Select Complete Tall",
\r
1534 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTCOMPLETETALL);
\r
1535 create_menu_item_with_mnemonic (menu_in_menu, "Select Touching",
\r
1536 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTTOUCHING);
\r
1537 create_menu_item_with_mnemonic (menu_in_menu, "Select Partial Tall",
\r
1538 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTPARTIALTALL);
\r
1539 create_menu_item_with_mnemonic (menu_in_menu, "Select Inside",
\r
1540 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTINSIDE);
\r
1541 menu_separator (menu); nID++;
\r
1542 // NOTE: temporary commented out until we put it back in for good (that is with actual features)
\r
1544 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Group",);
\r
1545 create_menu_item_with_mnemonic (menu_in_menu, "Add to...",
\r
1546 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_ADDTO);
\r
1547 create_menu_item_with_mnemonic (menu_in_menu, "Remove",
\r
1548 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_REMOVE);
\r
1549 create_menu_item_with_mnemonic (menu_in_menu, "Name...",
\r
1550 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_NAME);
\r
1551 menu_separator (menu_in_menu); nID++;
\r
1552 create_menu_item_with_mnemonic (menu_in_menu, "New Group...",
\r
1553 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_NEWGROUP);
\r
1555 create_menu_item_with_mnemonic (menu, "Ungroup Entity",
\r
1556 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_UNGROUPENTITY);
\r
1558 create_menu_item_with_mnemonic (menu, "Move into entity",
\r
1559 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MERGE);
\r
1560 create_menu_item_with_mnemonic (menu, "Move into worldspawn",
\r
1561 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SEPERATE);
\r
1563 create_menu_item_with_mnemonic (menu, "Make Detail",
\r
1564 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MAKE_DETAIL);
\r
1565 create_menu_item_with_mnemonic (menu, "Make Structural",
\r
1566 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MAKE_STRUCTURAL);
\r
1567 menu_separator (menu); nID++;
\r
1569 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Smart Entities");
\r
1570 create_menu_item_with_mnemonic (menu_in_menu, "Smart__Train",
\r
1571 GTK_SIGNAL_FUNC (HandleCommand), nID++);
\r
1572 menu_separator (menu); nID++;
\r
1575 submenu_root = NULL;
\r
1577 CString strActive;
\r
1580 for (e=eclass ; e ; e=e->next)
\r
1582 strLast = strName;
\r
1583 strName = e->name;
\r
1584 int n_ = strName.Find("_");
\r
1587 CString strLeft = strName.Left(n_);
\r
1588 CString strRight = strName.Right(strName.GetLength() - n_ - 1);
\r
1589 if (strLeft == strActive) // this is a child
\r
1592 item = gtk_menu_item_new_with_label (strName);
\r
1593 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
\r
1594 GINT_TO_POINTER (nID++));
\r
1595 gtk_widget_show (item);
\r
1596 CheckMenuSplitting(submenu);
\r
1597 gtk_menu_append (GTK_MENU (submenu), item);
\r
1603 // this is submenu from previous main_item, hook it back
\r
1604 // we use submenu_root cause we may have been cascading submenu
\r
1605 item = gtk_menu_item_new_with_label (strActive);
\r
1606 gtk_widget_show (item);
\r
1607 gtk_menu_append (GTK_MENU (menu), item);
\r
1608 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_root);
\r
1609 g_ptrMenus.Add(submenu_root);
\r
1611 submenu_root = NULL;
\r
1613 strActive = strLeft;
\r
1615 submenu = gtk_menu_new ();
\r
1616 submenu_root = submenu;
\r
1617 item = gtk_menu_item_new_with_label (strName);
\r
1618 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
\r
1619 GINT_TO_POINTER (nID++));
\r
1620 gtk_widget_show (item);
\r
1621 gtk_menu_append (GTK_MENU (submenu), item);
\r
1628 // this is submenu from previous main_item, hook it back
\r
1629 // we use submenu_root cause we may have been cascading submenu
\r
1630 item = gtk_menu_item_new_with_label (strActive);
\r
1631 gtk_widget_show (item);
\r
1632 gtk_menu_append (GTK_MENU (menu), item);
\r
1633 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_root);
\r
1634 g_ptrMenus.Add(submenu_root);
\r
1636 submenu_root = NULL;
\r
1640 item = gtk_menu_item_new_with_label (strName);
\r
1641 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
\r
1642 GINT_TO_POINTER (nID++));
\r
1643 gtk_widget_show (item);
\r
1644 gtk_menu_append (GTK_MENU (menu), item);
\r
1649 gtk_menu_popup (GTK_MENU (m_mnuDrop), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
\r
1657 void XYWnd::NewBrushDrag (int x, int y)
\r
1659 vec3_t mins, maxs, junk;
\r
1664 if (!DragDelta (x,y, junk))
\r
1667 // delete the current selection
\r
1668 if (selected_brushes.next != &selected_brushes)
\r
1669 Brush_Free (selected_brushes.next);
\r
1671 SnapToPoint (m_nPressx, m_nPressy, mins);
\r
1673 int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
\r
1676 // mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z / g_qeglobals.d_gridsize));
\r
1677 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_work_min[nDim]/g_qeglobals.d_gridsize));
\r
1679 SnapToPoint (x, y, maxs);
\r
1680 // maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z / g_qeglobals.d_gridsize));
\r
1681 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_work_max[nDim]/g_qeglobals.d_gridsize));
\r
1682 if (maxs[nDim] <= mins[nDim])
\r
1683 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
\r
1685 for (i=0 ; i<3 ; i++)
\r
1687 if (mins[i] == maxs[i])
\r
1688 return; // don't create a degenerate brush
\r
1689 if (mins[i] > maxs[i])
\r
1692 mins[i] = maxs[i];
\r
1697 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
\r
1702 VectorSubtract(maxs, mins, vSize);
\r
1703 g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
\r
1704 g_pParentWnd->SetStatusText(2, g_strStatus);
\r
1706 Brush_AddToList (n, &selected_brushes);
\r
1708 Entity_LinkBrush (world_entity, n);
\r
1712 // Sys_UpdateWindows (W_ALL);
\r
1713 Sys_UpdateWindows (W_XY| W_CAMERA);
\r
1722 void XYWnd::XY_MouseMoved (int x, int y, int buttons)
\r
1726 if (!m_nButtonstate)
\r
1728 if (g_bCrossHairs)
\r
1730 Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
\r
1735 // lbutton without selection = drag new brush
\r
1736 if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint && g_qeglobals.d_select_mode != sel_areatall)
\r
1738 NewBrushDrag (x, y);
\r
1742 // lbutton (possibly with control and or shift)
\r
1743 // with selection = drag selection
\r
1744 if (m_nButtonstate & MK_LBUTTON)
\r
1746 Drag_MouseMoved (x, y, buttons);
\r
1747 if(g_qeglobals.d_select_mode != sel_area)
\r
1748 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
\r
1752 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
\r
1753 // control mbutton = move camera
\r
1754 if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
\r
1756 SnapToPoint (x, y, point);
\r
1757 VectorCopyXY(point, g_pParentWnd->GetCamWnd()->Camera()->origin);
\r
1758 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
\r
1762 // shift mbutton = move z checker
\r
1763 if (m_nButtonstate == (MK_SHIFT|nMouseButton) )
\r
1765 if (RotateMode() || g_bPatchBendMode)
\r
1767 SnapToPoint (x, y, point);
\r
1768 VectorCopyXY(point, g_vRotateOrigin);
\r
1769 if (g_bPatchBendMode)
\r
1771 VectorCopy(point, g_vBendOrigin);
\r
1773 Sys_UpdateWindows (W_XY);
\r
1778 SnapToPoint (x, y, point);
\r
1779 if (m_nViewType == XY)
\r
1781 z.origin[0] = point[0];
\r
1782 z.origin[1] = point[1];
\r
1784 else if (m_nViewType == YZ)
\r
1786 z.origin[0] = point[1];
\r
1787 z.origin[1] = point[2];
\r
1791 z.origin[0] = point[0];
\r
1792 z.origin[1] = point[2];
\r
1795 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
\r
1799 // mbutton = angle camera
\r
1800 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
\r
1801 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
\r
1803 SnapToPoint (x, y, point);
\r
1804 VectorSubtract (point, g_pParentWnd->GetCamWnd()->Camera()->origin, point);
\r
1806 int n1 = (m_nViewType == XY) ? 1 : 2;
\r
1807 int n2 = (m_nViewType == YZ) ? 1 : 0;
\r
1808 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
\r
1809 if (point[n1] || point[n2])
\r
1811 g_pParentWnd->GetCamWnd()->Camera()->angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
\r
1812 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
\r
1817 // rbutton = drag xy origin
\r
1818 if (m_nButtonstate == MK_RBUTTON)
\r
1820 Sys_GetCursorPos (&x, &y);
\r
1821 if (x != m_ptCursorX || y != m_ptCursorY)
\r
1823 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
1824 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
1825 m_vOrigin[nDim1] -= (x - m_ptCursorX) / m_fScale;
\r
1826 m_vOrigin[nDim2] += (y - m_ptCursorY) / m_fScale;
\r
1827 Sys_SetCursorPos (m_ptCursorX, m_ptCursorY);
\r
1829 // create an empty cursor
\r
1830 if (!g_bWaitCursor)
\r
1832 GdkPixmap *pixmap;
\r
1834 char buffer [(32 * 32)/8];
\r
1835 memset (buffer, 0, (32 * 32)/8);
\r
1836 GdkColor white = {0, 0xffff, 0xffff, 0xffff};
\r
1837 GdkColor black = {0, 0x0000, 0x0000, 0x0000};
\r
1838 pixmap = gdk_bitmap_create_from_data (NULL, buffer, 32, 32);
\r
1839 mask = gdk_bitmap_create_from_data (NULL, buffer, 32, 32);
\r
1840 GdkCursor *cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &white, &black, 1, 1);
\r
1841 gdk_window_set_cursor (m_pWidget->window, cursor);
\r
1842 gdk_cursor_unref (cursor);
\r
1843 gdk_drawable_unref (pixmap);
\r
1844 gdk_drawable_unref (mask);
\r
1847 Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
\r
1853 if (m_nButtonstate == (MK_SHIFT | MK_RBUTTON))
\r
1855 Sys_GetCursorPos (&x, &y);
\r
1856 if (y != m_ptCursorY)
\r
1858 if (abs (m_ptCursorY - y) > 10)
\r
1860 if (m_ptCursorY < y)
\r
1861 g_pParentWnd->OnViewZoomout ();
\r
1863 g_pParentWnd->OnViewZoomin ();
\r
1865 Sys_SetCursorPos (m_ptCursorX, m_ptCursorY);
\r
1872 void XYWnd::OriginalButtonDown(guint32 nFlags, int pointx, int pointy)
\r
1876 XY_MouseDown (pointx, m_pWidget->allocation.height - 1 - pointy , nFlags);
\r
1877 m_nScrollFlags = nFlags;
\r
1880 void XYWnd::OriginalButtonUp(guint32 nFlags, int pointx, int pointy)
\r
1882 XY_MouseUp (pointx, m_pWidget->allocation.height - 1 - pointy , nFlags);
\r
1883 ReleaseCapture ();
\r
1886 void XYWnd::DropClipPoint(guint32 nFlags, int pointx, int pointy)
\r
1888 if (g_pMovingClip)
\r
1891 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *g_pMovingClip);
\r
1895 vec3_t* pPt = NULL;
\r
1896 if (g_Clip1.Set() == false)
\r
1899 g_Clip1.Set(true);
\r
1900 g_Clip1.m_ptScreenX = pointx;
\r
1901 g_Clip1.m_ptScreenY = pointy;
\r
1904 if (g_Clip2.Set() == false)
\r
1907 g_Clip2.Set(true);
\r
1908 g_Clip2.m_ptScreenX = pointx;
\r
1909 g_Clip2.m_ptScreenY = pointy;
\r
1912 if (g_Clip3.Set() == false)
\r
1915 g_Clip3.Set(true);
\r
1916 g_Clip3.m_ptScreenX = pointx;
\r
1917 g_Clip3.m_ptScreenY = pointy;
\r
1921 RetainClipMode(true);
\r
1923 g_Clip1.Set(true);
\r
1924 g_Clip1.m_ptScreenX = pointx;
\r
1925 g_Clip1.m_ptScreenY = pointy;
\r
1927 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *pPt);
\r
1928 // third coordinates for clip point: use d_work_max
\r
1929 // Arnout: changed to use center of selection for clipping, saves level designers moving points all over the map
\r
1930 // g_pParentWnd->ActiveXY()->GetViewType()
\r
1931 // cf VIEWTYPE defintion: enum VIEWTYPE {YZ, XZ, XY};
\r
1932 int nViewType = g_pParentWnd->ActiveXY()->GetViewType();
\r
1933 int nDim = (nViewType == YZ ) ? nDim = 0 : ( (nViewType == XZ) ? nDim = 1 : nDim = 2 );
\r
1934 //(*pPt)[nDim] = g_qeglobals.d_work_max[nDim];
\r
1936 Select_GetMid( mid );
\r
1937 (*pPt)[nDim] = mid[nDim];
\r
1939 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
1942 void XYWnd::DropPathPoint(guint32 nFlags, int pointx, int pointy)
\r
1944 if (g_pMovingPath)
\r
1947 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *g_pMovingPath);
\r
1951 g_PathPoints[g_nPathCount].Set(true);
\r
1952 g_PathPoints[g_nPathCount].m_ptScreenX = pointx;
\r
1953 g_PathPoints[g_nPathCount].m_ptScreenY = pointy;
\r
1954 SnapToPoint(pointx, m_pWidget->allocation.height - 1 - pointy, g_PathPoints[g_nPathCount]);
\r
1955 // third coordinates for dropped point: use d_work_max
\r
1956 // g_pParentWnd->ActiveXY()->GetViewType()
\r
1957 // cf VIEWTYPE definition: enum VIEWTYPE {YZ, XZ, XY};
\r
1958 int nViewType = g_pParentWnd->ActiveXY()->GetViewType();
\r
1959 int nDim = (nViewType == YZ ) ? nDim = 0 : ( (nViewType == XZ) ? nDim = 1 : nDim = 2 );
\r
1960 g_PathPoints[g_nPathCount].m_ptClip[nDim] = g_qeglobals.d_work_max[nDim];
\r
1963 if (g_nPathCount == g_nPathLimit)
\r
1966 g_pPathFunc(true, g_nPathCount);
\r
1968 g_bPathMode = false;
\r
1969 g_pPathFunc = NULL;
\r
1972 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
1975 // FIXME: AddPointPoint() redundant function never called
\r
1977 void XYWnd::AddPointPoint(guint32 nFlags, vec3_t* pVec)
\r
1979 g_PointPoints[g_nPointCount].Set(true);
\r
1980 //g_PointPoints[g_nPointCount].m_ptScreen = point;
\r
1981 _VectorCopy(*pVec, g_PointPoints[g_nPointCount]);
\r
1982 g_PointPoints[g_nPointCount].SetPointPtr(pVec);
\r
1984 Sys_UpdateWindows(XY | W_CAMERA_IFON);
\r
1987 // FIXME: ProduceSplits() redundant function never called
\r
1988 void XYWnd::ProduceSplits(brush_t** pFront, brush_t** pBack)
\r
1994 if (g_Clip1.Set() && g_Clip2.Set())
\r
1997 VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
\r
1998 VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
\r
1999 VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
\r
2000 if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes))
\r
2002 if (g_Clip3.Set() == false)
\r
2004 if (m_nViewType == XY)
\r
2006 face.planepts[0][2] = selected_brushes.next->mins[2];
\r
2007 face.planepts[1][2] = selected_brushes.next->mins[2];
\r
2008 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
\r
2009 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
\r
2010 face.planepts[2][2] = selected_brushes.next->maxs[2];
\r
2012 else if (m_nViewType == YZ)
\r
2014 face.planepts[0][0] = selected_brushes.next->mins[0];
\r
2015 face.planepts[1][0] = selected_brushes.next->mins[0];
\r
2016 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
\r
2017 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
\r
2018 face.planepts[2][0] = selected_brushes.next->maxs[0];
\r
2022 face.planepts[0][1] = selected_brushes.next->mins[1];
\r
2023 face.planepts[1][1] = selected_brushes.next->mins[1];
\r
2024 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
\r
2025 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
\r
2026 face.planepts[2][1] = selected_brushes.next->maxs[1];
\r
2030 Brush_SplitBrushByFace (selected_brushes.next, &face, pFront, pBack);
\r
2038 void XYWnd::PlanePointsFromClipPoints(vec3_t planepts[3], brush_t *pBrush)
\r
2040 VectorCopy(g_Clip1.m_ptClip,planepts[0]);
\r
2041 VectorCopy(g_Clip2.m_ptClip,planepts[1]);
\r
2042 VectorCopy(g_Clip3.m_ptClip,planepts[2]);
\r
2043 if (g_Clip3.Set() == false)
\r
2045 int n = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 2 : (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 0 : 1;
\r
2046 int x = (n == 0) ? 1 : 0;
\r
2047 int y = (n == 2) ? 1 : 2;
\r
2049 if (n == 1) // on viewtype XZ, flip clip points
\r
2051 planepts[0][n] = pBrush->maxs[n];
\r
2052 planepts[1][n] = pBrush->maxs[n];
\r
2053 planepts[2][x] = g_Clip1.m_ptClip[x];
\r
2054 planepts[2][y] = g_Clip1.m_ptClip[y];
\r
2055 planepts[2][n] = pBrush->mins[n];
\r
2059 planepts[0][n] = pBrush->mins[n];
\r
2060 planepts[1][n] = pBrush->mins[n];
\r
2061 planepts[2][x] = g_Clip1.m_ptClip[x];
\r
2062 planepts[2][y] = g_Clip1.m_ptClip[y];
\r
2063 planepts[2][n] = pBrush->maxs[n];
\r
2068 void XYWnd::ProduceSplitLists()
\r
2070 bool bCaulk = false;
\r
2073 if (AnyPatchesSelected())
\r
2075 Sys_Printf("Deselecting patches for clip operation.\n");
\r
2077 for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = next)
\r
2080 if (pb->patchBrush)
\r
2082 Brush_RemoveFromList (pb);
\r
2083 Brush_AddToList (pb, &active_brushes);
\r
2084 UpdatePatchInspector();
\r
2087 // ydnar: update the window if any patches are selected
\r
2088 Sys_UpdateWindows( XY | W_CAMERA_IFON );
\r
2091 CleanList(&g_brFrontSplits);
\r
2092 CleanList(&g_brBackSplits);
\r
2093 g_brFrontSplits.next = &g_brFrontSplits;
\r
2094 g_brBackSplits.next = &g_brBackSplits;
\r
2095 if (ClipMode() && (g_Clip1.Set() && g_Clip2.Set()))
\r
2098 for (pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
\r
2100 brush_t* pFront = NULL;
\r
2101 brush_t* pBack = NULL;
\r
2104 memset(&face,0,sizeof(face_t));
\r
2105 PlanePointsFromClipPoints(face.planepts, pBrush);
\r
2107 // decide wether caulking should be applied on the splits
\r
2109 // this should take the first brush face, check shader for NODRAW, if it isn't nodraw then find the appropriate
\r
2110 // common/ shader to use, out of solid+nodraw, nonsolid+nodraw, water+nodraw, lava+nodraw, nonsolid+nodraw+trans, water+nodraw+trans, lava+nodraw+trans.. and fog.. etc
\r
2111 // or if none of those apply (unlikely), construct a new shader (shadername_nodraw) based on the shader of the first face, but with surfaceparm nodraw
\r
2112 if (g_PrefsDlg.m_bClipCaulk)
\r
2114 nFlags = pBrush->brush_faces->pShader->getFlags();
\r
2115 if ((nFlags & QER_NODRAW) || (nFlags & QER_NONSOLID) || (nFlags & QER_WATER) || (nFlags & QER_LAVA) || (nFlags & QER_FOG)) // first face shader is anything other than solid AND opaque like caulk
\r
2116 bCaulk = false; // use first face's shader for the splitting face
\r
2118 bCaulk = true; // use caulk
\r
2121 Brush_SplitBrushByFace (pBrush, &face, &pFront, &pBack, bCaulk);
\r
2123 Brush_AddToList(pBack, &g_brBackSplits);
\r
2125 Brush_AddToList(pFront, &g_brFrontSplits);
\r
2131 void XYWnd::XY_Init()
\r
2134 m_vOrigin[1] = 20;
\r
2135 m_vOrigin[2] = 46;
\r
2139 void XYWnd::SnapToPoint (int x, int y, vec3_t point)
\r
2141 if (g_PrefsDlg.m_bNoClamp)
\r
2143 XY_ToPoint(x, y, point);
\r
2147 XY_ToGridPoint(x, y, point);
\r
2151 // TTimo: watch it, this doesn't init one of the 3 coords
\r
2152 void XYWnd::XY_ToPoint (int x, int y, vec3_t point)
\r
2156 float fw = m_nWidth;
\r
2157 float fh = m_nHeight;
\r
2158 if (m_nViewType == XY)
\r
2160 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
\r
2161 point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
\r
2163 else if (m_nViewType == YZ)
\r
2165 point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
\r
2166 point[2] = m_vOrigin[2] + (fy - fh / 2 ) / m_fScale;
\r
2170 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
\r
2171 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
\r
2175 void XYWnd::XY_ToGridPoint (int x, int y, vec3_t point)
\r
2177 if (m_nViewType == XY)
\r
2179 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
\r
2180 point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
\r
2181 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
2182 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
2184 else if (m_nViewType == YZ)
\r
2186 point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
\r
2187 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
\r
2188 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
2189 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
2193 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
\r
2194 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
\r
2195 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
2196 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
\r
2201 ============================================================================
\r
2205 ============================================================================
\r
2213 void XYWnd::XY_DrawGrid()
\r
2215 float x, y, xb, xe, yb, ye;
\r
2218 int step, stepx, stepy, colour;
\r
2219 step = stepx = stepy = MAX (64, (int)g_qeglobals.d_gridsize);
\r
2222 int stepSize = (int)(8 / m_fScale);
\r
2223 if (stepSize > step)
\r
2226 for (i = 1; i < stepSize; i <<= 1)
\r
2232 //Sys_Printf("scale: %f\n", m_fScale);
\r
2233 //Sys_Printf("step before: %i\n", step);
\r
2234 //Sys_Printf("scaled step: %f\n", step * m_fScale);
\r
2235 while ((step * m_fScale) < 4.0f) // make sure major grid spacing is at least 4 pixels on the screen
\r
2237 //Sys_Printf("step after: %i\n", step);
\r
2238 while ((stepx * m_fScale) < 32.0f) // text step x must be at least 32
\r
2240 while ((stepy * m_fScale) < 32.0f) // text step y must be at least 32
\r
2243 qglDisable(GL_TEXTURE_2D);
\r
2244 qglDisable(GL_TEXTURE_1D);
\r
2245 qglDisable(GL_DEPTH_TEST);
\r
2246 qglDisable(GL_BLEND);
\r
2248 w = (m_nWidth / 2 / m_fScale);
\r
2249 h = (m_nHeight / 2 / m_fScale);
\r
2251 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
2252 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
2254 xb = m_vOrigin[nDim1] - w;
\r
2255 if (xb < region_mins[nDim1])
\r
2256 xb = region_mins[nDim1];
\r
2257 xb = step * floor (xb/step);
\r
2259 xe = m_vOrigin[nDim1] + w;
\r
2260 if (xe > region_maxs[nDim1])
\r
2261 xe = region_maxs[nDim1];
\r
2262 xe = step * ceil (xe/step);
\r
2264 yb = m_vOrigin[nDim2] - h;
\r
2265 if (yb < region_mins[nDim2])
\r
2266 yb = region_mins[nDim2];
\r
2267 yb = step * floor (yb/step);
\r
2269 ye = m_vOrigin[nDim2] + h;
\r
2270 if (ye > region_maxs[nDim2])
\r
2271 ye = region_maxs[nDim2];
\r
2272 ye = step * ceil (ye/step);
\r
2274 #define COLORS_DIFFER(a,b) \
\r
2275 (g_qeglobals.d_savedinfo.colors[a][0] != g_qeglobals.d_savedinfo.colors[b][0] || \
\r
2276 g_qeglobals.d_savedinfo.colors[a][1] != g_qeglobals.d_savedinfo.colors[b][1] || \
\r
2277 g_qeglobals.d_savedinfo.colors[a][2] != g_qeglobals.d_savedinfo.colors[b][2])
\r
2280 // draw minor blocks
\r
2281 if (m_fScale > .1 && g_qeglobals.d_showgrid && g_qeglobals.d_gridsize * m_fScale >= 4)
\r
2283 if (g_qeglobals.d_gridsize < 1)
\r
2284 colour = COLOR_GRIDMINOR_ALT;
\r
2286 colour = COLOR_GRIDMINOR;
\r
2288 if (COLORS_DIFFER(colour, COLOR_GRIDBACK))
\r
2290 qglColor3fv(g_qeglobals.d_savedinfo.colors[colour]);
\r
2292 qglBegin (GL_LINES);
\r
2293 for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
\r
2295 if (!((int)x & (step-1)) && !((int)x - x))
\r
2297 qglVertex2f (x, yb);
\r
2298 qglVertex2f (x, ye);
\r
2300 for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
\r
2302 if (!((int)y & (step-1)) && !((int)y - y))
\r
2304 qglVertex2f (xb, y);
\r
2305 qglVertex2f (xe, y);
\r
2311 if(g_qeglobals.d_gridsize < 1)
\r
2312 colour = COLOR_GRIDMAJOR_ALT;
\r
2314 colour = COLOR_GRIDMAJOR;
\r
2316 // draw major blocks
\r
2317 if (COLORS_DIFFER(colour, COLOR_GRIDBACK))
\r
2318 qglColor3fv(g_qeglobals.d_savedinfo.colors[colour]);
\r
2320 if ( g_qeglobals.d_showgrid )
\r
2322 qglBegin (GL_LINES);
\r
2323 for (x=xb ; x<=xe ; x+=step)
\r
2325 qglVertex2f (x, yb);
\r
2326 qglVertex2f (x, ye);
\r
2328 for (y=yb ; y<=ye ; y+=step)
\r
2330 qglVertex2f (xb, y);
\r
2331 qglVertex2f (xe, y);
\r
2336 // draw coordinate text if needed
\r
2337 if ( g_qeglobals.d_savedinfo.show_coordinates)
\r
2339 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]);
\r
2340 float offx = m_vOrigin[nDim2] + h - 6 / m_fScale, offy = m_vOrigin[nDim1] - w + 1 / m_fScale;
\r
2341 for (x=xb-((int)xb)%stepx; x<=xe ; x+=stepx)
\r
2343 qglRasterPos2f (x, offx);
\r
2344 sprintf (text, "%i",(int)x);
\r
2345 gtk_glwidget_print_string(text);
\r
2347 for (y=yb-((int)yb)%stepy; y<=ye ; y+=stepy)
\r
2349 qglRasterPos2f (offy, y);
\r
2350 sprintf (text, "%i",(int)y);
\r
2351 gtk_glwidget_print_string(text);
\r
2355 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
\r
2357 // we do this part (the old way) only if show_axis is disabled
\r
2358 if (!g_qeglobals.d_savedinfo.show_axis)
\r
2360 qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
\r
2363 if (m_nViewType == XY)
\r
2364 strcpy(cView, "XY Top");
\r
2366 if (m_nViewType == XZ)
\r
2367 strcpy(cView, "XZ Front");
\r
2369 strcpy(cView, "YZ Side");
\r
2371 gtk_glwidget_print_string(cView);
\r
2375 if ( g_qeglobals.d_savedinfo.show_axis)
\r
2377 // draw two lines with corresponding axis colors to highlight current view
\r
2378 // horizontal line: nDim1 color
\r
2380 qglBegin( GL_LINES );
\r
2381 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
\r
2382 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
\r
2383 qglVertex2f( m_vOrigin[nDim1] - w + 65 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
\r
2384 qglVertex2f( 0, 0 );
\r
2385 qglVertex2f( 32 / m_fScale, 0 );
\r
2386 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
\r
2387 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
\r
2388 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
\r
2389 qglVertex2f( 0, 0 );
\r
2390 qglVertex2f( 0, 32 / m_fScale );
\r
2393 // now print axis symbols
\r
2394 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
\r
2395 qglRasterPos2f ( m_vOrigin[nDim1] - w + 55 / m_fScale, m_vOrigin[nDim2] + h - 55 / m_fScale );
\r
2396 gtk_glwidget_print_char(g_AxisName[nDim1]);
\r
2397 qglRasterPos2f (28 / m_fScale, -10 / m_fScale );
\r
2398 gtk_glwidget_print_char(g_AxisName[nDim1]);
\r
2399 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
\r
2400 qglRasterPos2f ( m_vOrigin[nDim1] - w + 25 / m_fScale, m_vOrigin[nDim2] + h - 30 / m_fScale );
\r
2401 gtk_glwidget_print_char(g_AxisName[nDim2]);
\r
2402 qglRasterPos2f ( -10 / m_fScale, 28 / m_fScale );
\r
2403 gtk_glwidget_print_char(g_AxisName[nDim2]);
\r
2407 // show current work zone?
\r
2408 // the work zone is used to place dropped points and brushes
\r
2409 if (g_qeglobals.d_show_work)
\r
2411 qglColor3f( 1.0f, 0.0f, 0.0f );
\r
2412 qglBegin( GL_LINES );
\r
2413 qglVertex2f( xb, g_qeglobals.d_work_min[nDim2] );
\r
2414 qglVertex2f( xe, g_qeglobals.d_work_min[nDim2] );
\r
2415 qglVertex2f( xb, g_qeglobals.d_work_max[nDim2] );
\r
2416 qglVertex2f( xe, g_qeglobals.d_work_max[nDim2] );
\r
2417 qglVertex2f( g_qeglobals.d_work_min[nDim1], yb );
\r
2418 qglVertex2f( g_qeglobals.d_work_min[nDim1], ye );
\r
2419 qglVertex2f( g_qeglobals.d_work_max[nDim1], yb );
\r
2420 qglVertex2f( g_qeglobals.d_work_max[nDim1], ye );
\r
2430 void XYWnd::XY_DrawBlockGrid()
\r
2432 const char *value = ValueForKey( world_entity, "_blocksize" );
\r
2433 if (strlen(value))
\r
2434 sscanf( value, "%i", &g_qeglobals.blockSize );
\r
2436 if (!g_qeglobals.blockSize || g_qeglobals.blockSize > 65536 || g_qeglobals.blockSize < 1024)
\r
2437 // don't use custom blocksize if it is less than the default, or greater than the maximum world coordinate
\r
2438 g_qeglobals.blockSize = 1024;
\r
2440 float x, y, xb, xe, yb, ye;
\r
2444 qglDisable(GL_TEXTURE_2D);
\r
2445 qglDisable(GL_TEXTURE_1D);
\r
2446 qglDisable(GL_DEPTH_TEST);
\r
2447 qglDisable(GL_BLEND);
\r
2449 w = (m_nWidth / 2 / m_fScale);
\r
2450 h = (m_nHeight / 2 / m_fScale);
\r
2452 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
2453 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
2455 xb = m_vOrigin[nDim1] - w;
\r
2456 if (xb < region_mins[nDim1])
\r
2457 xb = region_mins[nDim1];
\r
2458 xb = g_qeglobals.blockSize * floor (xb/g_qeglobals.blockSize);
\r
2460 xe = m_vOrigin[nDim1] + w;
\r
2461 if (xe > region_maxs[nDim1])
\r
2462 xe = region_maxs[nDim1];
\r
2463 xe = g_qeglobals.blockSize * ceil (xe/g_qeglobals.blockSize);
\r
2465 yb = m_vOrigin[nDim2] - h;
\r
2466 if (yb < region_mins[nDim2])
\r
2467 yb = region_mins[nDim2];
\r
2468 yb = g_qeglobals.blockSize * floor (yb/g_qeglobals.blockSize);
\r
2470 ye = m_vOrigin[nDim2] + h;
\r
2471 if (ye > region_maxs[nDim2])
\r
2472 ye = region_maxs[nDim2];
\r
2473 ye = g_qeglobals.blockSize * ceil (ye/g_qeglobals.blockSize);
\r
2475 // draw major blocks
\r
2477 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]);
\r
2480 qglBegin (GL_LINES);
\r
2482 for (x=xb ; x<=xe ; x+=g_qeglobals.blockSize)
\r
2484 qglVertex2f (x, yb);
\r
2485 qglVertex2f (x, ye);
\r
2488 if (m_nViewType == XY)
\r
2490 for (y=yb ; y<=ye ; y+=g_qeglobals.blockSize)
\r
2492 qglVertex2f (xb, y);
\r
2493 qglVertex2f (xe, y);
\r
2500 // draw coordinate text if needed
\r
2502 if (m_nViewType == XY && m_fScale > .1)
\r
2504 for (x=xb ; x<xe ; x+=g_qeglobals.blockSize)
\r
2505 for (y=yb ; y<ye ; y+=g_qeglobals.blockSize)
\r
2507 qglRasterPos2f (x+(g_qeglobals.blockSize/2), y+(g_qeglobals.blockSize/2));
\r
2508 sprintf (text, "%i,%i",(int)floor(x/g_qeglobals.blockSize), (int)floor(y/g_qeglobals.blockSize) );
\r
2509 gtk_glwidget_print_string(text);
\r
2513 qglColor4f(0, 0, 0, 0);
\r
2516 void XYWnd::DrawRotateIcon()
\r
2520 a = 4.0 / m_fScale; // compensate for zoom level
\r
2521 b = 6.0 / m_fScale;
\r
2523 if (m_nViewType == XY)
\r
2525 x = g_vRotateOrigin[0];
\r
2526 y = g_vRotateOrigin[1];
\r
2528 else if (m_nViewType == YZ)
\r
2530 x = g_vRotateOrigin[1];
\r
2531 y = g_vRotateOrigin[2];
\r
2535 x = g_vRotateOrigin[0];
\r
2536 y = g_vRotateOrigin[2];
\r
2539 qglEnable (GL_BLEND);
\r
2540 qglDisable (GL_TEXTURE_2D);
\r
2541 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
\r
2542 qglDisable (GL_CULL_FACE);
\r
2543 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\r
2544 qglColor4f (0.8f, 0.1f, 0.9f, 0.25f);
\r
2546 qglBegin(GL_QUADS);
\r
2547 qglVertex3f (x-a,y-a,0);
\r
2548 qglVertex3f (x+a,y-a,0);
\r
2549 qglVertex3f (x+a,y+a,0);
\r
2550 qglVertex3f (x-a,y+a,0);
\r
2552 qglDisable (GL_BLEND);
\r
2554 qglColor4f (1.0f, 0.2f, 1.0f, 1.f);
\r
2555 qglBegin(GL_POINTS);
\r
2556 qglVertex3f (x,y,0);
\r
2560 qglBegin(GL_LINES);
\r
2561 qglVertex3f (x-b,y+b,0);
\r
2562 qglVertex3f (x+b,y+b,0);
\r
2563 qglVertex3f (x-b,y-b,0);
\r
2564 qglVertex3f (x+b,y-b,0);
\r
2570 void XYWnd::DrawCameraIcon()
\r
2572 float x, y, a, fov, box;
\r
2574 fov = 48 / m_fScale;
\r
2575 box = 16 / m_fScale;
\r
2577 if (m_nViewType == XY)
\r
2579 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
\r
2580 y = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
\r
2581 a = g_pParentWnd->GetCamWnd()->Camera()->angles[YAW]/180*Q_PI;
\r
2583 else if (m_nViewType == YZ)
\r
2585 x = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
\r
2586 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
\r
2587 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
\r
2591 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
\r
2592 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
\r
2593 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
\r
2596 qglColor3f (0.0, 0.0, 1.0);
\r
2597 qglBegin(GL_LINE_STRIP);
\r
2598 qglVertex3f (x-box,y,0);
\r
2599 qglVertex3f (x,y+(box/2),0);
\r
2600 qglVertex3f (x+box,y,0);
\r
2601 qglVertex3f (x,y-(box/2),0);
\r
2602 qglVertex3f (x-box,y,0);
\r
2603 qglVertex3f (x+box,y,0);
\r
2606 qglBegin(GL_LINE_STRIP);
\r
2607 qglVertex3f (x+fov*cos(a+Q_PI/4), y+fov*sin(a+Q_PI/4), 0);
\r
2608 qglVertex3f (x, y, 0);
\r
2609 qglVertex3f (x+fov*cos(a-Q_PI/4), y+fov*sin(a-Q_PI/4), 0);
\r
2614 void XYWnd::DrawZIcon (void)
\r
2616 if (m_nViewType == XY)
\r
2618 float x = z.origin[0];
\r
2619 float y = z.origin[1];
\r
2620 float zdim = 8 / m_fScale;
\r
2621 qglEnable (GL_BLEND);
\r
2622 qglDisable (GL_TEXTURE_2D);
\r
2623 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
\r
2624 qglDisable (GL_CULL_FACE);
\r
2625 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\r
2626 qglColor4f (0.0, 0.0, 1.0, 0.25);
\r
2627 qglBegin(GL_QUADS);
\r
2628 qglVertex3f (x-zdim,y-zdim,0);
\r
2629 qglVertex3f (x+zdim,y-zdim,0);
\r
2630 qglVertex3f (x+zdim,y+zdim,0);
\r
2631 qglVertex3f (x-zdim,y+zdim,0);
\r
2633 qglDisable (GL_BLEND);
\r
2635 qglColor4f (0.0, 0.0, 1.0, 1);
\r
2637 qglBegin(GL_LINE_LOOP);
\r
2638 qglVertex3f (x-zdim,y-zdim,0);
\r
2639 qglVertex3f (x+zdim,y-zdim,0);
\r
2640 qglVertex3f (x+zdim,y+zdim,0);
\r
2641 qglVertex3f (x-zdim,y+zdim,0);
\r
2644 qglBegin(GL_LINE_STRIP);
\r
2645 qglVertex3f (x-(zdim/2),y+(zdim/2),0);
\r
2646 qglVertex3f (x+(zdim/2),y+(zdim/2),0);
\r
2647 qglVertex3f (x-(zdim/2),y-(zdim/2),0);
\r
2648 qglVertex3f (x+(zdim/2),y-(zdim/2),0);
\r
2653 // can be greatly simplified but per usual i am in a hurry
\r
2654 // which is not an excuse, just a fact
\r
2655 void XYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds)
\r
2657 const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"};
\r
2658 const char* g_pOrgStrings[] = {"(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)"};
\r
2663 VectorSubtract(vMaxBounds, vMinBounds, vSize);
\r
2665 qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
\r
2666 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
\r
2667 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65);
\r
2669 if (m_nViewType == XY)
\r
2671 qglBegin (GL_LINES);
\r
2673 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
\r
2674 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
\r
2676 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
\r
2677 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
\r
2679 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
\r
2680 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
\r
2683 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
\r
2684 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
\r
2686 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
\r
2687 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
\r
2689 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
\r
2690 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
\r
2694 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
\r
2695 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
\r
2696 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2698 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
\r
2699 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
\r
2700 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2702 qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
\r
2703 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
\r
2704 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2706 else if (m_nViewType == XZ)
\r
2708 qglBegin (GL_LINES);
\r
2710 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
\r
2711 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2713 qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2714 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2716 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale);
\r
2717 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2720 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2]);
\r
2721 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
\r
2723 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
\r
2724 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
\r
2726 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2]);
\r
2727 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
\r
2731 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
\r
2732 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
\r
2733 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2735 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
\r
2736 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
\r
2737 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2739 qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
\r
2740 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
\r
2741 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2745 qglBegin (GL_LINES);
\r
2747 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
\r
2748 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2750 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2751 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2753 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
\r
2754 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
\r
2757 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
\r
2758 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
\r
2760 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
\r
2761 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
\r
2763 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
\r
2764 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
\r
2768 qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
\r
2769 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
\r
2770 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2772 qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
\r
2773 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
\r
2774 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2776 qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
\r
2777 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
\r
2778 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
\r
2787 #define ALT_POINT_SIZE 4
\r
2788 // Alternative to GL_POINTS (for; vertex handles, patch handles, clip points, path points)
\r
2789 void DrawAlternatePoint(vec3_t v, float scale)
\r
2793 scale = g_pParentWnd->GetXYWnd()->Scale();
\r
2794 //scale = g_qeglobals.d_xyOld.scale;
\r
2797 // ugly gl_line cross
\r
2798 qglVertex3f ( v[0]+(ALT_POINT_SIZE/scale), v[1], v[2] );
\r
2799 qglVertex3f ( v[0]-(ALT_POINT_SIZE/scale), v[1], v[2] );
\r
2800 qglVertex3f ( v[0], v[1]+(ALT_POINT_SIZE/scale), v[2] );
\r
2801 qglVertex3f ( v[0], v[1]-(ALT_POINT_SIZE/scale), v[2] );
\r
2802 qglVertex3f ( v[0], v[1], v[2]+(ALT_POINT_SIZE/scale) );
\r
2803 qglVertex3f ( v[0], v[1], v[2]-(ALT_POINT_SIZE/scale) );
\r
2807 long g_lCount = 0;
\r
2808 long g_lTotal = 0;
\r
2809 extern void DrawBrushEntityName (brush_t *b);
\r
2811 //#define DBG_SCENEDUMP
\r
2813 void XYWnd::XY_Draw()
\r
2815 #ifdef DBG_SCENEDUMP
\r
2816 static time_t s_start = 0; // we use that to dump the selected stuff every 2 seconds
\r
2821 if ((now - s_start) > 3)
\r
2825 Sys_FPrintf(SYS_WRN, "Starting scene dump\n");
\r
2827 else bDump = false;
\r
2833 double start, end;
\r
2834 double start2, end2;
\r
2835 vec3_t mins, maxs;
\r
2836 int drawn, culled;
\r
2839 if (!active_brushes.next)
\r
2840 return; // not valid yet
\r
2842 Patch_LODMatchAll(); // spog
\r
2845 start = Sys_DoubleTime();
\r
2851 qglViewport(0, 0, m_nWidth, m_nHeight);
\r
2852 qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
\r
2853 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
\r
2854 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0);
\r
2856 qglClear(GL_COLOR_BUFFER_BIT);
\r
2859 // set up viewpoint
\r
2861 qglMatrixMode(GL_PROJECTION);
\r
2862 qglLoadIdentity ();
\r
2864 w = m_nWidth / 2 / m_fScale;
\r
2865 h = m_nHeight / 2/ m_fScale;
\r
2867 // fix GL_INVALID_VALUE error on first time the window is updated (win32)
\r
2871 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
\r
2872 int nDim2 = (m_nViewType == XY) ? 1 : 2;
\r
2873 mins[0] = m_vOrigin[nDim1] - w;
\r
2874 maxs[0] = m_vOrigin[nDim1] + w;
\r
2875 mins[1] = m_vOrigin[nDim2] - h;
\r
2876 maxs[1] = m_vOrigin[nDim2] + h;
\r
2878 qglOrtho (mins[0], maxs[0], mins[1], maxs[1], g_MinWorldCoord, g_MaxWorldCoord);
\r
2880 qglMatrixMode(GL_MODELVIEW);
\r
2881 qglLoadIdentity ();
\r
2884 // now draw the grid
\r
2889 // draw block grid
\r
2891 if ( g_qeglobals.show_blocks)
\r
2892 XY_DrawBlockGrid ();
\r
2894 if (m_nViewType != XY)
\r
2897 if (m_nViewType == YZ)
\r
2898 qglRotatef (-90, 0, 1, 0); // put Z going up
\r
2899 qglRotatef (-90, 1, 0, 0); // put Z going up
\r
2905 qglShadeModel (GL_FLAT);
\r
2906 qglDisable(GL_TEXTURE_2D);
\r
2907 qglDisable(GL_TEXTURE_1D);
\r
2908 qglDisable(GL_DEPTH_TEST);
\r
2909 qglDisable(GL_BLEND);
\r
2910 qglDisable(GL_CULL_FACE);
\r
2911 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
\r
2912 qglColor3f(0, 0, 0);
\r
2913 qglEnableClientState(GL_VERTEX_ARRAY);
\r
2915 // Fishman - Add antialiazed points and lines support. 09/15/00
\r
2916 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
\r
2918 qglEnable(GL_BLEND);
\r
2919 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\r
2920 qglEnable(GL_POINT_SMOOTH);
\r
2921 qglEnable(GL_LINE_SMOOTH);
\r
2924 drawn = culled = 0;
\r
2929 start2 = Sys_DoubleTime();
\r
2931 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
\r
2933 if (brush->bFiltered)
\r
2936 if (brush->mins[nDim1] > maxs[0] ||
\r
2937 brush->mins[nDim2] > maxs[1] ||
\r
2938 brush->maxs[nDim1] < mins[0] ||
\r
2939 brush->maxs[nDim2] < mins[1])
\r
2942 continue; // off screen
\r
2947 if (brush->owner != e && brush->owner)
\r
2949 qglColor3fv(brush->owner->eclass->color);
\r
2953 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
\r
2956 #ifdef DBG_SCENEDUMP
\r
2959 Sys_FPrintf(SYS_WRN, "Active brush: %p ", brush);
\r
2960 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
\r
2964 Brush_DrawXY(brush, m_nViewType);
\r
2968 end2 = Sys_DoubleTime();
\r
2975 //++timo why is the display list broken?
\r
2976 if ( g_qeglobals.d_pointfile_display_list)
\r
2980 // now draw selected brushes
\r
2984 qglColor3f(0.8f, 0.1f, 0.9f);
\r
2987 qglColor3f(0.1f, 0.8f, 0.1f);
\r
2989 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
\r
2992 if (g_PrefsDlg.m_bNoStipple == FALSE)
\r
2994 qglEnable (GL_LINE_STIPPLE);
\r
2995 qglLineStipple (3, 0xaaaa);
\r
2999 vec3_t vMinBounds;
\r
3000 vec3_t vMaxBounds;
\r
3001 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = g_MaxWorldCoord;
\r
3002 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = g_MinWorldCoord;
\r
3004 int nSaveDrawn = drawn;
\r
3005 bool bFixedSize = false;
\r
3006 for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
\r
3008 // spog - added culling of selected brushes in XY window
\r
3009 if (brush->mins[nDim1] > maxs[0] ||
\r
3010 brush->mins[nDim2] > maxs[1] ||
\r
3011 brush->maxs[nDim1] < mins[0] ||
\r
3012 brush->maxs[nDim2] < mins[1])
\r
3015 continue; // off screen
\r
3018 #ifdef DBG_SCENEDUMP
\r
3021 Sys_FPrintf(SYS_WRN, "Selected brush: %p ", brush);
\r
3022 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
\r
3025 Brush_DrawXY(brush, m_nViewType);
\r
3029 if (brush->owner->eclass->fixedsize)
\r
3030 bFixedSize = true;
\r
3031 if (g_PrefsDlg.m_bSizePaint)
\r
3033 for (i = 0; i < 3; i ++)
\r
3035 if (brush->mins[i] < vMinBounds[i])
\r
3036 vMinBounds[i] = brush->mins[i];
\r
3037 if (brush->maxs[i] > vMaxBounds[i])
\r
3038 vMaxBounds[i] = brush->maxs[i];
\r
3044 if (g_PrefsDlg.m_bNoStipple == FALSE)
\r
3046 qglDisable (GL_LINE_STIPPLE);
\r
3050 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint)
\r
3051 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
\r
3053 // edge / vertex flags
\r
3054 if (g_qeglobals.d_select_mode == sel_vertex)
\r
3056 if(!g_PrefsDlg.m_bGlPtWorkaround)
\r
3060 qglColor3f (0,1,0);
\r
3061 qglBegin (GL_POINTS);
\r
3062 for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
\r
3063 qglVertex3fv (g_qeglobals.d_points[i]);
\r
3066 if(g_qeglobals.d_num_move_points)
\r
3068 // selected brush verts
\r
3070 qglColor3f (0,0,1);
\r
3071 qglBegin (GL_POINTS);
\r
3072 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
\r
3073 qglVertex3fv (g_qeglobals.d_move_points[i]);
\r
3081 qglColor3f (0,1,0);
\r
3082 qglLineWidth(2.0);
\r
3083 qglBegin (GL_LINES);
\r
3084 for (i=0; i < g_qeglobals.d_numpoints; i++)
\r
3085 DrawAlternatePoint(g_qeglobals.d_points[i], m_fScale);
\r
3088 if(g_qeglobals.d_num_move_points)
\r
3090 // selected brush verts
\r
3091 qglColor3f (0,0,1);
\r
3092 qglLineWidth (3.0);
\r
3093 qglBegin (GL_LINES);
\r
3094 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
\r
3095 qglVertex3fv (g_qeglobals.d_move_points[i]);
\r
3098 qglLineWidth(1.0);
\r
3101 else if (g_qeglobals.d_select_mode == sel_edge)
\r
3104 if(!g_PrefsDlg.m_bGlPtWorkaround)
\r
3107 qglColor3f (0,0,1);
\r
3108 qglBegin (GL_POINTS);
\r
3109 for (i=0 ; i<g_qeglobals.d_numedges ; i++)
\r
3111 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
\r
3112 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
\r
3113 qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
\r
3119 qglColor3f (0,0,1);
\r
3120 qglLineWidth(2.0);
\r
3121 qglBegin (GL_LINES);
\r
3122 for (i=0; i < g_qeglobals.d_numedges; i++)
\r
3124 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
\r
3125 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
\r
3127 v3[0] = (v1[0]+v2[0])*0.5;
\r
3128 v3[1] = (v1[1]+v2[1])*0.5;
\r
3129 v3[2] = (v1[2]+v2[2])*0.5;
\r
3130 DrawAlternatePoint(v3, m_fScale);
\r
3133 qglLineWidth(1.0);
\r
3137 if (!(m_nViewType == XY))
\r
3140 // area selection hack
\r
3141 if ((g_qeglobals.d_select_mode == sel_area || g_qeglobals.d_select_mode == sel_areatall) && (g_nPatchClickedView == ((m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ)))
\r
3143 qglEnable (GL_BLEND);
\r
3144 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
\r
3145 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
\r
3146 qglColor4f(0.0, 0.0, 1.0, 0.25);
\r
3147 qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]);
\r
3148 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
\r
3149 qglDisable (GL_BLEND);
\r
3155 // now draw camera point
\r
3157 DrawCameraIcon ();
\r
3165 // plugin entities
\r
3166 //++timo TODO: use an object for the 2D view
\r
3167 Draw2DPluginEntities( (VIEWTYPE)m_nViewType );
\r
3169 if (g_qeglobals.d_savedinfo.show_outline)
\r
3173 qglMatrixMode (GL_PROJECTION);
\r
3175 qglLoadIdentity ();
\r
3176 qglOrtho (0, m_nWidth, 0, m_nHeight, 0, 1);
\r
3177 qglMatrixMode (GL_MODELVIEW);
\r
3179 qglLoadIdentity ();
\r
3181 // four view mode doesn't colorize
\r
3182 if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit)
\r
3183 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
\r
3185 qglColor3fv( g_qeglobals.d_savedinfo.AxisColors[m_nViewType]);
\r
3186 qglBegin (GL_LINE_LOOP);
\r
3187 qglVertex2i (0, 0);
\r
3188 qglVertex2i (m_nWidth-1, 0);
\r
3189 qglVertex2i (m_nWidth-1, m_nHeight-1);
\r
3190 qglVertex2i (0, m_nHeight-1);
\r
3193 qglMatrixMode (GL_PROJECTION);
\r
3195 qglMatrixMode (GL_MODELVIEW);
\r
3204 end = Sys_DoubleTime ();
\r
3205 i = (int)(1000*(end-start));
\r
3206 int i3 = (int)(1000*(end2-start2));
\r
3209 int i2 = g_lTotal / g_lCount;
\r
3210 Sys_Printf ("xy: %i ab: %i avg: %i\n", i, i3, i2);
\r
3213 // Fishman - Add antialiazed points and lines support. 09/03/00
\r
3214 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
\r
3216 qglDisable(GL_POINT_SMOOTH);
\r
3217 qglDisable(GL_LINE_SMOOTH);
\r
3218 qglDisable(GL_BLEND);
\r
3222 void XYWnd::Copy()
\r
3226 void XYWnd::Undo()
\r
3230 void XYWnd::UndoClear()
\r
3234 void XYWnd::UndoCopy()
\r
3238 bool XYWnd::UndoAvailable()
\r
3240 return (g_brUndo.next != &g_brUndo);
\r
3243 void XYWnd::Paste()
\r
3247 // should be static as should be the rotate scale stuff
\r
3248 bool XYWnd::AreaSelectOK()
\r
3250 return RotateMode() ? false : ScaleMode() ? false : true;
\r
3253 void XYWnd::OnCreate ()
\r
3255 if (!MakeCurrent ())
\r
3256 Error ("glXMakeCurrent failed");
\r
3258 qglPolygonStipple ((unsigned char *)s_stipple);
\r
3259 qglLineStipple (3, 0xaaaa);
\r
3262 void XYWnd::OnExpose ()
\r
3264 bool bPaint = true;
\r
3265 if (!MakeCurrent ())
\r
3267 Sys_Printf("ERROR: glXMakeCurrent failed.. Error:%i\n",qglGetError());
\r
3268 Sys_Printf("Please restart Radiant if the Map view is not working\n");
\r
3273 QE_CheckOpenGLForErrors();
\r
3275 QE_CheckOpenGLForErrors();
\r
3277 if (m_nViewType != XY)
\r
3280 if (m_nViewType == YZ)
\r
3281 qglRotatef (-90, 0, 1, 0); // put Z going up
\r
3282 qglRotatef (-90, 1, 0, 0); // put Z going up
\r
3285 if (g_bCrossHairs)
\r
3287 qglColor4f(0.2f, 0.9f, 0.2f, 0.8f);
\r
3288 qglBegin (GL_LINES);
\r
3289 if (m_nViewType == XY)
\r
3291 qglVertex2f(2*g_MinWorldCoord, tdp[1]);
\r
3292 qglVertex2f(2*g_MaxWorldCoord, tdp[1]);
\r
3293 qglVertex2f(tdp[0], 2*g_MinWorldCoord);
\r
3294 qglVertex2f(tdp[0], 2*g_MaxWorldCoord);
\r
3296 else if (m_nViewType == YZ)
\r
3298 qglVertex3f(tdp[0], 2*g_MinWorldCoord, tdp[2]);
\r
3299 qglVertex3f(tdp[0], 2*g_MaxWorldCoord, tdp[2]);
\r
3300 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
\r
3301 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
\r
3305 qglVertex3f (2*g_MinWorldCoord, tdp[1], tdp[2]);
\r
3306 qglVertex3f (2*g_MaxWorldCoord, tdp[1], tdp[2]);
\r
3307 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
\r
3308 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
\r
3315 // Draw clip points
\r
3316 if (g_Clip1.Set())
\r
3317 g_Clip1.Draw(m_fScale, 1); // qglVertex3fv (g_Clip1);
\r
3318 if (g_Clip2.Set())
\r
3319 g_Clip2.Draw(m_fScale, 2); // qglVertex3fv (g_Clip2);
\r
3320 if (g_Clip3.Set())
\r
3321 g_Clip3.Draw(m_fScale, 3); // qglVertex3fv (g_Clip3);
\r
3322 if (g_Clip1.Set() && g_Clip2.Set())
\r
3324 ProduceSplitLists();
\r
3326 brush_t* pList = (g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
\r
3327 for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next)
\r
3329 qglColor3f (1,1,0);
\r
3332 for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++)
\r
3334 winding_t* w = face->face_winding;
\r
3337 // draw the polygon
\r
3338 qglBegin(GL_LINE_LOOP);
\r
3339 for (int i=0 ; i<w->numpoints ; i++)
\r
3340 qglVertex3fv(w->points[i]);
\r
3350 for (n = 0; n < g_nPathCount; n++)
\r
3351 g_PathPoints[n].Draw(m_fScale, n+1); // qglVertex3fv(g_PathPoints[n]);
\r
3353 if (m_nViewType != XY)
\r
3356 m_XORRectangle.set(rectangle_t());
\r
3361 void XYWnd::KillPathMode()
\r
3363 g_bSmartGo = false;
\r
3364 g_bPathMode = false;
\r
3366 g_pPathFunc(false, g_nPathCount);
\r
3368 g_pPathFunc = NULL;
\r
3369 Sys_UpdateWindows(W_ALL);
\r
3372 // gets called for drop down menu messages
\r
3373 // TIP: it's not always about EntityCreate
\r
3374 void XYWnd::OnEntityCreate (const char* item)
\r
3376 Undo_Start("create entity");
\r
3377 Undo_AddBrushList(&selected_brushes);
\r
3379 if (m_mnuDrop != NULL)
\r
3384 if (strItem.CompareNoCase("Add to...") == 0)
\r
3386 //++timo TODO: fill the menu with current groups?
\r
3387 // this one is for adding to existing groups only
\r
3388 Sys_Printf("TODO: Add to... in XYWnd::OnEntityCreate\n");
\r
3390 else if (strItem.CompareNoCase("Remove") == 0)
\r
3392 // remove selected brushes from their current group
\r
3394 for( b = selected_brushes.next; b != &selected_brushes; b = b->next )
\r
3400 //++timo FIXME: remove when all hooks are in
\r
3401 if (strItem.CompareNoCase("Add to...") == 0
\r
3402 || strItem.CompareNoCase("Remove") == 0
\r
3403 || strItem.CompareNoCase("Name...") == 0
\r
3404 || strItem.CompareNoCase("New group...") == 0)
\r
3406 Sys_Printf("TODO: hook drop down group menu\n");
\r
3410 if (strItem.Find("Smart_") >= 0)
\r
3412 CreateSmartEntity(this, m_ptDownX, m_ptDownY, strItem);
\r
3416 CreateRightClickEntity(this, m_ptDownX, m_ptDownY, (char*)strItem.GetBuffer());
\r
3419 Sys_UpdateWindows(W_ALL);
\r
3420 //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
\r
3422 Undo_EndBrushList(&selected_brushes);
\r
3426 /* Drawing clip points */
\r
3427 void ClipPoint::Draw(float fScale, int num)
\r
3430 strLabel.Format("%d", num);
\r
3431 Draw(fScale, strLabel.GetBuffer());
\r
3434 #define ALT_POINT_VERTS 6
\r
3436 void ClipPoint::Draw(float fScale, const char *label)
\r
3439 if(!g_PrefsDlg.m_bGlPtWorkaround)
\r
3442 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
\r
3443 qglBegin (GL_POINTS);
\r
3444 qglVertex3fv (m_ptClip);
\r
3450 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
\r
3451 qglLineWidth(2.0);
\r
3452 qglBegin (GL_LINES);
\r
3453 DrawAlternatePoint(m_ptClip, fScale);
\r
3455 qglLineWidth(1.0);
\r
3459 qglRasterPos3f (m_ptClip[0]+2, m_ptClip[1]+2, m_ptClip[2]+2);
\r
3460 qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);
\r