2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 // Leonardo Zide (leo@lokigames.com)
30 #include <glib/gi18n.h>
35 #include <gdk/gdkwin32.h>
38 // =============================================================================
44 bool g_bCrossHairs = false;
49 bool g_bRogueClipMode;
54 ClipPoint* g_pMovingClip;
55 brush_t g_brFrontSplits;
56 brush_t g_brBackSplits;
58 brush_t g_brClipboard;
60 entity_t g_enClipboard;
62 vec3_t g_vRotateOrigin;
66 ClipPoint g_PathPoints[256]; // this limit isn't enforced?
67 ClipPoint* g_pMovingPath;
74 ClipPoint g_PointPoints[512];
75 ClipPoint* g_pMovingPoint;
79 const int XY_LEFT = 0x01;
80 const int XY_RIGHT = 0x02;
81 const int XY_UP = 0x04;
82 const int XY_DOWN = 0x08;
84 PFNPathCallback* g_pPathFunc = NULL;
86 static unsigned s_stipple[32] =
88 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
89 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
90 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
91 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
92 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
93 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
94 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
95 0xaaaaaaaa, 0x55555555,0xaaaaaaaa, 0x55555555,
98 void AcquirePath(int nCount, PFNPathCallback* pFunc)
101 g_nPathLimit = nCount;
107 CPtrArray g_ptrMenus;
109 MemStream g_Clipboard(4096);
110 MemStream g_PatchClipboard(4096);
114 extern bool g_bWaitCursor;
118 GtkWidget* XYWnd::m_mnuDrop = NULL;
120 extern int g_nPatchClickedView;
122 // =============================================================================
125 // this is disabled, and broken
126 // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394
131 width = g_pParentWnd->ActiveXY()->Width();
132 height = g_pParentWnd->ActiveXY()->Height();
134 const char* filename;
136 filename = file_dialog (g_pParentWnd->m_pWidget, FALSE, "Save Image", NULL, FILTER_BMP);
140 g_pParentWnd->ActiveXY()->MakeCurrent();
141 img = (unsigned char*)malloc (width*height*3);
142 qglReadPixels (0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,img);
145 fp = fopen(filename, "wb");
149 unsigned long cmap, bfSize;
153 bfSize = 54 + width*height*3;
155 long byteswritten = 0;
156 long pixoff = 54 + cmap*4;
158 char m1 ='B', m2 ='M';
159 fwrite(&m1, 1, 1, fp); byteswritten++; // B
160 fwrite(&m2, 1, 1, fp); byteswritten++; // M
161 fwrite(&bfSize, 4, 1, fp); byteswritten+=4;// bfSize
162 fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved1
163 fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved2
164 fwrite(&pixoff, 4, 1, fp); byteswritten+=4;// bfOffBits
166 unsigned long biSize = 40, compress = 0, size = 0;
168 unsigned short planes = 1;
169 fwrite(&biSize, 4, 1, fp); byteswritten+=4;// biSize
170 fwrite(&width, 4, 1, fp); byteswritten+=4;// biWidth
171 fwrite(&height, 4, 1, fp); byteswritten+=4;// biHeight
172 fwrite(&planes, 2, 1, fp); byteswritten+=2;// biPlanes
173 fwrite(&bits, 2, 1, fp); byteswritten+=2;// biBitCount
174 fwrite(&compress, 4, 1, fp);byteswritten+=4;// biCompression
175 fwrite(&size, 4, 1, fp); byteswritten+=4;// biSizeImage
176 fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biXPelsPerMeter
177 fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biYPelsPerMeter
178 fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrUsed
179 fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrImportant
181 unsigned long widthDW = (((width*24) + 31) / 32 * 4);
182 long row, row_size = width*3;
183 for (row = 0; row < height; row++)
185 unsigned char* buf = img+row*row_size;
189 for (col = 0; col < row_size; col += 3)
191 putc(buf[col+2], fp);
192 putc(buf[col+1], fp);
195 byteswritten += row_size;
198 for (count = row_size; count < widthDW; count++)
200 putc(0, fp); // dummy
212 float ptSum(vec3_t pt)
214 return pt[0] + pt[1] + pt[2];
217 float Betwixt(float f1, float f2)
220 return f2 + ((f1 - f2) / 2);
222 return f1 + ((f2 - f1) / 2);
225 void CleanList(brush_t* pList)
227 brush_t* pBrush = pList->next;
228 while (pBrush != NULL && pBrush != pList)
230 brush_t* pNext = pBrush->next;
236 void Brush_CopyList (brush_t* pFrom, brush_t* pTo)
238 brush_t* pBrush = pFrom->next;
239 while (pBrush != NULL && pBrush != pFrom)
241 brush_t* pNext = pBrush->next;
242 Brush_RemoveFromList(pBrush);
243 Brush_AddToList(pBrush, pTo);
248 float fDiff(float f1, float f2)
257 =============================================================
261 =============================================================
268 Draws connections between entities.
269 Needs to consider all entities, not just ones on screen,
270 because the lines can be visible when neither end is.
271 Called for both camera view and xy view.
274 void DrawPathLines (void)
285 const char *ent_target[MAX_MAP_ENTITIES];
286 entity_t *ent_entity[MAX_MAP_ENTITIES];
288 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
294 for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
296 ent_target[num_entities] = ValueForKey (te, "target");
297 if (ent_target[num_entities][0])
299 ent_entity[num_entities] = te;
304 for (se = entities.next ; se != &entities ; se = se->next)
306 psz = ValueForKey(se, "targetname");
308 if (psz == NULL || psz[0] == '\0')
311 sb = se->brushes.onext;
312 if (sb == &se->brushes)
315 for (k=0 ; k<num_entities ; k++)
317 if (strcmp (ent_target[k], psz))
321 tb = te->brushes.onext;
322 if (tb == &te->brushes)
325 for (i=0 ; i<3 ; i++)
326 mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
328 for (i=0 ; i<3 ; i++)
329 mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
331 VectorSubtract (mid1, mid, dir);
332 len = VectorNormalize (dir, dir);
333 s1[0] = -dir[1]*8 + dir[0]*8;
334 s2[0] = dir[1]*8 + dir[0]*8;
335 s1[1] = dir[0]*8 + dir[1]*8;
336 s2[1] = -dir[0]*8 + dir[1]*8;
338 qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
344 arrows = (int)(len / 256) + 1;
346 for (i=0 ; i<arrows ; i++)
348 f = len * (i + 0.5) / arrows;
350 for (j=0 ; j<3 ; j++)
351 mid1[j] = mid[j] + f*dir[j];
353 qglVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
355 qglVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
363 extern void AssignModel();
365 void CreateEntityFromName(const char* name, const vec3_t origin)
369 if (stricmp(name, "worldspawn") == 0)
371 gtk_MessageBox(g_pParentWnd->m_pWidget, "Can't create an entity with worldspawn.", "info", 0);
376 SetKeyValue(e, "classname", name);
378 if(e->eclass->fixedsize)
381 b = Brush_Create(e->eclass->mins, e->eclass->maxs, &e->eclass->texdef);
382 Entity_LinkBrush(e, b);
383 Brush_AddToList(b, &active_brushes);
385 Brush_Move(b, origin, true);
389 Select_GroupEntity(e);
390 if(e->brushes.onext == &e->brushes)
392 Sys_FPrintf(SYS_ERR, "CreateEntityFromName: selection could not be grouped\n");
398 Entity_AddToList(e, &entities);
403 // tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box
406 if (g_pGameDescription->mGameFile == "hl.game")
408 // FIXME - Hydra: really we need a combined light AND color dialog for halflife.
409 if ((stricmp(name, "light") == 0) ||
410 (stricmp(name, "light_environment") == 0) ||
411 (stricmp(name, "light_spot") == 0) )
413 int intensity = g_PrefsDlg.m_iLastLightIntensity;
415 // Create and show the dialog box
417 // pWnd = prompt.GetDlgItem( IDC_EDIT1 );
418 // prompt.GotoDlgCtrl( pWnd );
419 if (DoLightIntensityDlg (&intensity) == IDOK)
421 g_PrefsDlg.m_iLastLightIntensity = intensity;
423 sprintf( buf, "255 255 255 %d", intensity );
424 SetKeyValue(e, "_light", buf);
430 if (stricmp(name, "light") == 0)
432 int intensity = g_PrefsDlg.m_iLastLightIntensity;
434 // Create and show the dialog box
436 // pWnd = prompt.GetDlgItem( IDC_EDIT1 );
437 // prompt.GotoDlgCtrl( pWnd );
438 if (DoLightIntensityDlg (&intensity) == IDOK)
440 g_PrefsDlg.m_iLastLightIntensity = intensity;
442 sprintf( buf, "%d", intensity );
443 SetKeyValue(e, "light", buf);
447 Select_Brush (e->brushes.onext);
449 if ( (stricmp(name, "misc_model") == 0) || (stricmp(name, "misc_gamemodel") == 0) || (strcmpi(name, "model_static") == 0) )
451 SetInspectorMode(W_ENTITY);
456 void CreateRightClickEntity(XYWnd* pWnd, int x, int y, char* pName)
458 int height = pWnd->GetWidget()->allocation.height;
460 pWnd->SnapToPoint (x, height - 1 - y, point);
462 int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
463 float fWorkMid = (g_qeglobals.d_work_min[nDim] + g_qeglobals.d_work_max[nDim]) * 0.5;
464 point[nDim] = g_qeglobals.d_gridsize * ((int)(fWorkMid/g_qeglobals.d_gridsize));
466 CreateEntityFromName(pName, point);
470 brush_t* CreateSmartBrush(vec3_t v)
476 for (i=0 ; i<3 ; i++)
482 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
486 Brush_AddToList(n, &selected_brushes);
487 //Entity_LinkBrush(world_entity, n);
492 CString g_strSmartEntity;
495 bool g_bSmartWaiting;
496 void _SmartPointDone(bool b, int n)
498 g_bSmartWaiting = false;
501 void CreateSmartEntity(XYWnd* pWnd, int x, int y, const char* pName)
505 g_strSmartEntity = pName;
506 if (g_strSmartEntity.Find("Smart_Train") >= 0)
508 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");
515 if (g_strSmartEntity.Find("Smart_Monster...") >= 0)
522 if (g_strSmartEntity.Find("Smart_Rotating") >= 0)
524 g_bSmartWaiting = true;
525 ShowInfoDialog("Left click to specify the rotation origin");
526 AcquirePath(1, &_SmartPointDone);
527 while (g_bSmartWaiting)
528 gtk_main_iteration ();
531 g_bScreenUpdates = false;
532 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
533 array.Add(reinterpret_cast<void*>(selected_brushes.next));
535 brush_t* pBrush = CreateSmartBrush(g_PathPoints[0]);
538 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(0)));
539 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(1)));
541 g_bScreenUpdates = true;
545 void FinishSmartCreation()
549 // brush_t* pEntities = NULL;
552 if (g_strSmartEntity.Find("Smart_Train") >= 0)
554 g_bScreenUpdates = false;
555 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
556 array.Add(reinterpret_cast<void*>(selected_brushes.next));
557 for (n = 0; n < g_nPathCount; n++)
560 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_PathPoints[n].m_ptScreenX,
561 g_PathPoints[n].m_ptScreenY, "path_corner");
562 array.Add(reinterpret_cast<void*>(selected_brushes.next));
565 for (n = 0; n < g_nPathCount; n++)
568 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n)));
569 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n+1)));
572 g_bScreenUpdates = true;
577 Sys_UpdateWindows(W_ALL);
580 void CleanCopyEntities()
582 entity_t* pe = g_enClipboard.next;
583 while (pe != NULL && pe != &g_enClipboard)
585 entity_t* next = pe->next;
586 epair_t* enext = NULL;
587 for (epair_t* ep = pe->epairs ; ep ; ep=enext)
597 g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
600 entity_t *Entity_CopyClone (entity_t *e)
605 n = (entity_t*)qmalloc(sizeof(*n));
606 n->brushes.onext = n->brushes.oprev = &n->brushes;
607 n->eclass = e->eclass;
609 // add the entity to the entity list
610 n->next = g_enClipboard.next;
611 g_enClipboard.next = n;
613 n->prev = &g_enClipboard;
615 for (ep = e->epairs ; ep ; ep=ep->next)
617 np = (epair_t*)qmalloc(sizeof(*np));
618 np->key = copystring(ep->key);
619 np->value = copystring(ep->value);
620 np->next = n->epairs;
626 bool OnList(entity_t* pFind, CPtrArray* pList)
628 int nSize = pList->GetSize();
631 entity_t* pEntity = reinterpret_cast<entity_t*>(pList->GetAt(nSize));
632 if (pEntity == pFind)
638 // =============================================================================
642 : GLWindow (FALSE), m_XORRectangle(m_pWidget)
644 g_brClipboard.next = &g_brClipboard;
645 g_brUndo.next = &g_brUndo;
647 g_bRotateMode = false;
649 g_bRogueClipMode = false;
651 g_pMovingClip = (ClipPoint*)NULL;
652 g_pMovingPath = (ClipPoint*)NULL;
653 g_brFrontSplits.next = &g_brFrontSplits;
654 g_brBackSplits.next = &g_brBackSplits;
658 m_bRButtonDown = false;
659 m_nUpdateBits = W_XY;
664 // m_mnuDrop = (GtkWidget*)NULL;
668 vec3_t& XYWnd::Rotation()
673 vec3_t& XYWnd::RotateOrigin()
675 return g_vRotateOrigin;
683 void XYWnd::XY_Overlay()
688 static vec3_t lastcamera;
690 qglViewport(0, 0, m_nWidth, m_nHeight);
695 qglMatrixMode(GL_PROJECTION);
698 w = (int)(m_nWidth / 2 / m_fScale);
699 h = (int)(m_nHeight / 2 / m_fScale);
701 qglOrtho (m_vOrigin[0] - w, m_vOrigin[0] + w , m_vOrigin[1] - h, m_vOrigin[1] + h, g_MinWorldCoord, g_MaxWorldCoord);
703 // erase the old camera and z checker positions
704 // if the entire xy hasn't been redrawn
708 qglReadBuffer (GL_BACK);
709 qglDrawBuffer (GL_FRONT);
711 qglRasterPos2f (lastz[0]-9, lastz[1]-9);
712 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
713 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
715 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
716 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
717 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
722 // save off underneath where we are about to draw
724 VectorCopy (z.origin, lastz);
725 VectorCopy (g_pParentWnd->GetCamWnd()->Camera()->origin, lastcamera);
727 qglReadBuffer (GL_FRONT);
728 qglDrawBuffer (GL_BACK);
730 qglRasterPos2f (lastz[0]-9, lastz[1]-9);
731 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
732 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
734 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
735 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
736 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
739 // draw the new icons
741 qglDrawBuffer (GL_FRONT);
743 qglShadeModel (GL_FLAT);
744 qglDisable(GL_TEXTURE_2D);
745 qglDisable(GL_TEXTURE_1D);
746 qglDisable(GL_DEPTH_TEST);
747 qglDisable(GL_BLEND);
753 qglDrawBuffer (GL_BACK);
757 vec3_t& XYWnd::GetOrigin()
762 void XYWnd::SetOrigin(vec3_t org)
764 m_vOrigin[0] = org[0];
765 m_vOrigin[1] = org[1];
766 m_vOrigin[2] = org[2];
769 void XYWnd::OnSize(int cx, int cy)
775 brush_t hold_brushes;
781 hold_brushes.next = &hold_brushes;
784 if (g_PrefsDlg.m_bSwitchClip)
785 pList = (!g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
787 pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
789 if (pList->next != pList)
791 Brush_CopyList(pList, &hold_brushes);
792 CleanList(&g_brFrontSplits);
793 CleanList(&g_brBackSplits);
795 Brush_CopyList(&hold_brushes, &selected_brushes);
797 RetainClipMode(false);
799 RetainClipMode(true);
800 Sys_UpdateWindows(W_ALL);
805 FinishSmartCreation();
807 g_pPathFunc(true, g_nPathCount);
814 void XYWnd::SplitClip()
817 if ((g_brFrontSplits.next != &g_brFrontSplits) &&
818 (g_brBackSplits.next != &g_brBackSplits))
821 Brush_CopyList(&g_brFrontSplits, &selected_brushes);
822 Brush_CopyList(&g_brBackSplits, &selected_brushes);
823 CleanList(&g_brFrontSplits);
824 CleanList(&g_brBackSplits);
826 RetainClipMode(false);
828 RetainClipMode(true);
832 void XYWnd::FlipClip()
834 g_bSwitch = !g_bSwitch;
835 Sys_UpdateWindows(XY | W_CAMERA_IFON);
838 // makes sure the selected brush or camera is in view
839 void XYWnd::PositionView()
841 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
842 int nDim2 = (m_nViewType == XY) ? 1 : 2;
843 brush_t* b = selected_brushes.next;
844 if (b && b->next != b)
846 Select_GetMid (m_vOrigin);
850 m_vOrigin[nDim1] = g_pParentWnd->GetCamWnd()->Camera()->origin[nDim1];
851 m_vOrigin[nDim2] = g_pParentWnd->GetCamWnd()->Camera()->origin[nDim2];
855 void XYWnd::VectorCopyXY(vec3_t in, vec3_t out)
857 if (m_nViewType == XY)
862 else if (m_nViewType == XZ)
874 void XYWnd::RetainClipMode(bool bMode)
876 bool bSave = g_bRogueClipMode;
879 g_bRogueClipMode = bSave;
881 g_bRogueClipMode = false;
884 void XYWnd::SetClipMode(bool bMode)
887 g_bRogueClipMode = false;
893 CleanList(&g_brFrontSplits);
894 CleanList(&g_brBackSplits);
895 g_brFrontSplits.next = &g_brFrontSplits;
896 g_brBackSplits.next = &g_brBackSplits;
898 // ydnar: set clipper points based on first selected patch mesh
899 if( selected_brushes.next != &selected_brushes )
902 for( brush_t *pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next )
907 VectorCopy( pb->pPatch->ctrl[ 0 ][ 0 ].xyz, g_Clip1.m_ptClip );
908 VectorCopy( pb->pPatch->ctrl[ pb->pPatch->width - 1 ][ pb->pPatch->height - 1 ].xyz, g_Clip2.m_ptClip );
909 VectorCopy( pb->pPatch->ctrl[ pb->pPatch->width - 1 ][ 0 ].xyz, g_Clip3.m_ptClip );
919 // SetClipMode( true );
920 Sys_UpdateWindows( XY | W_CAMERA_IFON );
929 g_pMovingClip = NULL;
931 CleanList(&g_brFrontSplits);
932 CleanList(&g_brBackSplits);
933 g_brFrontSplits.next = &g_brFrontSplits;
934 g_brBackSplits.next = &g_brBackSplits;
935 Sys_UpdateWindows(XY | W_CAMERA_IFON);
939 bool XYWnd::ClipMode()
944 bool XYWnd::RogueClipMode()
946 return g_bRogueClipMode;
949 bool XYWnd::PathMode()
954 bool XYWnd::PointMode()
959 void XYWnd::SetPointMode(bool b)
966 void XYWnd::SetViewType(int n)
969 if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
971 char* str = "YZ Side";
972 if (m_nViewType == XY)
974 else if (m_nViewType == XZ)
977 if (m_pParent != NULL)
978 gtk_window_set_title (GTK_WINDOW (m_pParent), str);
982 void XYWnd::Redraw(unsigned int nBits)
984 m_nUpdateBits = nBits;
985 gtk_widget_queue_draw(m_pWidget);
986 m_nUpdateBits = W_XY;
989 bool XYWnd::RotateMode()
991 return g_bRotateMode;
994 bool XYWnd::ScaleMode()
999 bool XYWnd::SetRotateMode(bool bMode)
1001 if (bMode && selected_brushes.next != &selected_brushes)
1003 g_bRotateMode = true;
1004 Select_GetTrueMid(g_vRotateOrigin);
1005 g_vRotation[0] = g_vRotation[1] = g_vRotation[2] = 0.0;
1010 Sys_Printf("Need a brush selected to turn on Mouse Rotation mode\n");
1011 g_bRotateMode = false;
1014 return g_bRotateMode;
1017 void XYWnd::SetScaleMode(bool bMode)
1019 g_bScaleMode = bMode;
1023 rectangle_t rectangle_from_area_xy()
1025 XYWnd* xy = g_pParentWnd->ActiveXY();
1026 int nDim1 = (xy->GetViewType() == YZ) ? 1 : 0;
1027 int nDim2 = (xy->GetViewType() == XY) ? 1 : 2;
1028 float origin_left = xy->GetOrigin()[nDim1] - (xy->Width() / 2) / xy->Scale();
1029 float origin_bottom = xy->GetOrigin()[nDim2] - (xy->Height() / 2) / xy->Scale();
1030 float left = MIN(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1]) - origin_left;
1031 float top = MAX(g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2]) - origin_bottom;
1032 float right = MAX(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1]) - origin_left;
1033 float bottom = MIN(g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2]) - origin_bottom;
1034 left *= xy->Scale();
1036 right *= xy->Scale();
1037 bottom *= xy->Scale();
1038 return rectangle_t(left, bottom, right - left, top - bottom);
1041 void update_xor_rectangle_xy(XORRectangle& xor_rectangle)
1043 rectangle_t rectangle;
1044 if ((g_qeglobals.d_select_mode == sel_area))
1045 rectangle = rectangle_from_area_xy();
1046 xor_rectangle.set(rectangle);
1049 void XYWnd::OnMouseMove(guint32 nFlags, int pointx, int pointy)
1052 // TODO TTimo handle return code
1053 DispatchOnMouseMove (nFlags, pointx, pointy);
1058 if (g_PrefsDlg.m_bChaseMouse == TRUE &&
1059 (pointx < 0 || pointy < 0 || pointx > m_nWidth || pointy > m_nHeight) &&
1062 float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
1069 m_ptDragAdjX = (int)(-fAdjustment);
1071 else if (pointx > m_nWidth)
1073 m_ptDragAdjX = (int)(fAdjustment);
1078 m_ptDragAdjY = (int)(-fAdjustment);
1080 else if (pointy > m_nHeight)
1082 m_ptDragAdjY = (int)(fAdjustment);
1099 pressx -= m_ptDragTotalX;
1100 pressy += m_ptDragTotalY;
1103 bool bCrossHair = false;
1104 if (!m_bRButtonDown)
1106 tdp[0] = tdp[1] = tdp[2] = 0.0;
1107 SnapToPoint (pointx, m_nHeight - 1 - pointy , tdp);
1109 g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]);
1110 g_pParentWnd->SetStatusText(1, g_strStatus);
1112 // i need to generalize the point code.. having 3 flavors pretty much sucks..
1113 // once the new curve stuff looks like it is going to stick i will
1114 // rationalize this down to a single interface..
1117 if (g_pMovingPoint && HasCapture ())
1120 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingPoint->m_ptClip);
1121 g_pMovingPoint->UpdatePointPtr();
1122 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1126 g_pMovingPoint = NULL;
1127 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1128 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1129 for (int n = 0; n < g_nPointCount; n++)
1131 if ( fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1132 fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
1135 g_pMovingPoint = &g_PointPoints[n];
1140 else if (ClipMode())
1142 if (g_pMovingClip && HasCapture ())
1145 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingClip->m_ptClip);
1146 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1150 g_pMovingClip = NULL;
1151 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1152 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1155 if ( fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1156 fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3 )
1159 g_pMovingClip = &g_Clip1;
1164 if ( fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1165 fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3 )
1168 g_pMovingClip = &g_Clip2;
1173 if ( fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1174 fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3 )
1177 g_pMovingClip = &g_Clip3;
1181 if (bCrossHair == false)
1182 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
1184 else if (PathMode())
1186 if (g_pMovingPath && HasCapture ())
1189 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingPath->m_ptClip);
1190 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1194 g_pMovingPath = NULL;
1195 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1196 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1197 for (int n = 0; n < g_nPathCount; n++)
1199 if ( fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1200 fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
1203 g_pMovingPath = &g_PathPoints[n];
1210 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
1215 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
1218 if ((nFlags & MK_RBUTTON) == 0)
1220 if (bCrossHair && !g_bWaitCursor)
1223 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1224 gdk_window_set_cursor (m_pWidget->window, cursor);
1225 gdk_cursor_unref (cursor);
1229 gdk_window_set_cursor (m_pWidget->window, NULL);
1233 update_xor_rectangle_xy(m_XORRectangle);
1236 void XYWnd::OnMouseWheel(bool bUp)
1239 g_pParentWnd->OnViewZoomin ();
1241 g_pParentWnd->OnViewZoomout ();
1243 int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
1244 Sys_UpdateWindows (nUpdate);
1245 g_pParentWnd->OnTimer ();
1248 void XYWnd::OnTimer ()
1250 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1251 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1252 m_vOrigin[nDim1] += m_ptDragAdjX / m_fScale;
1253 m_vOrigin[nDim2] -= m_ptDragAdjY / m_fScale;
1254 Sys_UpdateWindows(W_XY | W_CAMERA);
1255 m_ptDragX += m_ptDragAdjX;
1256 m_ptDragY += m_ptDragAdjY;
1257 m_ptDragTotalX += m_ptDragAdjX;
1258 m_ptDragTotalY += m_ptDragAdjY;
1259 XY_MouseMoved (m_ptDragX, m_nHeight - 1 - m_ptDragY , m_nScrollFlags);
1262 void XYWnd::OnLButtonDown(guint32 flags, int pointx, int pointy)
1264 g_pParentWnd->SetActiveXY(this);
1268 if (DispatchOnLButtonDown(flags, pointx, pointy))
1271 if (ClipMode() && !RogueClipMode())
1273 DropClipPoint(flags, pointx, pointy);
1275 else if (PathMode())
1277 DropPathPoint(flags, pointx, pointy);
1279 else OriginalButtonDown(flags, pointx, pointy);
1282 void XYWnd::OnMButtonDown(guint32 flags, int pointx, int pointy)
1284 OriginalButtonDown(flags, pointx, pointy);
1287 void XYWnd::OnRButtonDown(guint32 flags, int pointx, int pointy)
1289 g_pParentWnd->SetActiveXY(this);
1292 m_bRButtonDown = true;
1294 if (g_PrefsDlg.m_nMouseButtons == 3) // 3 button mouse
1296 if (flags & MK_CONTROL)
1298 if (ClipMode()) // already there?
1299 DropClipPoint(flags, pointx, pointy);
1303 g_bRogueClipMode = true;
1304 DropClipPoint(flags, pointx, pointy);
1309 OriginalButtonDown(flags, pointx, pointy);
1312 void XYWnd::OnLButtonUp(guint32 flags, int pointx, int pointy)
1315 if (DispatchOnLButtonUp(flags, pointx, pointy))
1323 g_pMovingClip = NULL;
1326 OriginalButtonUp(flags, pointx, pointy);
1329 void XYWnd::OnMButtonUp(guint32 flags, int pointx, int pointy)
1331 OriginalButtonUp(flags, pointx, pointy);
1334 void XYWnd::OnRButtonUp(guint32 flags, int pointx, int pointy)
1336 m_bRButtonDown = false;
1337 if ((pointx == m_ptDownX) && (pointy == m_ptDownY)) // mouse didn't move
1342 if (flags & MK_CONTROL)
1344 if (flags & MK_SHIFT)
1349 OriginalButtonUp(flags, pointx, pointy);
1352 void XYWnd::XY_MouseDown (int x, int y, int buttons)
1355 vec3_t origin, dir, right, up;
1357 m_nButtonstate = buttons;
1360 VectorCopy (vec3_origin, m_vPressdelta);
1363 XY_ToPoint (x, y, point);
1365 VectorCopy (point, origin);
1368 if (m_nViewType == XY) // view facing dir = negative Z
1370 origin[2] = g_MaxWorldCoord;
1372 right[0] = 1 / m_fScale;
1376 up[1] = 1 / m_fScale;
1379 else if (m_nViewType == XZ)
1381 origin[1] = g_MinWorldCoord; // view facing dir = positive Y
1383 right[0] = 1 / m_fScale;
1388 up[2] = 1 / m_fScale;
1390 else // if (m_nViewType == YZ) // view facing dir = negative X
1392 origin[0] = g_MaxWorldCoord;
1395 right[1] = 1 / m_fScale;
1399 up[2] = 1 / m_fScale;
1402 m_bPress_selection = (selected_brushes.next != &selected_brushes);
1404 Sys_GetCursorPos(&m_ptCursorX, &m_ptCursorY);
1406 // lbutton = manipulate selection
1407 // shift-LBUTTON = select
1408 if ( (buttons == MK_LBUTTON)
1409 || (buttons == (MK_LBUTTON | MK_SHIFT))
1410 || (buttons == (MK_LBUTTON | MK_CONTROL))
1411 || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
1413 Patch_SetView( (m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
1414 Drag_Begin (x, y, buttons, right, up, origin, dir);
1418 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
1420 // control mbutton = move camera
1421 if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
1423 VectorCopyXY(point, g_pParentWnd->GetCamWnd()->Camera()->origin);
1424 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
1427 // mbutton = angle camera
1428 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
1429 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
1431 VectorSubtract (point, g_pParentWnd->GetCamWnd()->Camera()->origin, point);
1433 int n1 = (m_nViewType == XY) ? 1 : 2;
1434 int n2 = (m_nViewType == YZ) ? 1 : 0;
1435 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
1436 if (point[n1] || point[n2])
1438 g_pParentWnd->GetCamWnd()->Camera()->angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
1439 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
1443 // shift mbutton = move z checker
1444 if (m_nButtonstate == (MK_SHIFT | nMouseButton))
1446 if (RotateMode() || g_bPatchBendMode)
1448 SnapToPoint (x, y, point);
1449 VectorCopyXY(point, g_vRotateOrigin);
1450 if (g_bPatchBendMode)
1452 VectorCopy(point, g_vBendOrigin);
1454 Sys_UpdateWindows (W_XY);
1459 SnapToPoint (x, y, point);
1460 if (m_nViewType == XY)
1462 z.origin[0] = point[0];
1463 z.origin[1] = point[1];
1465 else if (m_nViewType == YZ)
1467 z.origin[0] = point[1];
1468 z.origin[1] = point[2];
1472 z.origin[0] = point[0];
1473 z.origin[1] = point[2];
1475 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
1480 update_xor_rectangle_xy(m_XORRectangle);
1483 void XYWnd::XY_MouseUp(int x, int y, int buttons)
1485 Drag_MouseUp (buttons);
1486 if (!m_bPress_selection)
1487 Sys_UpdateWindows (W_ALL);
1490 gdk_window_set_cursor (m_pWidget->window, NULL);
1492 update_xor_rectangle_xy(m_XORRectangle);
1495 qboolean XYWnd::DragDelta (int x, int y, vec3_t move)
1497 vec3_t xvec, yvec, delta;
1500 xvec[0] = 1 / m_fScale;
1501 xvec[1] = xvec[2] = 0;
1502 yvec[1] = 1 / m_fScale;
1503 yvec[0] = yvec[2] = 0;
1505 for (i=0 ; i<3 ; i++)
1507 delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
1508 if (!g_PrefsDlg.m_bNoClamp)
1510 delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
1513 VectorSubtract (delta, m_vPressdelta, move);
1514 VectorCopy (delta, m_vPressdelta);
1516 if (move[0] || move[1] || move[2])
1521 void XYWnd::HandleDrop()
1523 if (g_PrefsDlg.m_bRightClick == false)
1526 if (m_mnuDrop == NULL) // first time, load it up
1528 int nID = ID_ENTITY_START;
1529 GtkWidget *menu, *menu_in_menu, *item, *submenu, *submenu_root;
1531 menu = m_mnuDrop = gtk_menu_new ();
1533 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Select");
1534 create_menu_item_with_mnemonic (menu_in_menu, "Select Complete Tall",
1535 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTCOMPLETETALL);
1536 create_menu_item_with_mnemonic (menu_in_menu, "Select Touching",
1537 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTTOUCHING);
1538 create_menu_item_with_mnemonic (menu_in_menu, "Select Partial Tall",
1539 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTPARTIALTALL);
1540 create_menu_item_with_mnemonic (menu_in_menu, "Select Inside",
1541 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTINSIDE);
1542 menu_separator (menu); nID++;
1543 // NOTE: temporary commented out until we put it back in for good (that is with actual features)
1545 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Group",);
1546 create_menu_item_with_mnemonic (menu_in_menu, "Add to...",
1547 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_ADDTO);
1548 create_menu_item_with_mnemonic (menu_in_menu, "Remove",
1549 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_REMOVE);
1550 create_menu_item_with_mnemonic (menu_in_menu, "Name...",
1551 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_NAME);
1552 menu_separator (menu_in_menu); nID++;
1553 create_menu_item_with_mnemonic (menu_in_menu, "New Group...",
1554 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_NEWGROUP);
1556 create_menu_item_with_mnemonic (menu, "Ungroup Entity",
1557 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_UNGROUPENTITY);
1559 create_menu_item_with_mnemonic (menu, "Move into entity",
1560 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MERGE);
1561 create_menu_item_with_mnemonic (menu, "Move into worldspawn",
1562 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SEPERATE);
1564 create_menu_item_with_mnemonic (menu, "Make Detail",
1565 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MAKE_DETAIL);
1566 create_menu_item_with_mnemonic (menu, "Make Structural",
1567 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MAKE_STRUCTURAL);
1568 menu_separator (menu); nID++;
1570 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Smart Entities");
1571 create_menu_item_with_mnemonic (menu_in_menu, "Smart__Train",
1572 GTK_SIGNAL_FUNC (HandleCommand), nID++);
1573 menu_separator (menu); nID++;
1576 submenu_root = NULL;
1581 for (e=eclass ; e ; e=e->next)
1585 int n_ = strName.Find("_");
1588 CString strLeft = strName.Left(n_);
1589 CString strRight = strName.Right(strName.GetLength() - n_ - 1);
1590 if (strLeft == strActive) // this is a child
1593 item = gtk_menu_item_new_with_label (strName);
1594 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
1595 GINT_TO_POINTER (nID++));
1596 gtk_widget_show (item);
1597 CheckMenuSplitting(submenu);
1598 gtk_menu_append (GTK_MENU (submenu), item);
1604 // this is submenu from previous main_item, hook it back
1605 // we use submenu_root cause we may have been cascading submenu
1606 item = gtk_menu_item_new_with_label (strActive);
1607 gtk_widget_show (item);
1608 gtk_menu_append (GTK_MENU (menu), item);
1609 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_root);
1610 g_ptrMenus.Add(submenu_root);
1612 submenu_root = NULL;
1614 strActive = strLeft;
1616 submenu = gtk_menu_new ();
1617 submenu_root = submenu;
1618 item = gtk_menu_item_new_with_label (strName);
1619 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
1620 GINT_TO_POINTER (nID++));
1621 gtk_widget_show (item);
1622 gtk_menu_append (GTK_MENU (submenu), item);
1629 // this is submenu from previous main_item, hook it back
1630 // we use submenu_root cause we may have been cascading submenu
1631 item = gtk_menu_item_new_with_label (strActive);
1632 gtk_widget_show (item);
1633 gtk_menu_append (GTK_MENU (menu), item);
1634 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_root);
1635 g_ptrMenus.Add(submenu_root);
1637 submenu_root = NULL;
1641 item = gtk_menu_item_new_with_label (strName);
1642 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
1643 GINT_TO_POINTER (nID++));
1644 gtk_widget_show (item);
1645 gtk_menu_append (GTK_MENU (menu), item);
1650 gtk_menu_popup (GTK_MENU (m_mnuDrop), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
1658 void XYWnd::NewBrushDrag (int x, int y)
1660 vec3_t mins, maxs, junk;
1665 if (!DragDelta (x,y, junk))
1668 // delete the current selection
1669 if (selected_brushes.next != &selected_brushes)
1670 Brush_Free (selected_brushes.next);
1672 SnapToPoint (m_nPressx, m_nPressy, mins);
1674 int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
1677 // mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z / g_qeglobals.d_gridsize));
1678 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_work_min[nDim]/g_qeglobals.d_gridsize));
1680 SnapToPoint (x, y, maxs);
1681 // maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z / g_qeglobals.d_gridsize));
1682 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_work_max[nDim]/g_qeglobals.d_gridsize));
1683 if (maxs[nDim] <= mins[nDim])
1684 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
1686 for (i=0 ; i<3 ; i++)
1688 if (mins[i] == maxs[i])
1689 return; // don't create a degenerate brush
1690 if (mins[i] > maxs[i])
1698 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
1703 VectorSubtract(maxs, mins, vSize);
1704 g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
1705 g_pParentWnd->SetStatusText(2, g_strStatus);
1707 Brush_AddToList (n, &selected_brushes);
1709 Entity_LinkBrush (world_entity, n);
1713 // Sys_UpdateWindows (W_ALL);
1714 Sys_UpdateWindows (W_XY| W_CAMERA);
1723 void XYWnd::XY_MouseMoved (int x, int y, int buttons)
1727 if (!m_nButtonstate)
1731 Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
1736 // lbutton without selection = drag new brush
1737 if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint && g_qeglobals.d_select_mode != sel_areatall)
1739 NewBrushDrag (x, y);
1743 // lbutton (possibly with control and or shift)
1744 // with selection = drag selection
1745 if (m_nButtonstate & MK_LBUTTON)
1747 Drag_MouseMoved (x, y, buttons);
1748 if(g_qeglobals.d_select_mode != sel_area)
1749 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
1753 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
1754 // control mbutton = move camera
1755 if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
1757 SnapToPoint (x, y, point);
1758 VectorCopyXY(point, g_pParentWnd->GetCamWnd()->Camera()->origin);
1759 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
1763 // shift mbutton = move z checker
1764 if (m_nButtonstate == (MK_SHIFT|nMouseButton) )
1766 if (RotateMode() || g_bPatchBendMode)
1768 SnapToPoint (x, y, point);
1769 VectorCopyXY(point, g_vRotateOrigin);
1770 if (g_bPatchBendMode)
1772 VectorCopy(point, g_vBendOrigin);
1774 Sys_UpdateWindows (W_XY);
1779 SnapToPoint (x, y, point);
1780 if (m_nViewType == XY)
1782 z.origin[0] = point[0];
1783 z.origin[1] = point[1];
1785 else if (m_nViewType == YZ)
1787 z.origin[0] = point[1];
1788 z.origin[1] = point[2];
1792 z.origin[0] = point[0];
1793 z.origin[1] = point[2];
1796 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
1800 // mbutton = angle camera
1801 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
1802 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
1804 SnapToPoint (x, y, point);
1805 VectorSubtract (point, g_pParentWnd->GetCamWnd()->Camera()->origin, point);
1807 int n1 = (m_nViewType == XY) ? 1 : 2;
1808 int n2 = (m_nViewType == YZ) ? 1 : 0;
1809 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
1810 if (point[n1] || point[n2])
1812 g_pParentWnd->GetCamWnd()->Camera()->angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
1813 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
1818 // rbutton = drag xy origin
1819 if (m_nButtonstate == MK_RBUTTON)
1821 Sys_GetCursorPos (&x, &y);
1822 if (x != m_ptCursorX || y != m_ptCursorY)
1824 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1825 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1826 m_vOrigin[nDim1] -= (x - m_ptCursorX) / m_fScale;
1827 m_vOrigin[nDim2] += (y - m_ptCursorY) / m_fScale;
1828 Sys_SetCursorPos (m_ptCursorX, m_ptCursorY);
1830 // create an empty cursor
1835 char buffer [(32 * 32)/8];
1836 memset (buffer, 0, (32 * 32)/8);
1837 GdkColor white = {0, 0xffff, 0xffff, 0xffff};
1838 GdkColor black = {0, 0x0000, 0x0000, 0x0000};
1839 pixmap = gdk_bitmap_create_from_data (NULL, buffer, 32, 32);
1840 mask = gdk_bitmap_create_from_data (NULL, buffer, 32, 32);
1841 GdkCursor *cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &white, &black, 1, 1);
1842 gdk_window_set_cursor (m_pWidget->window, cursor);
1843 gdk_cursor_unref (cursor);
1844 gdk_drawable_unref (pixmap);
1845 gdk_drawable_unref (mask);
1848 Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
1854 if (m_nButtonstate == (MK_SHIFT | MK_RBUTTON))
1856 Sys_GetCursorPos (&x, &y);
1857 if (y != m_ptCursorY)
1859 if (abs (m_ptCursorY - y) > 10)
1861 if (m_ptCursorY < y)
1862 g_pParentWnd->OnViewZoomout ();
1864 g_pParentWnd->OnViewZoomin ();
1866 Sys_SetCursorPos (m_ptCursorX, m_ptCursorY);
1873 void XYWnd::OriginalButtonDown(guint32 nFlags, int pointx, int pointy)
1877 XY_MouseDown (pointx, m_pWidget->allocation.height - 1 - pointy , nFlags);
1878 m_nScrollFlags = nFlags;
1881 void XYWnd::OriginalButtonUp(guint32 nFlags, int pointx, int pointy)
1883 XY_MouseUp (pointx, m_pWidget->allocation.height - 1 - pointy , nFlags);
1887 void XYWnd::DropClipPoint(guint32 nFlags, int pointx, int pointy)
1892 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *g_pMovingClip);
1897 if (g_Clip1.Set() == false)
1901 g_Clip1.m_ptScreenX = pointx;
1902 g_Clip1.m_ptScreenY = pointy;
1905 if (g_Clip2.Set() == false)
1909 g_Clip2.m_ptScreenX = pointx;
1910 g_Clip2.m_ptScreenY = pointy;
1913 if (g_Clip3.Set() == false)
1917 g_Clip3.m_ptScreenX = pointx;
1918 g_Clip3.m_ptScreenY = pointy;
1922 RetainClipMode(true);
1925 g_Clip1.m_ptScreenX = pointx;
1926 g_Clip1.m_ptScreenY = pointy;
1928 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *pPt);
1929 // third coordinates for clip point: use d_work_max
1930 // Arnout: changed to use center of selection for clipping, saves level designers moving points all over the map
1931 // g_pParentWnd->ActiveXY()->GetViewType()
1932 // cf VIEWTYPE defintion: enum VIEWTYPE {YZ, XZ, XY};
1933 int nViewType = g_pParentWnd->ActiveXY()->GetViewType();
1934 int nDim = (nViewType == YZ ) ? nDim = 0 : ( (nViewType == XZ) ? nDim = 1 : nDim = 2 );
1935 //(*pPt)[nDim] = g_qeglobals.d_work_max[nDim];
1937 Select_GetMid( mid );
1938 (*pPt)[nDim] = mid[nDim];
1940 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1943 void XYWnd::DropPathPoint(guint32 nFlags, int pointx, int pointy)
1948 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *g_pMovingPath);
1952 g_PathPoints[g_nPathCount].Set(true);
1953 g_PathPoints[g_nPathCount].m_ptScreenX = pointx;
1954 g_PathPoints[g_nPathCount].m_ptScreenY = pointy;
1955 SnapToPoint(pointx, m_pWidget->allocation.height - 1 - pointy, g_PathPoints[g_nPathCount]);
1956 // third coordinates for dropped point: use d_work_max
1957 // g_pParentWnd->ActiveXY()->GetViewType()
1958 // cf VIEWTYPE definition: enum VIEWTYPE {YZ, XZ, XY};
1959 int nViewType = g_pParentWnd->ActiveXY()->GetViewType();
1960 int nDim = (nViewType == YZ ) ? nDim = 0 : ( (nViewType == XZ) ? nDim = 1 : nDim = 2 );
1961 g_PathPoints[g_nPathCount].m_ptClip[nDim] = g_qeglobals.d_work_max[nDim];
1964 if (g_nPathCount == g_nPathLimit)
1967 g_pPathFunc(true, g_nPathCount);
1969 g_bPathMode = false;
1973 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1976 // FIXME: AddPointPoint() redundant function never called
1978 void XYWnd::AddPointPoint(guint32 nFlags, vec3_t* pVec)
1980 g_PointPoints[g_nPointCount].Set(true);
1981 //g_PointPoints[g_nPointCount].m_ptScreen = point;
1982 _VectorCopy(*pVec, g_PointPoints[g_nPointCount]);
1983 g_PointPoints[g_nPointCount].SetPointPtr(pVec);
1985 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1988 // FIXME: ProduceSplits() redundant function never called
1989 void XYWnd::ProduceSplits(brush_t** pFront, brush_t** pBack)
1995 if (g_Clip1.Set() && g_Clip2.Set())
1998 VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
1999 VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
2000 VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
2001 if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes))
2003 if (g_Clip3.Set() == false)
2005 if (m_nViewType == XY)
2007 face.planepts[0][2] = selected_brushes.next->mins[2];
2008 face.planepts[1][2] = selected_brushes.next->mins[2];
2009 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
2010 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
2011 face.planepts[2][2] = selected_brushes.next->maxs[2];
2013 else if (m_nViewType == YZ)
2015 face.planepts[0][0] = selected_brushes.next->mins[0];
2016 face.planepts[1][0] = selected_brushes.next->mins[0];
2017 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
2018 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
2019 face.planepts[2][0] = selected_brushes.next->maxs[0];
2023 face.planepts[0][1] = selected_brushes.next->mins[1];
2024 face.planepts[1][1] = selected_brushes.next->mins[1];
2025 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
2026 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
2027 face.planepts[2][1] = selected_brushes.next->maxs[1];
2031 Brush_SplitBrushByFace (selected_brushes.next, &face, pFront, pBack);
2039 void XYWnd::PlanePointsFromClipPoints(vec3_t planepts[3], brush_t *pBrush)
2041 VectorCopy(g_Clip1.m_ptClip,planepts[0]);
2042 VectorCopy(g_Clip2.m_ptClip,planepts[1]);
2043 VectorCopy(g_Clip3.m_ptClip,planepts[2]);
2044 if (g_Clip3.Set() == false)
2046 int n = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 2 : (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 0 : 1;
2047 int x = (n == 0) ? 1 : 0;
2048 int y = (n == 2) ? 1 : 2;
2050 if (n == 1) // on viewtype XZ, flip clip points
2052 planepts[0][n] = pBrush->maxs[n];
2053 planepts[1][n] = pBrush->maxs[n];
2054 planepts[2][x] = g_Clip1.m_ptClip[x];
2055 planepts[2][y] = g_Clip1.m_ptClip[y];
2056 planepts[2][n] = pBrush->mins[n];
2060 planepts[0][n] = pBrush->mins[n];
2061 planepts[1][n] = pBrush->mins[n];
2062 planepts[2][x] = g_Clip1.m_ptClip[x];
2063 planepts[2][y] = g_Clip1.m_ptClip[y];
2064 planepts[2][n] = pBrush->maxs[n];
2069 void XYWnd::ProduceSplitLists()
2071 bool bCaulk = false;
2074 if (AnyPatchesSelected())
2076 Sys_Printf("Deselecting patches for clip operation.\n");
2078 for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = next)
2083 Brush_RemoveFromList (pb);
2084 Brush_AddToList (pb, &active_brushes);
2085 UpdatePatchInspector();
2088 // ydnar: update the window if any patches are selected
2089 Sys_UpdateWindows( XY | W_CAMERA_IFON );
2092 CleanList(&g_brFrontSplits);
2093 CleanList(&g_brBackSplits);
2094 g_brFrontSplits.next = &g_brFrontSplits;
2095 g_brBackSplits.next = &g_brBackSplits;
2096 if (ClipMode() && (g_Clip1.Set() && g_Clip2.Set()))
2099 for (pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
2101 brush_t* pFront = NULL;
2102 brush_t* pBack = NULL;
2105 memset(&face,0,sizeof(face_t));
2106 PlanePointsFromClipPoints(face.planepts, pBrush);
2108 // decide wether caulking should be applied on the splits
2110 // this should take the first brush face, check shader for NODRAW, if it isn't nodraw then find the appropriate
2111 // 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
2112 // 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
2113 if (g_PrefsDlg.m_bClipCaulk)
2115 nFlags = pBrush->brush_faces->pShader->getFlags();
2116 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
2117 bCaulk = false; // use first face's shader for the splitting face
2119 bCaulk = true; // use caulk
2122 Brush_SplitBrushByFace (pBrush, &face, &pFront, &pBack, bCaulk);
2124 Brush_AddToList(pBack, &g_brBackSplits);
2126 Brush_AddToList(pFront, &g_brFrontSplits);
2132 void XYWnd::XY_Init()
2140 void XYWnd::SnapToPoint (int x, int y, vec3_t point)
2142 if (g_PrefsDlg.m_bNoClamp)
2144 XY_ToPoint(x, y, point);
2148 XY_ToGridPoint(x, y, point);
2152 // TTimo: watch it, this doesn't init one of the 3 coords
2153 void XYWnd::XY_ToPoint (int x, int y, vec3_t point)
2157 float fw = m_nWidth;
2158 float fh = m_nHeight;
2159 if (m_nViewType == XY)
2161 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2162 point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
2164 else if (m_nViewType == YZ)
2166 point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
2167 point[2] = m_vOrigin[2] + (fy - fh / 2 ) / m_fScale;
2171 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2172 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
2176 void XYWnd::XY_ToGridPoint (int x, int y, vec3_t point)
2178 if (m_nViewType == XY)
2180 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2181 point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2182 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2183 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2185 else if (m_nViewType == YZ)
2187 point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
2188 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2189 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2190 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2194 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2195 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2196 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2197 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2202 ============================================================================
2206 ============================================================================
2214 void XYWnd::XY_DrawGrid()
2216 float x, y, xb, xe, yb, ye;
2219 int step, stepx, stepy, colour;
2220 step = stepx = stepy = MAX (64, (int)g_qeglobals.d_gridsize);
2223 int stepSize = (int)(8 / m_fScale);
2224 if (stepSize > step)
2227 for (i = 1; i < stepSize; i <<= 1)
2233 //Sys_Printf("scale: %f\n", m_fScale);
2234 //Sys_Printf("step before: %i\n", step);
2235 //Sys_Printf("scaled step: %f\n", step * m_fScale);
2236 while ((step * m_fScale) < 4.0f) // make sure major grid spacing is at least 4 pixels on the screen
2238 //Sys_Printf("step after: %i\n", step);
2239 while ((stepx * m_fScale) < 32.0f) // text step x must be at least 32
2241 while ((stepy * m_fScale) < 32.0f) // text step y must be at least 32
2244 qglDisable(GL_TEXTURE_2D);
2245 qglDisable(GL_TEXTURE_1D);
2246 qglDisable(GL_DEPTH_TEST);
2247 qglDisable(GL_BLEND);
2249 w = (m_nWidth / 2 / m_fScale);
2250 h = (m_nHeight / 2 / m_fScale);
2252 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2253 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2255 xb = m_vOrigin[nDim1] - w;
2256 if (xb < region_mins[nDim1])
2257 xb = region_mins[nDim1];
2258 xb = step * floor (xb/step);
2260 xe = m_vOrigin[nDim1] + w;
2261 if (xe > region_maxs[nDim1])
2262 xe = region_maxs[nDim1];
2263 xe = step * ceil (xe/step);
2265 yb = m_vOrigin[nDim2] - h;
2266 if (yb < region_mins[nDim2])
2267 yb = region_mins[nDim2];
2268 yb = step * floor (yb/step);
2270 ye = m_vOrigin[nDim2] + h;
2271 if (ye > region_maxs[nDim2])
2272 ye = region_maxs[nDim2];
2273 ye = step * ceil (ye/step);
2275 #define COLORS_DIFFER(a,b) \
2276 (g_qeglobals.d_savedinfo.colors[a][0] != g_qeglobals.d_savedinfo.colors[b][0] || \
2277 g_qeglobals.d_savedinfo.colors[a][1] != g_qeglobals.d_savedinfo.colors[b][1] || \
2278 g_qeglobals.d_savedinfo.colors[a][2] != g_qeglobals.d_savedinfo.colors[b][2])
2281 // draw minor blocks
2282 if (m_fScale > .1 && g_qeglobals.d_showgrid && g_qeglobals.d_gridsize * m_fScale >= 4)
2284 if (g_qeglobals.d_gridsize < 1)
2285 colour = COLOR_GRIDMINOR_ALT;
2287 colour = COLOR_GRIDMINOR;
2289 if (COLORS_DIFFER(colour, COLOR_GRIDBACK))
2291 qglColor3fv(g_qeglobals.d_savedinfo.colors[colour]);
2293 qglBegin (GL_LINES);
2294 for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
2296 if (!((int)x & (step-1)) && !((int)x - x))
2298 qglVertex2f (x, yb);
2299 qglVertex2f (x, ye);
2301 for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
2303 if (!((int)y & (step-1)) && !((int)y - y))
2305 qglVertex2f (xb, y);
2306 qglVertex2f (xe, y);
2312 if(g_qeglobals.d_gridsize < 1)
2313 colour = COLOR_GRIDMAJOR_ALT;
2315 colour = COLOR_GRIDMAJOR;
2317 // draw major blocks
2318 if (COLORS_DIFFER(colour, COLOR_GRIDBACK))
2319 qglColor3fv(g_qeglobals.d_savedinfo.colors[colour]);
2321 if ( g_qeglobals.d_showgrid )
2323 qglBegin (GL_LINES);
2324 for (x=xb ; x<=xe ; x+=step)
2326 qglVertex2f (x, yb);
2327 qglVertex2f (x, ye);
2329 for (y=yb ; y<=ye ; y+=step)
2331 qglVertex2f (xb, y);
2332 qglVertex2f (xe, y);
2337 // draw coordinate text if needed
2338 if ( g_qeglobals.d_savedinfo.show_coordinates)
2340 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]);
2341 float offx = m_vOrigin[nDim2] + h - 6 / m_fScale, offy = m_vOrigin[nDim1] - w + 1 / m_fScale;
2342 for (x=xb-((int)xb)%stepx; x<=xe ; x+=stepx)
2344 qglRasterPos2f (x, offx);
2345 sprintf (text, "%i",(int)x);
2346 gtk_glwidget_print_string(text);
2348 for (y=yb-((int)yb)%stepy; y<=ye ; y+=stepy)
2350 qglRasterPos2f (offy, y);
2351 sprintf (text, "%i",(int)y);
2352 gtk_glwidget_print_string(text);
2356 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
2358 // we do this part (the old way) only if show_axis is disabled
2359 if (!g_qeglobals.d_savedinfo.show_axis)
2361 qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
2364 if (m_nViewType == XY)
2365 strcpy(cView, "XY Top");
2367 if (m_nViewType == XZ)
2368 strcpy(cView, "XZ Front");
2370 strcpy(cView, "YZ Side");
2372 gtk_glwidget_print_string(cView);
2376 if ( g_qeglobals.d_savedinfo.show_axis)
2378 // draw two lines with corresponding axis colors to highlight current view
2379 // horizontal line: nDim1 color
2381 qglBegin( GL_LINES );
2382 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
2383 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2384 qglVertex2f( m_vOrigin[nDim1] - w + 65 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2385 qglVertex2f( 0, 0 );
2386 qglVertex2f( 32 / m_fScale, 0 );
2387 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
2388 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2389 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
2390 qglVertex2f( 0, 0 );
2391 qglVertex2f( 0, 32 / m_fScale );
2394 // now print axis symbols
2395 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
2396 qglRasterPos2f ( m_vOrigin[nDim1] - w + 55 / m_fScale, m_vOrigin[nDim2] + h - 55 / m_fScale );
2397 gtk_glwidget_print_char(g_AxisName[nDim1]);
2398 qglRasterPos2f (28 / m_fScale, -10 / m_fScale );
2399 gtk_glwidget_print_char(g_AxisName[nDim1]);
2400 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
2401 qglRasterPos2f ( m_vOrigin[nDim1] - w + 25 / m_fScale, m_vOrigin[nDim2] + h - 30 / m_fScale );
2402 gtk_glwidget_print_char(g_AxisName[nDim2]);
2403 qglRasterPos2f ( -10 / m_fScale, 28 / m_fScale );
2404 gtk_glwidget_print_char(g_AxisName[nDim2]);
2408 // show current work zone?
2409 // the work zone is used to place dropped points and brushes
2410 if (g_qeglobals.d_show_work)
2412 qglColor3f( 1.0f, 0.0f, 0.0f );
2413 qglBegin( GL_LINES );
2414 qglVertex2f( xb, g_qeglobals.d_work_min[nDim2] );
2415 qglVertex2f( xe, g_qeglobals.d_work_min[nDim2] );
2416 qglVertex2f( xb, g_qeglobals.d_work_max[nDim2] );
2417 qglVertex2f( xe, g_qeglobals.d_work_max[nDim2] );
2418 qglVertex2f( g_qeglobals.d_work_min[nDim1], yb );
2419 qglVertex2f( g_qeglobals.d_work_min[nDim1], ye );
2420 qglVertex2f( g_qeglobals.d_work_max[nDim1], yb );
2421 qglVertex2f( g_qeglobals.d_work_max[nDim1], ye );
2431 void XYWnd::XY_DrawBlockGrid()
2433 const char *value = ValueForKey( world_entity, "_blocksize" );
2435 sscanf( value, "%i", &g_qeglobals.blockSize );
2437 if (!g_qeglobals.blockSize || g_qeglobals.blockSize > 65536 || g_qeglobals.blockSize < 1024)
2438 // don't use custom blocksize if it is less than the default, or greater than the maximum world coordinate
2439 g_qeglobals.blockSize = 1024;
2441 float x, y, xb, xe, yb, ye;
2445 qglDisable(GL_TEXTURE_2D);
2446 qglDisable(GL_TEXTURE_1D);
2447 qglDisable(GL_DEPTH_TEST);
2448 qglDisable(GL_BLEND);
2450 w = (m_nWidth / 2 / m_fScale);
2451 h = (m_nHeight / 2 / m_fScale);
2453 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2454 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2456 xb = m_vOrigin[nDim1] - w;
2457 if (xb < region_mins[nDim1])
2458 xb = region_mins[nDim1];
2459 xb = g_qeglobals.blockSize * floor (xb/g_qeglobals.blockSize);
2461 xe = m_vOrigin[nDim1] + w;
2462 if (xe > region_maxs[nDim1])
2463 xe = region_maxs[nDim1];
2464 xe = g_qeglobals.blockSize * ceil (xe/g_qeglobals.blockSize);
2466 yb = m_vOrigin[nDim2] - h;
2467 if (yb < region_mins[nDim2])
2468 yb = region_mins[nDim2];
2469 yb = g_qeglobals.blockSize * floor (yb/g_qeglobals.blockSize);
2471 ye = m_vOrigin[nDim2] + h;
2472 if (ye > region_maxs[nDim2])
2473 ye = region_maxs[nDim2];
2474 ye = g_qeglobals.blockSize * ceil (ye/g_qeglobals.blockSize);
2476 // draw major blocks
2478 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]);
2481 qglBegin (GL_LINES);
2483 for (x=xb ; x<=xe ; x+=g_qeglobals.blockSize)
2485 qglVertex2f (x, yb);
2486 qglVertex2f (x, ye);
2489 if (m_nViewType == XY)
2491 for (y=yb ; y<=ye ; y+=g_qeglobals.blockSize)
2493 qglVertex2f (xb, y);
2494 qglVertex2f (xe, y);
2501 // draw coordinate text if needed
2503 if (m_nViewType == XY && m_fScale > .1)
2505 for (x=xb ; x<xe ; x+=g_qeglobals.blockSize)
2506 for (y=yb ; y<ye ; y+=g_qeglobals.blockSize)
2508 qglRasterPos2f (x+(g_qeglobals.blockSize/2), y+(g_qeglobals.blockSize/2));
2509 sprintf (text, "%i,%i",(int)floor(x/g_qeglobals.blockSize), (int)floor(y/g_qeglobals.blockSize) );
2510 gtk_glwidget_print_string(text);
2514 qglColor4f(0, 0, 0, 0);
2517 void XYWnd::DrawRotateIcon()
2521 a = 4.0 / m_fScale; // compensate for zoom level
2524 if (m_nViewType == XY)
2526 x = g_vRotateOrigin[0];
2527 y = g_vRotateOrigin[1];
2529 else if (m_nViewType == YZ)
2531 x = g_vRotateOrigin[1];
2532 y = g_vRotateOrigin[2];
2536 x = g_vRotateOrigin[0];
2537 y = g_vRotateOrigin[2];
2540 qglEnable (GL_BLEND);
2541 qglDisable (GL_TEXTURE_2D);
2542 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
2543 qglDisable (GL_CULL_FACE);
2544 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2545 qglColor4f (0.8f, 0.1f, 0.9f, 0.25f);
2548 qglVertex3f (x-a,y-a,0);
2549 qglVertex3f (x+a,y-a,0);
2550 qglVertex3f (x+a,y+a,0);
2551 qglVertex3f (x-a,y+a,0);
2553 qglDisable (GL_BLEND);
2555 qglColor4f (1.0f, 0.2f, 1.0f, 1.f);
2556 qglBegin(GL_POINTS);
2557 qglVertex3f (x,y,0);
2562 qglVertex3f (x-b,y+b,0);
2563 qglVertex3f (x+b,y+b,0);
2564 qglVertex3f (x-b,y-b,0);
2565 qglVertex3f (x+b,y-b,0);
2571 void XYWnd::DrawCameraIcon()
2573 float x, y, a, fov, box;
2575 fov = 48 / m_fScale;
2576 box = 16 / m_fScale;
2578 if (m_nViewType == XY)
2580 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
2581 y = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
2582 a = g_pParentWnd->GetCamWnd()->Camera()->angles[YAW]/180*Q_PI;
2584 else if (m_nViewType == YZ)
2586 x = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
2587 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
2588 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
2592 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
2593 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
2594 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
2597 qglColor3f (0.0, 0.0, 1.0);
2598 qglBegin(GL_LINE_STRIP);
2599 qglVertex3f (x-box,y,0);
2600 qglVertex3f (x,y+(box/2),0);
2601 qglVertex3f (x+box,y,0);
2602 qglVertex3f (x,y-(box/2),0);
2603 qglVertex3f (x-box,y,0);
2604 qglVertex3f (x+box,y,0);
2607 qglBegin(GL_LINE_STRIP);
2608 qglVertex3f (x+fov*cos(a+Q_PI/4), y+fov*sin(a+Q_PI/4), 0);
2609 qglVertex3f (x, y, 0);
2610 qglVertex3f (x+fov*cos(a-Q_PI/4), y+fov*sin(a-Q_PI/4), 0);
2615 void XYWnd::DrawZIcon (void)
2617 if (m_nViewType == XY)
2619 float x = z.origin[0];
2620 float y = z.origin[1];
2621 float zdim = 8 / m_fScale;
2622 qglEnable (GL_BLEND);
2623 qglDisable (GL_TEXTURE_2D);
2624 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
2625 qglDisable (GL_CULL_FACE);
2626 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2627 qglColor4f (0.0, 0.0, 1.0, 0.25);
2629 qglVertex3f (x-zdim,y-zdim,0);
2630 qglVertex3f (x+zdim,y-zdim,0);
2631 qglVertex3f (x+zdim,y+zdim,0);
2632 qglVertex3f (x-zdim,y+zdim,0);
2634 qglDisable (GL_BLEND);
2636 qglColor4f (0.0, 0.0, 1.0, 1);
2638 qglBegin(GL_LINE_LOOP);
2639 qglVertex3f (x-zdim,y-zdim,0);
2640 qglVertex3f (x+zdim,y-zdim,0);
2641 qglVertex3f (x+zdim,y+zdim,0);
2642 qglVertex3f (x-zdim,y+zdim,0);
2645 qglBegin(GL_LINE_STRIP);
2646 qglVertex3f (x-(zdim/2),y+(zdim/2),0);
2647 qglVertex3f (x+(zdim/2),y+(zdim/2),0);
2648 qglVertex3f (x-(zdim/2),y-(zdim/2),0);
2649 qglVertex3f (x+(zdim/2),y-(zdim/2),0);
2654 // can be greatly simplified but per usual i am in a hurry
2655 // which is not an excuse, just a fact
2656 void XYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds)
2658 const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"};
2659 const char* g_pOrgStrings[] = {"(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)"};
2664 VectorSubtract(vMaxBounds, vMinBounds, vSize);
2666 qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
2667 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
2668 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65);
2670 if (m_nViewType == XY)
2672 qglBegin (GL_LINES);
2674 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
2675 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2677 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2678 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2680 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
2681 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2684 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2685 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2687 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2688 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2690 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2691 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2695 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
2696 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2697 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2699 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
2700 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2701 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2703 qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
2704 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
2705 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2707 else if (m_nViewType == XZ)
2709 qglBegin (GL_LINES);
2711 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
2712 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
2714 qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2715 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2717 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale);
2718 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2721 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2]);
2722 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
2724 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
2725 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
2727 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2]);
2728 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
2732 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
2733 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2734 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2736 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
2737 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2738 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2740 qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
2741 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
2742 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2746 qglBegin (GL_LINES);
2748 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
2749 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2751 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2752 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2754 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
2755 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2758 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
2759 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
2761 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
2762 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
2764 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
2765 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
2769 qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
2770 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2771 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2773 qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
2774 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2775 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2777 qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
2778 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
2779 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2788 #define ALT_POINT_SIZE 4
2789 // Alternative to GL_POINTS (for; vertex handles, patch handles, clip points, path points)
2790 void DrawAlternatePoint(vec3_t v, float scale)
2794 scale = g_pParentWnd->GetXYWnd()->Scale();
2795 //scale = g_qeglobals.d_xyOld.scale;
2798 // ugly gl_line cross
2799 qglVertex3f ( v[0]+(ALT_POINT_SIZE/scale), v[1], v[2] );
2800 qglVertex3f ( v[0]-(ALT_POINT_SIZE/scale), v[1], v[2] );
2801 qglVertex3f ( v[0], v[1]+(ALT_POINT_SIZE/scale), v[2] );
2802 qglVertex3f ( v[0], v[1]-(ALT_POINT_SIZE/scale), v[2] );
2803 qglVertex3f ( v[0], v[1], v[2]+(ALT_POINT_SIZE/scale) );
2804 qglVertex3f ( v[0], v[1], v[2]-(ALT_POINT_SIZE/scale) );
2810 extern void DrawBrushEntityName (brush_t *b);
2812 //#define DBG_SCENEDUMP
2814 void XYWnd::XY_Draw()
2816 #ifdef DBG_SCENEDUMP
2817 static time_t s_start = 0; // we use that to dump the selected stuff every 2 seconds
2822 if ((now - s_start) > 3)
2826 Sys_FPrintf(SYS_WRN, "Starting scene dump\n");
2835 double start2, end2;
2840 if (!active_brushes.next)
2841 return; // not valid yet
2843 Patch_LODMatchAll(); // spog
2846 start = Sys_DoubleTime();
2852 qglViewport(0, 0, m_nWidth, m_nHeight);
2853 qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
2854 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
2855 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0);
2857 qglClear(GL_COLOR_BUFFER_BIT);
2862 qglMatrixMode(GL_PROJECTION);
2865 w = m_nWidth / 2 / m_fScale;
2866 h = m_nHeight / 2/ m_fScale;
2868 // fix GL_INVALID_VALUE error on first time the window is updated (win32)
2872 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2873 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2874 mins[0] = m_vOrigin[nDim1] - w;
2875 maxs[0] = m_vOrigin[nDim1] + w;
2876 mins[1] = m_vOrigin[nDim2] - h;
2877 maxs[1] = m_vOrigin[nDim2] + h;
2879 qglOrtho (mins[0], maxs[0], mins[1], maxs[1], g_MinWorldCoord, g_MaxWorldCoord);
2881 qglMatrixMode(GL_MODELVIEW);
2885 // now draw the grid
2892 if ( g_qeglobals.show_blocks)
2893 XY_DrawBlockGrid ();
2895 if (m_nViewType != XY)
2898 if (m_nViewType == YZ)
2899 qglRotatef (-90, 0, 1, 0); // put Z going up
2900 qglRotatef (-90, 1, 0, 0); // put Z going up
2906 qglShadeModel (GL_FLAT);
2907 qglDisable(GL_TEXTURE_2D);
2908 qglDisable(GL_TEXTURE_1D);
2909 qglDisable(GL_DEPTH_TEST);
2910 qglDisable(GL_BLEND);
2911 qglDisable(GL_CULL_FACE);
2912 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
2913 qglColor3f(0, 0, 0);
2914 qglEnableClientState(GL_VERTEX_ARRAY);
2916 // Fishman - Add antialiazed points and lines support. 09/15/00
2917 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
2919 qglEnable(GL_BLEND);
2920 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2921 qglEnable(GL_POINT_SMOOTH);
2922 qglEnable(GL_LINE_SMOOTH);
2930 start2 = Sys_DoubleTime();
2932 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
2934 if (brush->bFiltered)
2937 if (brush->mins[nDim1] > maxs[0] ||
2938 brush->mins[nDim2] > maxs[1] ||
2939 brush->maxs[nDim1] < mins[0] ||
2940 brush->maxs[nDim2] < mins[1])
2943 continue; // off screen
2948 if (brush->owner != e && brush->owner)
2950 qglColor3fv(brush->owner->eclass->color);
2954 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
2957 #ifdef DBG_SCENEDUMP
2960 Sys_FPrintf(SYS_WRN, "Active brush: %p ", brush);
2961 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
2965 Brush_DrawXY(brush, m_nViewType);
2969 end2 = Sys_DoubleTime();
2976 //++timo why is the display list broken?
2977 if ( g_qeglobals.d_pointfile_display_list)
2981 // now draw selected brushes
2985 qglColor3f(0.8f, 0.1f, 0.9f);
2988 qglColor3f(0.1f, 0.8f, 0.1f);
2990 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
2993 if (g_PrefsDlg.m_bNoStipple == FALSE)
2995 qglEnable (GL_LINE_STIPPLE);
2996 qglLineStipple (3, 0xaaaa);
3002 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = g_MaxWorldCoord;
3003 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = g_MinWorldCoord;
3005 int nSaveDrawn = drawn;
3006 bool bFixedSize = false;
3007 for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
3009 // spog - added culling of selected brushes in XY window
3010 if (brush->mins[nDim1] > maxs[0] ||
3011 brush->mins[nDim2] > maxs[1] ||
3012 brush->maxs[nDim1] < mins[0] ||
3013 brush->maxs[nDim2] < mins[1])
3016 continue; // off screen
3019 #ifdef DBG_SCENEDUMP
3022 Sys_FPrintf(SYS_WRN, "Selected brush: %p ", brush);
3023 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
3026 Brush_DrawXY(brush, m_nViewType);
3030 if (brush->owner->eclass->fixedsize)
3032 if (g_PrefsDlg.m_bSizePaint)
3034 for (i = 0; i < 3; i ++)
3036 if (brush->mins[i] < vMinBounds[i])
3037 vMinBounds[i] = brush->mins[i];
3038 if (brush->maxs[i] > vMaxBounds[i])
3039 vMaxBounds[i] = brush->maxs[i];
3045 if (g_PrefsDlg.m_bNoStipple == FALSE)
3047 qglDisable (GL_LINE_STIPPLE);
3051 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint)
3052 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
3054 // edge / vertex flags
3055 if (g_qeglobals.d_select_mode == sel_vertex)
3057 if(!g_PrefsDlg.m_bGlPtWorkaround)
3062 qglBegin (GL_POINTS);
3063 for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
3064 qglVertex3fv (g_qeglobals.d_points[i]);
3067 if(g_qeglobals.d_num_move_points)
3069 // selected brush verts
3072 qglBegin (GL_POINTS);
3073 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
3074 qglVertex3fv (g_qeglobals.d_move_points[i]);
3084 qglBegin (GL_LINES);
3085 for (i=0; i < g_qeglobals.d_numpoints; i++)
3086 DrawAlternatePoint(g_qeglobals.d_points[i], m_fScale);
3089 if(g_qeglobals.d_num_move_points)
3091 // selected brush verts
3094 qglBegin (GL_LINES);
3095 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
3096 qglVertex3fv (g_qeglobals.d_move_points[i]);
3102 else if (g_qeglobals.d_select_mode == sel_edge)
3105 if(!g_PrefsDlg.m_bGlPtWorkaround)
3109 qglBegin (GL_POINTS);
3110 for (i=0 ; i<g_qeglobals.d_numedges ; i++)
3112 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
3113 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
3114 qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
3122 qglBegin (GL_LINES);
3123 for (i=0; i < g_qeglobals.d_numedges; i++)
3125 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
3126 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
3128 v3[0] = (v1[0]+v2[0])*0.5;
3129 v3[1] = (v1[1]+v2[1])*0.5;
3130 v3[2] = (v1[2]+v2[2])*0.5;
3131 DrawAlternatePoint(v3, m_fScale);
3138 if (!(m_nViewType == XY))
3141 // area selection hack
3142 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)))
3144 qglEnable (GL_BLEND);
3145 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
3146 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3147 qglColor4f(0.0, 0.0, 1.0, 0.25);
3148 qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]);
3149 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
3150 qglDisable (GL_BLEND);
3156 // now draw camera point
3167 //++timo TODO: use an object for the 2D view
3168 Draw2DPluginEntities( (VIEWTYPE)m_nViewType );
3170 if (g_qeglobals.d_savedinfo.show_outline)
3174 qglMatrixMode (GL_PROJECTION);
3177 qglOrtho (0, m_nWidth, 0, m_nHeight, 0, 1);
3178 qglMatrixMode (GL_MODELVIEW);
3182 // four view mode doesn't colorize
3183 if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit)
3184 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
3186 qglColor3fv( g_qeglobals.d_savedinfo.AxisColors[m_nViewType]);
3187 qglBegin (GL_LINE_LOOP);
3189 qglVertex2i (m_nWidth-1, 0);
3190 qglVertex2i (m_nWidth-1, m_nHeight-1);
3191 qglVertex2i (0, m_nHeight-1);
3194 qglMatrixMode (GL_PROJECTION);
3196 qglMatrixMode (GL_MODELVIEW);
3205 end = Sys_DoubleTime ();
3206 i = (int)(1000*(end-start));
3207 int i3 = (int)(1000*(end2-start2));
3210 int i2 = g_lTotal / g_lCount;
3211 Sys_Printf ("xy: %i ab: %i avg: %i\n", i, i3, i2);
3214 // Fishman - Add antialiazed points and lines support. 09/03/00
3215 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
3217 qglDisable(GL_POINT_SMOOTH);
3218 qglDisable(GL_LINE_SMOOTH);
3219 qglDisable(GL_BLEND);
3231 void XYWnd::UndoClear()
3235 void XYWnd::UndoCopy()
3239 bool XYWnd::UndoAvailable()
3241 return (g_brUndo.next != &g_brUndo);
3248 // should be static as should be the rotate scale stuff
3249 bool XYWnd::AreaSelectOK()
3251 return RotateMode() ? false : ScaleMode() ? false : true;
3254 void XYWnd::OnCreate ()
3256 if (!MakeCurrent ())
3257 Error ("glXMakeCurrent failed");
3259 qglPolygonStipple ((unsigned char *)s_stipple);
3260 qglLineStipple (3, 0xaaaa);
3263 void XYWnd::OnExpose ()
3266 if (!MakeCurrent ())
3268 Sys_Printf("ERROR: glXMakeCurrent failed.. Error:%i\n",qglGetError());
3269 Sys_Printf("Please restart Radiant if the Map view is not working\n");
3274 QE_CheckOpenGLForErrors();
3276 QE_CheckOpenGLForErrors();
3278 if (m_nViewType != XY)
3281 if (m_nViewType == YZ)
3282 qglRotatef (-90, 0, 1, 0); // put Z going up
3283 qglRotatef (-90, 1, 0, 0); // put Z going up
3288 qglColor4f(0.2f, 0.9f, 0.2f, 0.8f);
3289 qglBegin (GL_LINES);
3290 if (m_nViewType == XY)
3292 qglVertex2f(2*g_MinWorldCoord, tdp[1]);
3293 qglVertex2f(2*g_MaxWorldCoord, tdp[1]);
3294 qglVertex2f(tdp[0], 2*g_MinWorldCoord);
3295 qglVertex2f(tdp[0], 2*g_MaxWorldCoord);
3297 else if (m_nViewType == YZ)
3299 qglVertex3f(tdp[0], 2*g_MinWorldCoord, tdp[2]);
3300 qglVertex3f(tdp[0], 2*g_MaxWorldCoord, tdp[2]);
3301 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
3302 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
3306 qglVertex3f (2*g_MinWorldCoord, tdp[1], tdp[2]);
3307 qglVertex3f (2*g_MaxWorldCoord, tdp[1], tdp[2]);
3308 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
3309 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
3318 g_Clip1.Draw(m_fScale, 1); // qglVertex3fv (g_Clip1);
3320 g_Clip2.Draw(m_fScale, 2); // qglVertex3fv (g_Clip2);
3322 g_Clip3.Draw(m_fScale, 3); // qglVertex3fv (g_Clip3);
3323 if (g_Clip1.Set() && g_Clip2.Set())
3325 ProduceSplitLists();
3327 brush_t* pList = (g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
3328 for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next)
3333 for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++)
3335 winding_t* w = face->face_winding;
3339 qglBegin(GL_LINE_LOOP);
3340 for (int i=0 ; i<w->numpoints ; i++)
3341 qglVertex3fv(w->points[i]);
3351 for (n = 0; n < g_nPathCount; n++)
3352 g_PathPoints[n].Draw(m_fScale, n+1); // qglVertex3fv(g_PathPoints[n]);
3354 if (m_nViewType != XY)
3357 m_XORRectangle.set(rectangle_t());
3362 void XYWnd::KillPathMode()
3365 g_bPathMode = false;
3367 g_pPathFunc(false, g_nPathCount);
3370 Sys_UpdateWindows(W_ALL);
3373 // gets called for drop down menu messages
3374 // TIP: it's not always about EntityCreate
3375 void XYWnd::OnEntityCreate (const char* item)
3377 Undo_Start("create entity");
3378 Undo_AddBrushList(&selected_brushes);
3380 if (m_mnuDrop != NULL)
3385 if (strItem.CompareNoCase("Add to...") == 0)
3387 //++timo TODO: fill the menu with current groups?
3388 // this one is for adding to existing groups only
3389 Sys_Printf("TODO: Add to... in XYWnd::OnEntityCreate\n");
3391 else if (strItem.CompareNoCase("Remove") == 0)
3393 // remove selected brushes from their current group
3395 for( b = selected_brushes.next; b != &selected_brushes; b = b->next )
3401 //++timo FIXME: remove when all hooks are in
3402 if (strItem.CompareNoCase("Add to...") == 0
3403 || strItem.CompareNoCase("Remove") == 0
3404 || strItem.CompareNoCase("Name...") == 0
3405 || strItem.CompareNoCase("New group...") == 0)
3407 Sys_Printf("TODO: hook drop down group menu\n");
3411 if (strItem.Find("Smart_") >= 0)
3413 CreateSmartEntity(this, m_ptDownX, m_ptDownY, strItem);
3417 CreateRightClickEntity(this, m_ptDownX, m_ptDownY, (char*)strItem.GetBuffer());
3420 Sys_UpdateWindows(W_ALL);
3421 //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
3423 Undo_EndBrushList(&selected_brushes);
3427 /* Drawing clip points */
3428 void ClipPoint::Draw(float fScale, int num)
3431 strLabel.Format("%d", num);
3432 Draw(fScale, strLabel.GetBuffer());
3435 #define ALT_POINT_VERTS 6
3437 void ClipPoint::Draw(float fScale, const char *label)
3440 if(!g_PrefsDlg.m_bGlPtWorkaround)
3443 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
3444 qglBegin (GL_POINTS);
3445 qglVertex3fv (m_ptClip);
3451 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
3453 qglBegin (GL_LINES);
3454 DrawAlternatePoint(m_ptClip, fScale);
3460 qglRasterPos3f (m_ptClip[0]+2, m_ptClip[1]+2, m_ptClip[2]+2);
3461 qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);