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 // =============================================================================
128 const long width = g_pParentWnd->ActiveXY()->Width();
129 const long height = g_pParentWnd->ActiveXY()->Height();
131 const char* filename;
133 filename = file_dialog (g_pParentWnd->m_pWidget, FALSE, _("Save BMP Image"), NULL, "bmp");
137 g_pParentWnd->ActiveXY()->MakeCurrent();
138 img = (unsigned char*)malloc (width*height*3);
139 qglReadPixels (0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,img);
142 fp = fopen(filename, "wb");
146 unsigned long cmap, bfSize;
150 bfSize = 54 + width*height*3;
152 long byteswritten = 0;
153 long pixoff = 54 + cmap*4;
155 char m1 ='B', m2 ='M';
156 fwrite(&m1, 1, 1, fp); byteswritten++; // B
157 fwrite(&m2, 1, 1, fp); byteswritten++; // M
158 fwrite(&bfSize, 4, 1, fp); byteswritten+=4;// bfSize
159 fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved1
160 fwrite(&res, 2, 1, fp); byteswritten+=2;// bfReserved2
161 fwrite(&pixoff, 4, 1, fp); byteswritten+=4;// bfOffBits
163 unsigned long biSize = 40, compress = 0, size = 0;
165 unsigned short planes = 1;
166 fwrite(&biSize, 4, 1, fp); byteswritten+=4;// biSize
167 fwrite(&width, 4, 1, fp); byteswritten+=4;// biWidth
168 fwrite(&height, 4, 1, fp); byteswritten+=4;// biHeight
169 fwrite(&planes, 2, 1, fp); byteswritten+=2;// biPlanes
170 fwrite(&bits, 2, 1, fp); byteswritten+=2;// biBitCount
171 fwrite(&compress, 4, 1, fp);byteswritten+=4;// biCompression
172 fwrite(&size, 4, 1, fp); byteswritten+=4;// biSizeImage
173 fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biXPelsPerMeter
174 fwrite(&pixels, 4, 1, fp); byteswritten+=4;// biYPelsPerMeter
175 fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrUsed
176 fwrite(&cmap, 4, 1, fp); byteswritten+=4;// biClrImportant
178 unsigned long widthDW = (((width*24) + 31) / 32 * 4);
179 long row, row_size = width*3;
180 for (row = 0; row < height; row++)
182 unsigned char* buf = img+row*row_size;
186 for (col = 0; col < row_size; col += 3)
188 putc(buf[col+2], fp);
189 putc(buf[col+1], fp);
192 byteswritten += row_size;
195 for (count = row_size; count < widthDW; count++)
197 putc(0, fp); // dummy
208 float ptSum(vec3_t pt)
210 return pt[0] + pt[1] + pt[2];
213 float Betwixt(float f1, float f2)
216 return f2 + ((f1 - f2) / 2);
218 return f1 + ((f2 - f1) / 2);
221 void CleanList(brush_t* pList)
223 brush_t* pBrush = pList->next;
224 while (pBrush != NULL && pBrush != pList)
226 brush_t* pNext = pBrush->next;
232 void Brush_CopyList (brush_t* pFrom, brush_t* pTo)
234 brush_t* pBrush = pFrom->next;
235 while (pBrush != NULL && pBrush != pFrom)
237 brush_t* pNext = pBrush->next;
238 Brush_RemoveFromList(pBrush);
239 Brush_AddToList(pBrush, pTo);
244 float fDiff(float f1, float f2)
253 =============================================================
257 =============================================================
264 Draws connections between entities.
265 Needs to consider all entities, not just ones on screen,
266 because the lines can be visible when neither end is.
267 Called for both camera view and xy view.
270 void DrawPathLines (void)
281 const char *ent_target[MAX_MAP_ENTITIES];
282 entity_t *ent_entity[MAX_MAP_ENTITIES];
284 if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
290 for (te = entities.next ; te != &entities && num_entities != MAX_MAP_ENTITIES ; te = te->next)
292 ent_target[num_entities] = ValueForKey (te, "target");
293 if (ent_target[num_entities][0])
295 ent_entity[num_entities] = te;
300 for (se = entities.next ; se != &entities ; se = se->next)
302 psz = ValueForKey(se, "targetname");
304 if (psz == NULL || psz[0] == '\0')
307 sb = se->brushes.onext;
308 if (sb == &se->brushes)
311 for (k=0 ; k<num_entities ; k++)
313 if (strcmp (ent_target[k], psz))
317 tb = te->brushes.onext;
318 if (tb == &te->brushes)
321 for (i=0 ; i<3 ; i++)
322 mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
324 for (i=0 ; i<3 ; i++)
325 mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
327 VectorSubtract (mid1, mid, dir);
328 len = VectorNormalize (dir, dir);
329 s1[0] = -dir[1]*8 + dir[0]*8;
330 s2[0] = dir[1]*8 + dir[0]*8;
331 s1[1] = dir[0]*8 + dir[1]*8;
332 s2[1] = -dir[0]*8 + dir[1]*8;
334 qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
340 arrows = (int)(len / 256) + 1;
342 for (i=0 ; i<arrows ; i++)
344 f = len * (i + 0.5) / arrows;
346 for (j=0 ; j<3 ; j++)
347 mid1[j] = mid[j] + f*dir[j];
349 qglVertex3f (mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
351 qglVertex3f (mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
359 extern void AssignModel();
361 void CreateEntityFromName(const char* name, const vec3_t origin)
365 if (stricmp(name, "worldspawn") == 0)
367 gtk_MessageBox(g_pParentWnd->m_pWidget, "Can't create an entity with worldspawn.", "info", 0);
372 SetKeyValue(e, "classname", name);
374 if(e->eclass->fixedsize)
377 b = Brush_Create(e->eclass->mins, e->eclass->maxs, &e->eclass->texdef);
378 Entity_LinkBrush(e, b);
379 Brush_AddToList(b, &active_brushes);
381 Brush_Move(b, origin, true);
385 Select_GroupEntity(e);
386 if(e->brushes.onext == &e->brushes)
388 Sys_FPrintf(SYS_ERR, "CreateEntityFromName: selection could not be grouped\n");
394 Entity_AddToList(e, &entities);
399 // tweaking: when right clic dropping a light entity, ask for light value in a custom dialog box
402 if (g_pGameDescription->mGameFile == "hl.game")
404 // FIXME - Hydra: really we need a combined light AND color dialog for halflife.
405 if ((stricmp(name, "light") == 0) ||
406 (stricmp(name, "light_environment") == 0) ||
407 (stricmp(name, "light_spot") == 0) )
409 int intensity = g_PrefsDlg.m_iLastLightIntensity;
411 // Create and show the dialog box
413 // pWnd = prompt.GetDlgItem( IDC_EDIT1 );
414 // prompt.GotoDlgCtrl( pWnd );
415 if (DoLightIntensityDlg (&intensity) == IDOK)
417 g_PrefsDlg.m_iLastLightIntensity = intensity;
419 sprintf( buf, "255 255 255 %d", intensity );
420 SetKeyValue(e, "_light", buf);
426 if (stricmp(name, "light") == 0)
428 int intensity = g_PrefsDlg.m_iLastLightIntensity;
430 // Create and show the dialog box
432 // pWnd = prompt.GetDlgItem( IDC_EDIT1 );
433 // prompt.GotoDlgCtrl( pWnd );
434 if (DoLightIntensityDlg (&intensity) == IDOK)
436 g_PrefsDlg.m_iLastLightIntensity = intensity;
438 sprintf( buf, "%d", intensity );
439 SetKeyValue(e, "light", buf);
443 Select_Brush (e->brushes.onext);
445 if ( (stricmp(name, "misc_model") == 0) || (stricmp(name, "misc_gamemodel") == 0) || (strcmpi(name, "model_static") == 0) )
447 SetInspectorMode(W_ENTITY);
452 void CreateRightClickEntity(XYWnd* pWnd, int x, int y, char* pName)
454 int height = pWnd->GetWidget()->allocation.height;
456 pWnd->SnapToPoint (x, height - 1 - y, point);
458 int nDim = (pWnd->GetViewType() == XY) ? 2 : (pWnd->GetViewType() == YZ) ? 0 : 1;
459 float fWorkMid = (g_qeglobals.d_work_min[nDim] + g_qeglobals.d_work_max[nDim]) * 0.5;
460 point[nDim] = g_qeglobals.d_gridsize * ((int)(fWorkMid/g_qeglobals.d_gridsize));
462 CreateEntityFromName(pName, point);
466 brush_t* CreateSmartBrush(vec3_t v)
472 for (i=0 ; i<3 ; i++)
478 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
482 Brush_AddToList(n, &selected_brushes);
483 //Entity_LinkBrush(world_entity, n);
488 CString g_strSmartEntity;
491 bool g_bSmartWaiting;
492 void _SmartPointDone(bool b, int n)
494 g_bSmartWaiting = false;
497 void CreateSmartEntity(XYWnd* pWnd, int x, int y, const char* pName)
501 g_strSmartEntity = pName;
502 if (g_strSmartEntity.Find("Smart_Train") >= 0)
504 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");
511 if (g_strSmartEntity.Find("Smart_Monster...") >= 0)
518 if (g_strSmartEntity.Find("Smart_Rotating") >= 0)
520 g_bSmartWaiting = true;
521 ShowInfoDialog("Left click to specify the rotation origin");
522 AcquirePath(1, &_SmartPointDone);
523 while (g_bSmartWaiting)
524 gtk_main_iteration ();
527 g_bScreenUpdates = false;
528 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_rotating");
529 array.Add(reinterpret_cast<void*>(selected_brushes.next));
531 brush_t* pBrush = CreateSmartBrush(g_PathPoints[0]);
534 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(0)));
535 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(1)));
537 g_bScreenUpdates = true;
541 void FinishSmartCreation()
545 // brush_t* pEntities = NULL;
548 if (g_strSmartEntity.Find("Smart_Train") >= 0)
550 g_bScreenUpdates = false;
551 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_nSmartX, g_nSmartY, "func_train");
552 array.Add(reinterpret_cast<void*>(selected_brushes.next));
553 for (n = 0; n < g_nPathCount; n++)
556 CreateRightClickEntity(g_pParentWnd->ActiveXY(), g_PathPoints[n].m_ptScreenX,
557 g_PathPoints[n].m_ptScreenY, "path_corner");
558 array.Add(reinterpret_cast<void*>(selected_brushes.next));
561 for (n = 0; n < g_nPathCount; n++)
564 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n)));
565 Select_Brush(reinterpret_cast<brush_t*>(array.GetAt(n+1)));
568 g_bScreenUpdates = true;
573 Sys_UpdateWindows(W_ALL);
576 void CleanCopyEntities()
578 entity_t* pe = g_enClipboard.next;
579 while (pe != NULL && pe != &g_enClipboard)
581 entity_t* next = pe->next;
582 epair_t* enext = NULL;
583 for (epair_t* ep = pe->epairs ; ep ; ep=enext)
593 g_enClipboard.next = g_enClipboard.prev = &g_enClipboard;
596 entity_t *Entity_CopyClone (entity_t *e)
601 n = (entity_t*)qmalloc(sizeof(*n));
602 n->brushes.onext = n->brushes.oprev = &n->brushes;
603 n->eclass = e->eclass;
605 // add the entity to the entity list
606 n->next = g_enClipboard.next;
607 g_enClipboard.next = n;
609 n->prev = &g_enClipboard;
611 for (ep = e->epairs ; ep ; ep=ep->next)
613 np = (epair_t*)qmalloc(sizeof(*np));
614 np->key = copystring(ep->key);
615 np->value = copystring(ep->value);
616 np->next = n->epairs;
622 bool OnList(entity_t* pFind, CPtrArray* pList)
624 int nSize = pList->GetSize();
627 entity_t* pEntity = reinterpret_cast<entity_t*>(pList->GetAt(nSize));
628 if (pEntity == pFind)
634 // =============================================================================
638 : GLWindow (FALSE), m_XORRectangle(m_pWidget)
640 g_brClipboard.next = &g_brClipboard;
641 g_brUndo.next = &g_brUndo;
643 g_bRotateMode = false;
645 g_bRogueClipMode = false;
647 g_pMovingClip = (ClipPoint*)NULL;
648 g_pMovingPath = (ClipPoint*)NULL;
649 g_brFrontSplits.next = &g_brFrontSplits;
650 g_brBackSplits.next = &g_brBackSplits;
654 m_bRButtonDown = false;
655 m_nUpdateBits = W_XY;
660 // m_mnuDrop = (GtkWidget*)NULL;
664 vec3_t& XYWnd::Rotation()
669 vec3_t& XYWnd::RotateOrigin()
671 return g_vRotateOrigin;
679 void XYWnd::XY_Overlay()
684 static vec3_t lastcamera;
686 qglViewport(0, 0, m_nWidth, m_nHeight);
691 qglMatrixMode(GL_PROJECTION);
694 w = (int)(m_nWidth / 2 / m_fScale);
695 h = (int)(m_nHeight / 2 / m_fScale);
697 qglOrtho (m_vOrigin[0] - w, m_vOrigin[0] + w , m_vOrigin[1] - h, m_vOrigin[1] + h, g_MinWorldCoord, g_MaxWorldCoord);
699 // erase the old camera and z checker positions
700 // if the entire xy hasn't been redrawn
704 qglReadBuffer (GL_BACK);
705 qglDrawBuffer (GL_FRONT);
707 qglRasterPos2f (lastz[0]-9, lastz[1]-9);
708 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
709 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
711 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
712 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
713 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
718 // save off underneath where we are about to draw
720 VectorCopy (z.origin, lastz);
721 VectorCopy (g_pParentWnd->GetCamWnd()->Camera()->origin, lastcamera);
723 qglReadBuffer (GL_FRONT);
724 qglDrawBuffer (GL_BACK);
726 qglRasterPos2f (lastz[0]-9, lastz[1]-9);
727 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
728 qglCopyPixels(r[0], r[1], 18,18, GL_COLOR);
730 qglRasterPos2f (lastcamera[0]-50, lastcamera[1]-50);
731 qglGetIntegerv (GL_CURRENT_RASTER_POSITION,r);
732 qglCopyPixels(r[0], r[1], 100,100, GL_COLOR);
735 // draw the new icons
737 qglDrawBuffer (GL_FRONT);
739 qglShadeModel (GL_FLAT);
740 qglDisable(GL_TEXTURE_2D);
741 qglDisable(GL_TEXTURE_1D);
742 qglDisable(GL_DEPTH_TEST);
743 qglDisable(GL_BLEND);
749 qglDrawBuffer (GL_BACK);
753 vec3_t& XYWnd::GetOrigin()
758 void XYWnd::SetOrigin(vec3_t org)
760 m_vOrigin[0] = org[0];
761 m_vOrigin[1] = org[1];
762 m_vOrigin[2] = org[2];
765 void XYWnd::OnSize(int cx, int cy)
771 brush_t hold_brushes;
777 hold_brushes.next = &hold_brushes;
780 if (g_PrefsDlg.m_bSwitchClip)
781 pList = (!g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
783 pList = (g_bSwitch) ? &g_brFrontSplits : &g_brBackSplits;
785 if (pList->next != pList)
787 Brush_CopyList(pList, &hold_brushes);
788 CleanList(&g_brFrontSplits);
789 CleanList(&g_brBackSplits);
791 Brush_CopyList(&hold_brushes, &selected_brushes);
793 RetainClipMode(false);
795 RetainClipMode(true);
796 Sys_UpdateWindows(W_ALL);
801 FinishSmartCreation();
803 g_pPathFunc(true, g_nPathCount);
810 void XYWnd::SplitClip()
813 if ((g_brFrontSplits.next != &g_brFrontSplits) &&
814 (g_brBackSplits.next != &g_brBackSplits))
817 Brush_CopyList(&g_brFrontSplits, &selected_brushes);
818 Brush_CopyList(&g_brBackSplits, &selected_brushes);
819 CleanList(&g_brFrontSplits);
820 CleanList(&g_brBackSplits);
822 RetainClipMode(false);
824 RetainClipMode(true);
828 void XYWnd::FlipClip()
830 g_bSwitch = !g_bSwitch;
831 Sys_UpdateWindows(XY | W_CAMERA_IFON);
834 // makes sure the selected brush or camera is in view
835 void XYWnd::PositionView()
837 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
838 int nDim2 = (m_nViewType == XY) ? 1 : 2;
839 brush_t* b = selected_brushes.next;
840 if (b && b->next != b)
842 Select_GetMid (m_vOrigin);
846 m_vOrigin[nDim1] = g_pParentWnd->GetCamWnd()->Camera()->origin[nDim1];
847 m_vOrigin[nDim2] = g_pParentWnd->GetCamWnd()->Camera()->origin[nDim2];
851 void XYWnd::VectorCopyXY(vec3_t in, vec3_t out)
853 if (m_nViewType == XY)
858 else if (m_nViewType == XZ)
870 void XYWnd::RetainClipMode(bool bMode)
872 bool bSave = g_bRogueClipMode;
875 g_bRogueClipMode = bSave;
877 g_bRogueClipMode = false;
880 void XYWnd::SetClipMode(bool bMode)
883 g_bRogueClipMode = false;
889 CleanList(&g_brFrontSplits);
890 CleanList(&g_brBackSplits);
891 g_brFrontSplits.next = &g_brFrontSplits;
892 g_brBackSplits.next = &g_brBackSplits;
894 // ydnar: set clipper points based on first selected patch mesh
895 if( selected_brushes.next != &selected_brushes )
898 for( brush_t *pb = selected_brushes.next; pb != &selected_brushes; pb = pb->next )
903 VectorCopy( pb->pPatch->ctrl[ 0 ][ 0 ].xyz, g_Clip1.m_ptClip );
904 VectorCopy( pb->pPatch->ctrl[ pb->pPatch->width - 1 ][ pb->pPatch->height - 1 ].xyz, g_Clip2.m_ptClip );
905 VectorCopy( pb->pPatch->ctrl[ pb->pPatch->width - 1 ][ 0 ].xyz, g_Clip3.m_ptClip );
915 // SetClipMode( true );
916 Sys_UpdateWindows( XY | W_CAMERA_IFON );
925 g_pMovingClip = NULL;
927 CleanList(&g_brFrontSplits);
928 CleanList(&g_brBackSplits);
929 g_brFrontSplits.next = &g_brFrontSplits;
930 g_brBackSplits.next = &g_brBackSplits;
931 Sys_UpdateWindows(XY | W_CAMERA_IFON);
935 bool XYWnd::ClipMode()
940 bool XYWnd::RogueClipMode()
942 return g_bRogueClipMode;
945 bool XYWnd::PathMode()
950 bool XYWnd::PointMode()
955 void XYWnd::SetPointMode(bool b)
962 void XYWnd::SetViewType(int n)
965 if (g_pParentWnd->CurrentStyle() == MainFrame::eFloating)
967 char* str = "YZ Side";
968 if (m_nViewType == XY)
970 else if (m_nViewType == XZ)
973 if (m_pParent != NULL)
974 gtk_window_set_title (GTK_WINDOW (m_pParent), str);
978 void XYWnd::Redraw(unsigned int nBits)
980 m_nUpdateBits = nBits;
981 gtk_widget_queue_draw(m_pWidget);
982 m_nUpdateBits = W_XY;
985 bool XYWnd::RotateMode()
987 return g_bRotateMode;
990 bool XYWnd::ScaleMode()
995 bool XYWnd::SetRotateMode(bool bMode)
997 if (bMode && selected_brushes.next != &selected_brushes)
999 g_bRotateMode = true;
1000 Select_GetTrueMid(g_vRotateOrigin);
1001 g_vRotation[0] = g_vRotation[1] = g_vRotation[2] = 0.0;
1006 Sys_Printf("Need a brush selected to turn on Mouse Rotation mode\n");
1007 g_bRotateMode = false;
1010 return g_bRotateMode;
1013 void XYWnd::SetScaleMode(bool bMode)
1015 g_bScaleMode = bMode;
1019 rectangle_t rectangle_from_area_xy()
1021 XYWnd* xy = g_pParentWnd->ActiveXY();
1022 int nDim1 = (xy->GetViewType() == YZ) ? 1 : 0;
1023 int nDim2 = (xy->GetViewType() == XY) ? 1 : 2;
1024 float origin_left = xy->GetOrigin()[nDim1] - (xy->Width() / 2) / xy->Scale();
1025 float origin_bottom = xy->GetOrigin()[nDim2] - (xy->Height() / 2) / xy->Scale();
1026 float left = MIN(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1]) - origin_left;
1027 float top = MAX(g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2]) - origin_bottom;
1028 float right = MAX(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaBR[nDim1]) - origin_left;
1029 float bottom = MIN(g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim2]) - origin_bottom;
1030 left *= xy->Scale();
1032 right *= xy->Scale();
1033 bottom *= xy->Scale();
1034 return rectangle_t(left, bottom, right - left, top - bottom);
1037 void update_xor_rectangle_xy(XORRectangle& xor_rectangle)
1039 rectangle_t rectangle;
1040 if ((g_qeglobals.d_select_mode == sel_area))
1041 rectangle = rectangle_from_area_xy();
1042 xor_rectangle.set(rectangle);
1045 void XYWnd::OnMouseMove(guint32 nFlags, int pointx, int pointy)
1048 // TODO TTimo handle return code
1049 DispatchOnMouseMove (nFlags, pointx, pointy);
1054 if (g_PrefsDlg.m_bChaseMouse == TRUE &&
1055 (pointx < 0 || pointy < 0 || pointx > m_nWidth || pointy > m_nHeight) &&
1058 float fAdjustment = (g_qeglobals.d_gridsize / 8 * 64) / m_fScale;
1065 m_ptDragAdjX = (int)(-fAdjustment);
1067 else if (pointx > m_nWidth)
1069 m_ptDragAdjX = (int)(fAdjustment);
1074 m_ptDragAdjY = (int)(-fAdjustment);
1076 else if (pointy > m_nHeight)
1078 m_ptDragAdjY = (int)(fAdjustment);
1095 pressx -= m_ptDragTotalX;
1096 pressy += m_ptDragTotalY;
1099 bool bCrossHair = false;
1100 if (!m_bRButtonDown)
1102 tdp[0] = tdp[1] = tdp[2] = 0.0;
1103 SnapToPoint (pointx, m_nHeight - 1 - pointy , tdp);
1105 g_strStatus.Format("x:: %.1f y:: %.1f z:: %.1f", tdp[0], tdp[1], tdp[2]);
1106 g_pParentWnd->SetStatusText(1, g_strStatus);
1108 // i need to generalize the point code.. having 3 flavors pretty much sucks..
1109 // once the new curve stuff looks like it is going to stick i will
1110 // rationalize this down to a single interface..
1113 if (g_pMovingPoint && HasCapture ())
1116 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingPoint->m_ptClip);
1117 g_pMovingPoint->UpdatePointPtr();
1118 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1122 g_pMovingPoint = NULL;
1123 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1124 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1125 for (int n = 0; n < g_nPointCount; n++)
1127 if ( fDiff(g_PointPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1128 fDiff(g_PointPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
1131 g_pMovingPoint = &g_PointPoints[n];
1136 else if (ClipMode())
1138 if (g_pMovingClip && HasCapture ())
1141 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingClip->m_ptClip);
1142 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1146 g_pMovingClip = NULL;
1147 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1148 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1151 if ( fDiff(g_Clip1.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1152 fDiff(g_Clip1.m_ptClip[nDim2], tdp[nDim2]) < 3 )
1155 g_pMovingClip = &g_Clip1;
1160 if ( fDiff(g_Clip2.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1161 fDiff(g_Clip2.m_ptClip[nDim2], tdp[nDim2]) < 3 )
1164 g_pMovingClip = &g_Clip2;
1169 if ( fDiff(g_Clip3.m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1170 fDiff(g_Clip3.m_ptClip[nDim2], tdp[nDim2]) < 3 )
1173 g_pMovingClip = &g_Clip3;
1177 if (bCrossHair == false)
1178 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
1180 else if (PathMode())
1182 if (g_pMovingPath && HasCapture ())
1185 SnapToPoint (pointx, m_nHeight - 1 - pointy , g_pMovingPath->m_ptClip);
1186 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1190 g_pMovingPath = NULL;
1191 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1192 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1193 for (int n = 0; n < g_nPathCount; n++)
1195 if ( fDiff(g_PathPoints[n].m_ptClip[nDim1], tdp[nDim1]) < 3 &&
1196 fDiff(g_PathPoints[n].m_ptClip[nDim2], tdp[nDim2]) < 3 )
1199 g_pMovingPath = &g_PathPoints[n];
1206 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
1211 XY_MouseMoved (pointx, m_nHeight - 1 - pointy , nFlags);
1214 if ((nFlags & MK_RBUTTON) == 0)
1216 if (bCrossHair && !g_bWaitCursor)
1219 cursor = gdk_cursor_new (GDK_CROSSHAIR);
1220 gdk_window_set_cursor (m_pWidget->window, cursor);
1221 gdk_cursor_unref (cursor);
1225 gdk_window_set_cursor (m_pWidget->window, NULL);
1229 update_xor_rectangle_xy(m_XORRectangle);
1232 void XYWnd::OnMouseWheel(bool bUp)
1235 g_pParentWnd->OnViewZoomin ();
1237 g_pParentWnd->OnViewZoomout ();
1239 int nUpdate = (g_PrefsDlg.m_bCamXYUpdate) ? (W_CAMERA | W_XY) : (W_CAMERA);
1240 Sys_UpdateWindows (nUpdate);
1241 g_pParentWnd->OnTimer ();
1244 void XYWnd::OnTimer ()
1246 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1247 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1248 m_vOrigin[nDim1] += m_ptDragAdjX / m_fScale;
1249 m_vOrigin[nDim2] -= m_ptDragAdjY / m_fScale;
1250 Sys_UpdateWindows(W_XY | W_CAMERA);
1251 m_ptDragX += m_ptDragAdjX;
1252 m_ptDragY += m_ptDragAdjY;
1253 m_ptDragTotalX += m_ptDragAdjX;
1254 m_ptDragTotalY += m_ptDragAdjY;
1255 XY_MouseMoved (m_ptDragX, m_nHeight - 1 - m_ptDragY , m_nScrollFlags);
1258 void XYWnd::OnLButtonDown(guint32 flags, int pointx, int pointy)
1260 g_pParentWnd->SetActiveXY(this);
1264 if (DispatchOnLButtonDown(flags, pointx, pointy))
1267 if (ClipMode() && !RogueClipMode())
1269 DropClipPoint(flags, pointx, pointy);
1271 else if (PathMode())
1273 DropPathPoint(flags, pointx, pointy);
1275 else OriginalButtonDown(flags, pointx, pointy);
1278 void XYWnd::OnMButtonDown(guint32 flags, int pointx, int pointy)
1280 OriginalButtonDown(flags, pointx, pointy);
1283 void XYWnd::OnRButtonDown(guint32 flags, int pointx, int pointy)
1285 g_pParentWnd->SetActiveXY(this);
1288 m_bRButtonDown = true;
1290 if (g_PrefsDlg.m_nMouseButtons == 3) // 3 button mouse
1292 if (flags & MK_CONTROL)
1294 if (ClipMode()) // already there?
1295 DropClipPoint(flags, pointx, pointy);
1299 g_bRogueClipMode = true;
1300 DropClipPoint(flags, pointx, pointy);
1305 OriginalButtonDown(flags, pointx, pointy);
1308 void XYWnd::OnLButtonUp(guint32 flags, int pointx, int pointy)
1311 if (DispatchOnLButtonUp(flags, pointx, pointy))
1319 g_pMovingClip = NULL;
1322 OriginalButtonUp(flags, pointx, pointy);
1325 void XYWnd::OnMButtonUp(guint32 flags, int pointx, int pointy)
1327 OriginalButtonUp(flags, pointx, pointy);
1330 void XYWnd::OnRButtonUp(guint32 flags, int pointx, int pointy)
1332 m_bRButtonDown = false;
1333 if ((pointx == m_ptDownX) && (pointy == m_ptDownY)) // mouse didn't move
1338 if (flags & MK_CONTROL)
1340 if (flags & MK_SHIFT)
1345 OriginalButtonUp(flags, pointx, pointy);
1348 void XYWnd::XY_MouseDown (int x, int y, int buttons)
1351 vec3_t origin, dir, right, up;
1353 m_nButtonstate = buttons;
1356 VectorCopy (vec3_origin, m_vPressdelta);
1359 XY_ToPoint (x, y, point);
1361 VectorCopy (point, origin);
1364 if (m_nViewType == XY) // view facing dir = negative Z
1366 origin[2] = g_MaxWorldCoord;
1368 right[0] = 1 / m_fScale;
1372 up[1] = 1 / m_fScale;
1375 else if (m_nViewType == XZ)
1377 origin[1] = g_MinWorldCoord; // view facing dir = positive Y
1379 right[0] = 1 / m_fScale;
1384 up[2] = 1 / m_fScale;
1386 else // if (m_nViewType == YZ) // view facing dir = negative X
1388 origin[0] = g_MaxWorldCoord;
1391 right[1] = 1 / m_fScale;
1395 up[2] = 1 / m_fScale;
1398 m_bPress_selection = (selected_brushes.next != &selected_brushes);
1400 Sys_GetCursorPos(&m_ptCursorX, &m_ptCursorY);
1402 // lbutton = manipulate selection
1403 // shift-LBUTTON = select
1404 if ( (buttons == MK_LBUTTON)
1405 || (buttons == (MK_LBUTTON | MK_SHIFT))
1406 || (buttons == (MK_LBUTTON | MK_CONTROL))
1407 || (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) )
1409 Patch_SetView( (m_nViewType == XY) ? W_XY : (m_nViewType == YZ) ? W_YZ : W_XZ);
1410 Drag_Begin (x, y, buttons, right, up, origin, dir);
1414 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
1416 // control mbutton = move camera
1417 if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
1419 VectorCopyXY(point, g_pParentWnd->GetCamWnd()->Camera()->origin);
1420 Sys_UpdateWindows (W_CAMERA|W_XY_OVERLAY);
1423 // mbutton = angle camera
1424 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
1425 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
1427 VectorSubtract (point, g_pParentWnd->GetCamWnd()->Camera()->origin, point);
1429 int n1 = (m_nViewType == XY) ? 1 : 2;
1430 int n2 = (m_nViewType == YZ) ? 1 : 0;
1431 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
1432 if (point[n1] || point[n2])
1434 g_pParentWnd->GetCamWnd()->Camera()->angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
1435 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
1439 // shift mbutton = move z checker
1440 if (m_nButtonstate == (MK_SHIFT | nMouseButton))
1442 if (RotateMode() || g_bPatchBendMode)
1444 SnapToPoint (x, y, point);
1445 VectorCopyXY(point, g_vRotateOrigin);
1446 if (g_bPatchBendMode)
1448 VectorCopy(point, g_vBendOrigin);
1450 Sys_UpdateWindows (W_XY);
1455 SnapToPoint (x, y, point);
1456 if (m_nViewType == XY)
1458 z.origin[0] = point[0];
1459 z.origin[1] = point[1];
1461 else if (m_nViewType == YZ)
1463 z.origin[0] = point[1];
1464 z.origin[1] = point[2];
1468 z.origin[0] = point[0];
1469 z.origin[1] = point[2];
1471 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
1476 update_xor_rectangle_xy(m_XORRectangle);
1479 void XYWnd::XY_MouseUp(int x, int y, int buttons)
1481 Drag_MouseUp (buttons);
1482 if (!m_bPress_selection)
1483 Sys_UpdateWindows (W_ALL);
1486 gdk_window_set_cursor (m_pWidget->window, NULL);
1488 update_xor_rectangle_xy(m_XORRectangle);
1491 qboolean XYWnd::DragDelta (int x, int y, vec3_t move)
1493 vec3_t xvec, yvec, delta;
1496 xvec[0] = 1 / m_fScale;
1497 xvec[1] = xvec[2] = 0;
1498 yvec[1] = 1 / m_fScale;
1499 yvec[0] = yvec[2] = 0;
1501 for (i=0 ; i<3 ; i++)
1503 delta[i] = xvec[i] * (x - m_nPressx) + yvec[i] * (y - m_nPressy);
1504 if (g_PrefsDlg.m_bSnap)
1506 delta[i] = floor(delta[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
1509 VectorSubtract (delta, m_vPressdelta, move);
1510 VectorCopy (delta, m_vPressdelta);
1512 if (move[0] || move[1] || move[2])
1517 void XYWnd::HandleDrop()
1519 if (g_PrefsDlg.m_bRightClick == false)
1522 if (m_mnuDrop == NULL) // first time, load it up
1524 int nID = ID_ENTITY_START;
1525 GtkWidget *menu, *menu_in_menu, *item, *submenu, *submenu_root;
1527 menu = m_mnuDrop = gtk_menu_new ();
1529 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Select");
1530 create_menu_item_with_mnemonic (menu_in_menu, "Select Complete Tall",
1531 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTCOMPLETETALL);
1532 create_menu_item_with_mnemonic (menu_in_menu, "Select Touching",
1533 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTTOUCHING);
1534 create_menu_item_with_mnemonic (menu_in_menu, "Select Partial Tall",
1535 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTPARTIALTALL);
1536 create_menu_item_with_mnemonic (menu_in_menu, "Select Inside",
1537 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SELECTINSIDE);
1538 menu_separator (menu); nID++;
1539 // NOTE: temporary commented out until we put it back in for good (that is with actual features)
1541 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Group",);
1542 create_menu_item_with_mnemonic (menu_in_menu, "Add to...",
1543 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_ADDTO);
1544 create_menu_item_with_mnemonic (menu_in_menu, "Remove",
1545 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_REMOVE);
1546 create_menu_item_with_mnemonic (menu_in_menu, "Name...",
1547 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_NAME);
1548 menu_separator (menu_in_menu); nID++;
1549 create_menu_item_with_mnemonic (menu_in_menu, "New Group...",
1550 GTK_SIGNAL_FUNC (HandleCommand), ID_DROP_GROUP_NEWGROUP);
1552 create_menu_item_with_mnemonic (menu, "Ungroup Entity",
1553 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_UNGROUPENTITY);
1555 create_menu_item_with_mnemonic (menu, "Move into entity",
1556 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MERGE);
1557 create_menu_item_with_mnemonic (menu, "Move into worldspawn",
1558 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_SEPERATE);
1560 create_menu_item_with_mnemonic (menu, "Make Detail",
1561 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MAKE_DETAIL);
1562 create_menu_item_with_mnemonic (menu, "Make Structural",
1563 GTK_SIGNAL_FUNC (HandleCommand), ID_SELECTION_MAKE_STRUCTURAL);
1564 menu_separator (menu); nID++;
1566 menu_in_menu = create_menu_in_menu_with_mnemonic (menu, "Smart Entities");
1567 create_menu_item_with_mnemonic (menu_in_menu, "Smart__Train",
1568 GTK_SIGNAL_FUNC (HandleCommand), nID++);
1569 menu_separator (menu); nID++;
1572 submenu_root = NULL;
1577 for (e=eclass ; e ; e=e->next)
1581 int n_ = strName.Find("_");
1584 CString strLeft = strName.Left(n_);
1585 CString strRight = strName.Right(strName.GetLength() - n_ - 1);
1586 if (strLeft == strActive) // this is a child
1589 item = gtk_menu_item_new_with_label (strName);
1590 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
1591 GINT_TO_POINTER (nID++));
1592 gtk_widget_show (item);
1593 CheckMenuSplitting(submenu);
1594 gtk_menu_append (GTK_MENU (submenu), item);
1600 // this is submenu from previous main_item, hook it back
1601 // we use submenu_root cause we may have been cascading submenu
1602 item = gtk_menu_item_new_with_label (strActive);
1603 gtk_widget_show (item);
1604 gtk_menu_append (GTK_MENU (menu), item);
1605 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_root);
1606 g_ptrMenus.Add(submenu_root);
1608 submenu_root = NULL;
1610 strActive = strLeft;
1612 submenu = gtk_menu_new ();
1613 submenu_root = submenu;
1614 item = gtk_menu_item_new_with_label (strName);
1615 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
1616 GINT_TO_POINTER (nID++));
1617 gtk_widget_show (item);
1618 gtk_menu_append (GTK_MENU (submenu), item);
1625 // this is submenu from previous main_item, hook it back
1626 // we use submenu_root cause we may have been cascading submenu
1627 item = gtk_menu_item_new_with_label (strActive);
1628 gtk_widget_show (item);
1629 gtk_menu_append (GTK_MENU (menu), item);
1630 gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu_root);
1631 g_ptrMenus.Add(submenu_root);
1633 submenu_root = NULL;
1637 item = gtk_menu_item_new_with_label (strName);
1638 gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (HandleCommand),
1639 GINT_TO_POINTER (nID++));
1640 gtk_widget_show (item);
1641 gtk_menu_append (GTK_MENU (menu), item);
1646 gtk_menu_popup (GTK_MENU (m_mnuDrop), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
1654 void XYWnd::NewBrushDrag (int x, int y)
1656 vec3_t mins, maxs, junk;
1661 if (!DragDelta (x,y, junk))
1664 // delete the current selection
1665 if (selected_brushes.next != &selected_brushes)
1666 Brush_Free (selected_brushes.next);
1668 SnapToPoint (m_nPressx, m_nPressy, mins);
1670 int nDim = (m_nViewType == XY) ? 2 : (m_nViewType == YZ) ? 0 : 1;
1673 // mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z / g_qeglobals.d_gridsize));
1674 mins[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_work_min[nDim]/g_qeglobals.d_gridsize));
1676 SnapToPoint (x, y, maxs);
1677 // maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z / g_qeglobals.d_gridsize));
1678 maxs[nDim] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_work_max[nDim]/g_qeglobals.d_gridsize));
1679 if (maxs[nDim] <= mins[nDim])
1680 maxs[nDim] = mins[nDim] + g_qeglobals.d_gridsize;
1682 for (i=0 ; i<3 ; i++)
1684 if (mins[i] == maxs[i])
1685 return; // don't create a degenerate brush
1686 if (mins[i] > maxs[i])
1694 n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
1699 VectorSubtract(maxs, mins, vSize);
1700 g_strStatus.Format("Size X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]);
1701 g_pParentWnd->SetStatusText(2, g_strStatus);
1703 Brush_AddToList (n, &selected_brushes);
1705 Entity_LinkBrush (world_entity, n);
1709 // Sys_UpdateWindows (W_ALL);
1710 Sys_UpdateWindows (W_XY| W_CAMERA);
1719 void XYWnd::XY_MouseMoved (int x, int y, int buttons)
1723 if (!m_nButtonstate)
1727 Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
1732 // lbutton without selection = drag new brush
1733 if (m_nButtonstate == MK_LBUTTON && !m_bPress_selection && g_qeglobals.d_select_mode != sel_curvepoint && g_qeglobals.d_select_mode != sel_areatall)
1735 NewBrushDrag (x, y);
1739 // lbutton (possibly with control and or shift)
1740 // with selection = drag selection
1741 if (m_nButtonstate & MK_LBUTTON)
1743 Drag_MouseMoved (x, y, buttons);
1744 if(g_qeglobals.d_select_mode != sel_area)
1745 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA_IFON | W_Z);
1749 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
1750 // control mbutton = move camera
1751 if (m_nButtonstate == (MK_CONTROL|nMouseButton) )
1753 SnapToPoint (x, y, point);
1754 VectorCopyXY(point, g_pParentWnd->GetCamWnd()->Camera()->origin);
1755 Sys_UpdateWindows (W_XY_OVERLAY | W_CAMERA);
1759 // shift mbutton = move z checker
1760 if (m_nButtonstate == (MK_SHIFT|nMouseButton) )
1762 if (RotateMode() || g_bPatchBendMode)
1764 SnapToPoint (x, y, point);
1765 VectorCopyXY(point, g_vRotateOrigin);
1766 if (g_bPatchBendMode)
1768 VectorCopy(point, g_vBendOrigin);
1770 Sys_UpdateWindows (W_XY);
1775 SnapToPoint (x, y, point);
1776 if (m_nViewType == XY)
1778 z.origin[0] = point[0];
1779 z.origin[1] = point[1];
1781 else if (m_nViewType == YZ)
1783 z.origin[0] = point[1];
1784 z.origin[1] = point[2];
1788 z.origin[0] = point[0];
1789 z.origin[1] = point[2];
1792 Sys_UpdateWindows (W_XY_OVERLAY|W_Z);
1796 // mbutton = angle camera
1797 if ((g_PrefsDlg.m_nMouseButtons == 3 && m_nButtonstate == MK_MBUTTON) ||
1798 (g_PrefsDlg.m_nMouseButtons == 2 && m_nButtonstate == (MK_SHIFT|MK_CONTROL|MK_RBUTTON)))
1800 SnapToPoint (x, y, point);
1801 VectorSubtract (point, g_pParentWnd->GetCamWnd()->Camera()->origin, point);
1803 int n1 = (m_nViewType == XY) ? 1 : 2;
1804 int n2 = (m_nViewType == YZ) ? 1 : 0;
1805 int nAngle = (m_nViewType == XY) ? YAW : PITCH;
1806 if (point[n1] || point[n2])
1808 g_pParentWnd->GetCamWnd()->Camera()->angles[nAngle] = 180/Q_PI*atan2 (point[n1], point[n2]);
1809 Sys_UpdateWindows (W_CAMERA_IFON|W_XY_OVERLAY);
1814 // rbutton = drag xy origin
1815 if (m_nButtonstate == MK_RBUTTON)
1817 Sys_GetCursorPos (&x, &y);
1818 if (x != m_ptCursorX || y != m_ptCursorY)
1820 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
1821 int nDim2 = (m_nViewType == XY) ? 1 : 2;
1822 m_vOrigin[nDim1] -= (x - m_ptCursorX) / m_fScale;
1823 m_vOrigin[nDim2] += (y - m_ptCursorY) / m_fScale;
1824 Sys_SetCursorPos (m_ptCursorX, m_ptCursorY);
1826 // create an empty cursor
1831 char buffer [(32 * 32)/8];
1832 memset (buffer, 0, (32 * 32)/8);
1833 GdkColor white = {0, 0xffff, 0xffff, 0xffff};
1834 GdkColor black = {0, 0x0000, 0x0000, 0x0000};
1835 pixmap = gdk_bitmap_create_from_data (NULL, buffer, 32, 32);
1836 mask = gdk_bitmap_create_from_data (NULL, buffer, 32, 32);
1837 GdkCursor *cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &white, &black, 1, 1);
1838 gdk_window_set_cursor (m_pWidget->window, cursor);
1839 gdk_cursor_unref (cursor);
1840 gdk_drawable_unref (pixmap);
1841 gdk_drawable_unref (mask);
1844 Sys_UpdateWindows (W_XY | W_XY_OVERLAY);
1850 if (m_nButtonstate == (MK_SHIFT | MK_RBUTTON))
1852 Sys_GetCursorPos (&x, &y);
1853 if (y != m_ptCursorY)
1855 if (abs (m_ptCursorY - y) > 10)
1857 if (m_ptCursorY < y)
1858 g_pParentWnd->OnViewZoomout ();
1860 g_pParentWnd->OnViewZoomin ();
1862 Sys_SetCursorPos (m_ptCursorX, m_ptCursorY);
1869 void XYWnd::OriginalButtonDown(guint32 nFlags, int pointx, int pointy)
1873 XY_MouseDown (pointx, m_pWidget->allocation.height - 1 - pointy , nFlags);
1874 m_nScrollFlags = nFlags;
1877 void XYWnd::OriginalButtonUp(guint32 nFlags, int pointx, int pointy)
1879 XY_MouseUp (pointx, m_pWidget->allocation.height - 1 - pointy , nFlags);
1883 void XYWnd::DropClipPoint(guint32 nFlags, int pointx, int pointy)
1888 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *g_pMovingClip);
1893 if (g_Clip1.Set() == false)
1897 g_Clip1.m_ptScreenX = pointx;
1898 g_Clip1.m_ptScreenY = pointy;
1901 if (g_Clip2.Set() == false)
1905 g_Clip2.m_ptScreenX = pointx;
1906 g_Clip2.m_ptScreenY = pointy;
1909 if (g_Clip3.Set() == false)
1913 g_Clip3.m_ptScreenX = pointx;
1914 g_Clip3.m_ptScreenY = pointy;
1918 RetainClipMode(true);
1921 g_Clip1.m_ptScreenX = pointx;
1922 g_Clip1.m_ptScreenY = pointy;
1924 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *pPt);
1925 // third coordinates for clip point: use d_work_max
1926 // Arnout: changed to use center of selection for clipping, saves level designers moving points all over the map
1927 // g_pParentWnd->ActiveXY()->GetViewType()
1928 // cf VIEWTYPE defintion: enum VIEWTYPE {YZ, XZ, XY};
1929 int nViewType = g_pParentWnd->ActiveXY()->GetViewType();
1930 int nDim = (nViewType == YZ ) ? nDim = 0 : ( (nViewType == XZ) ? nDim = 1 : nDim = 2 );
1931 //(*pPt)[nDim] = g_qeglobals.d_work_max[nDim];
1933 Select_GetMid( mid );
1934 (*pPt)[nDim] = mid[nDim];
1936 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1939 void XYWnd::DropPathPoint(guint32 nFlags, int pointx, int pointy)
1944 SnapToPoint (pointx, m_pWidget->allocation.height - 1 - pointy , *g_pMovingPath);
1948 g_PathPoints[g_nPathCount].Set(true);
1949 g_PathPoints[g_nPathCount].m_ptScreenX = pointx;
1950 g_PathPoints[g_nPathCount].m_ptScreenY = pointy;
1951 SnapToPoint(pointx, m_pWidget->allocation.height - 1 - pointy, g_PathPoints[g_nPathCount]);
1952 // third coordinates for dropped point: use d_work_max
1953 // g_pParentWnd->ActiveXY()->GetViewType()
1954 // cf VIEWTYPE definition: enum VIEWTYPE {YZ, XZ, XY};
1955 int nViewType = g_pParentWnd->ActiveXY()->GetViewType();
1956 int nDim = (nViewType == YZ ) ? nDim = 0 : ( (nViewType == XZ) ? nDim = 1 : nDim = 2 );
1957 g_PathPoints[g_nPathCount].m_ptClip[nDim] = g_qeglobals.d_work_max[nDim];
1960 if (g_nPathCount == g_nPathLimit)
1963 g_pPathFunc(true, g_nPathCount);
1965 g_bPathMode = false;
1969 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1972 // FIXME: AddPointPoint() redundant function never called
1974 void XYWnd::AddPointPoint(guint32 nFlags, vec3_t* pVec)
1976 g_PointPoints[g_nPointCount].Set(true);
1977 //g_PointPoints[g_nPointCount].m_ptScreen = point;
1978 _VectorCopy(*pVec, g_PointPoints[g_nPointCount]);
1979 g_PointPoints[g_nPointCount].SetPointPtr(pVec);
1981 Sys_UpdateWindows(XY | W_CAMERA_IFON);
1984 // FIXME: ProduceSplits() redundant function never called
1985 void XYWnd::ProduceSplits(brush_t** pFront, brush_t** pBack)
1991 if (g_Clip1.Set() && g_Clip2.Set())
1994 VectorCopy(g_Clip1.m_ptClip,face.planepts[0]);
1995 VectorCopy(g_Clip2.m_ptClip,face.planepts[1]);
1996 VectorCopy(g_Clip3.m_ptClip,face.planepts[2]);
1997 if (selected_brushes.next && (selected_brushes.next->next == &selected_brushes))
1999 if (g_Clip3.Set() == false)
2001 if (m_nViewType == XY)
2003 face.planepts[0][2] = selected_brushes.next->mins[2];
2004 face.planepts[1][2] = selected_brushes.next->mins[2];
2005 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
2006 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
2007 face.planepts[2][2] = selected_brushes.next->maxs[2];
2009 else if (m_nViewType == YZ)
2011 face.planepts[0][0] = selected_brushes.next->mins[0];
2012 face.planepts[1][0] = selected_brushes.next->mins[0];
2013 face.planepts[2][1] = Betwixt(g_Clip1.m_ptClip[1], g_Clip2.m_ptClip[1]);
2014 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
2015 face.planepts[2][0] = selected_brushes.next->maxs[0];
2019 face.planepts[0][1] = selected_brushes.next->mins[1];
2020 face.planepts[1][1] = selected_brushes.next->mins[1];
2021 face.planepts[2][0] = Betwixt(g_Clip1.m_ptClip[0], g_Clip2.m_ptClip[0]);
2022 face.planepts[2][2] = Betwixt(g_Clip1.m_ptClip[2], g_Clip2.m_ptClip[2]);
2023 face.planepts[2][1] = selected_brushes.next->maxs[1];
2027 Brush_SplitBrushByFace (selected_brushes.next, &face, pFront, pBack);
2035 void XYWnd::PlanePointsFromClipPoints(vec3_t planepts[3], brush_t *pBrush)
2037 VectorCopy(g_Clip1.m_ptClip,planepts[0]);
2038 VectorCopy(g_Clip2.m_ptClip,planepts[1]);
2039 VectorCopy(g_Clip3.m_ptClip,planepts[2]);
2040 if (g_Clip3.Set() == false)
2042 int n = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 2 : (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 0 : 1;
2043 int x = (n == 0) ? 1 : 0;
2044 int y = (n == 2) ? 1 : 2;
2046 if (n == 1) // on viewtype XZ, flip clip points
2048 planepts[0][n] = pBrush->maxs[n];
2049 planepts[1][n] = pBrush->maxs[n];
2050 planepts[2][x] = g_Clip1.m_ptClip[x];
2051 planepts[2][y] = g_Clip1.m_ptClip[y];
2052 planepts[2][n] = pBrush->mins[n];
2056 planepts[0][n] = pBrush->mins[n];
2057 planepts[1][n] = pBrush->mins[n];
2058 planepts[2][x] = g_Clip1.m_ptClip[x];
2059 planepts[2][y] = g_Clip1.m_ptClip[y];
2060 planepts[2][n] = pBrush->maxs[n];
2065 void XYWnd::ProduceSplitLists()
2067 bool bCaulk = false;
2070 if (AnyPatchesSelected())
2072 Sys_Printf("Deselecting patches for clip operation.\n");
2074 for (brush_t *pb = selected_brushes.next ; pb != &selected_brushes ; pb = next)
2079 Brush_RemoveFromList (pb);
2080 Brush_AddToList (pb, &active_brushes);
2081 UpdatePatchInspector();
2084 // ydnar: update the window if any patches are selected
2085 Sys_UpdateWindows( XY | W_CAMERA_IFON );
2088 CleanList(&g_brFrontSplits);
2089 CleanList(&g_brBackSplits);
2090 g_brFrontSplits.next = &g_brFrontSplits;
2091 g_brBackSplits.next = &g_brBackSplits;
2092 if (ClipMode() && (g_Clip1.Set() && g_Clip2.Set()))
2095 for (pBrush = selected_brushes.next ; pBrush != NULL && pBrush != &selected_brushes ; pBrush=pBrush->next)
2097 brush_t* pFront = NULL;
2098 brush_t* pBack = NULL;
2101 memset(&face,0,sizeof(face_t));
2102 PlanePointsFromClipPoints(face.planepts, pBrush);
2104 // decide wether caulking should be applied on the splits
2106 // this should take the first brush face, check shader for NODRAW, if it isn't nodraw then find the appropriate
2107 // 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
2108 // 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
2109 if (g_PrefsDlg.m_bClipCaulk)
2111 nFlags = pBrush->brush_faces->pShader->getFlags();
2112 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
2113 bCaulk = false; // use first face's shader for the splitting face
2115 bCaulk = true; // use caulk
2118 Brush_SplitBrushByFace (pBrush, &face, &pFront, &pBack, bCaulk);
2120 Brush_AddToList(pBack, &g_brBackSplits);
2122 Brush_AddToList(pFront, &g_brFrontSplits);
2128 void XYWnd::XY_Init()
2136 void XYWnd::SnapToPoint (int x, int y, vec3_t point)
2138 if (g_PrefsDlg.m_bSnap)
2140 XY_ToGridPoint(x, y, point);
2144 XY_ToPoint(x, y, point);
2148 // TTimo: watch it, this doesn't init one of the 3 coords
2149 void XYWnd::XY_ToPoint (int x, int y, vec3_t point)
2153 float fw = m_nWidth;
2154 float fh = m_nHeight;
2155 if (m_nViewType == XY)
2157 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2158 point[1] = m_vOrigin[1] + (fy - fh / 2) / m_fScale;
2160 else if (m_nViewType == YZ)
2162 point[1] = m_vOrigin[1] + (fx - fw / 2) / m_fScale;
2163 point[2] = m_vOrigin[2] + (fy - fh / 2 ) / m_fScale;
2167 point[0] = m_vOrigin[0] + (fx - fw / 2) / m_fScale;
2168 point[2] = m_vOrigin[2] + (fy - fh / 2) / m_fScale;
2172 void XYWnd::XY_ToGridPoint (int x, int y, vec3_t point)
2174 if (m_nViewType == XY)
2176 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2177 point[1] = m_vOrigin[1] + (y - m_nHeight / 2) / m_fScale;
2178 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2179 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2181 else if (m_nViewType == YZ)
2183 point[1] = m_vOrigin[1] + (x - m_nWidth / 2) / m_fScale;
2184 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2185 point[1] = floor(point[1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2186 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2190 point[0] = m_vOrigin[0] + (x - m_nWidth / 2) / m_fScale;
2191 point[2] = m_vOrigin[2] + (y - m_nHeight / 2) / m_fScale;
2192 point[0] = floor(point[0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2193 point[2] = floor(point[2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
2198 ============================================================================
2202 ============================================================================
2210 void XYWnd::XY_DrawGrid()
2212 float x, y, xb, xe, yb, ye;
2215 int step, stepx, stepy, colour;
2216 step = stepx = stepy = MAX (64, (int)g_qeglobals.d_gridsize);
2219 int stepSize = (int)(8 / m_fScale);
2220 if (stepSize > step)
2223 for (i = 1; i < stepSize; i <<= 1)
2229 //Sys_Printf("scale: %f\n", m_fScale);
2230 //Sys_Printf("step before: %i\n", step);
2231 //Sys_Printf("scaled step: %f\n", step * m_fScale);
2232 while ((step * m_fScale) < 4.0f) // make sure major grid spacing is at least 4 pixels on the screen
2234 //Sys_Printf("step after: %i\n", step);
2235 while ((stepx * m_fScale) < 40.0f) // text step x must be at least 40 pixels
2237 while ((stepy * m_fScale) < 40.0f) // text step y must be at least 40 pixels
2240 qglDisable(GL_TEXTURE_2D);
2241 qglDisable(GL_TEXTURE_1D);
2242 qglDisable(GL_DEPTH_TEST);
2243 qglDisable(GL_BLEND);
2245 w = (m_nWidth / 2 / m_fScale);
2246 h = (m_nHeight / 2 / m_fScale);
2248 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2249 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2251 xb = m_vOrigin[nDim1] - w;
2252 if (xb < region_mins[nDim1])
2253 xb = region_mins[nDim1];
2254 xb = step * floor (xb/step);
2256 xe = m_vOrigin[nDim1] + w;
2257 if (xe > region_maxs[nDim1])
2258 xe = region_maxs[nDim1];
2259 xe = step * ceil (xe/step);
2261 yb = m_vOrigin[nDim2] - h;
2262 if (yb < region_mins[nDim2])
2263 yb = region_mins[nDim2];
2264 yb = step * floor (yb/step);
2266 ye = m_vOrigin[nDim2] + h;
2267 if (ye > region_maxs[nDim2])
2268 ye = region_maxs[nDim2];
2269 ye = step * ceil (ye/step);
2271 #define COLORS_DIFFER(a,b) \
2272 (g_qeglobals.d_savedinfo.colors[a][0] != g_qeglobals.d_savedinfo.colors[b][0] || \
2273 g_qeglobals.d_savedinfo.colors[a][1] != g_qeglobals.d_savedinfo.colors[b][1] || \
2274 g_qeglobals.d_savedinfo.colors[a][2] != g_qeglobals.d_savedinfo.colors[b][2])
2277 // draw minor blocks
2278 if (m_fScale > .1 && g_qeglobals.d_showgrid && g_qeglobals.d_gridsize * m_fScale >= 4)
2280 if (g_qeglobals.d_gridsize < 1)
2281 colour = COLOR_GRIDMINOR_ALT;
2283 colour = COLOR_GRIDMINOR;
2285 if (COLORS_DIFFER(colour, COLOR_GRIDBACK))
2287 qglColor3fv(g_qeglobals.d_savedinfo.colors[colour]);
2289 qglBegin (GL_LINES);
2290 for (x=xb ; x<xe ; x += g_qeglobals.d_gridsize)
2292 if (!((int)x & (step-1)) && !((int)x - x))
2294 qglVertex2f (x, yb);
2295 qglVertex2f (x, ye);
2297 for (y=yb ; y<ye ; y+=g_qeglobals.d_gridsize)
2299 if (!((int)y & (step-1)) && !((int)y - y))
2301 qglVertex2f (xb, y);
2302 qglVertex2f (xe, y);
2308 if(g_qeglobals.d_gridsize < 1)
2309 colour = COLOR_GRIDMAJOR_ALT;
2311 colour = COLOR_GRIDMAJOR;
2313 // draw major blocks
2314 if (COLORS_DIFFER(colour, COLOR_GRIDBACK))
2315 qglColor3fv(g_qeglobals.d_savedinfo.colors[colour]);
2317 if ( g_qeglobals.d_showgrid )
2319 qglBegin (GL_LINES);
2320 for (x=xb ; x<=xe ; x+=step)
2322 qglVertex2f (x, yb);
2323 qglVertex2f (x, ye);
2325 for (y=yb ; y<=ye ; y+=step)
2327 qglVertex2f (xb, y);
2328 qglVertex2f (xe, y);
2333 // draw coordinate text if needed
2334 if ( g_qeglobals.d_savedinfo.show_coordinates)
2336 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDTEXT]);
2338 // Pixels between top of label for vertical grid line and top of grid view window.
2339 // Note: There is currently a bug where the top few pixels of the grid view are hidden
2340 // under the border. So you should add about 5 to the desired value here. However,
2341 // the font ascent reaches higher than all digits, so you can subtract a few from the final
2343 const int pixelsTopCushion = 4;
2345 // Pixels between left of label and
2346 // - left of grid view window (for horizontal grid line label) or
2347 // - drawn vertical grid line (for vertical grid line label).
2348 const int pixelsLeftCushion = 2; // IMPORTANT! Must be at least 1 otherwise labels might not be drawn
2349 // because the origin of the text might be off screen due to rounding.
2351 // Pixels between baseline of horizontal grid line label and drawn horizontal grid line.
2352 const int pixelsButtomCushion = 2;
2354 float yPosLabelsTop = m_vOrigin[nDim2] + h - (gtk_glwidget_font_ascent() + pixelsTopCushion) / m_fScale;
2355 float xPosLabelsLeft = m_vOrigin[nDim1] - w + pixelsLeftCushion / m_fScale;
2356 float leftCushion = pixelsLeftCushion / m_fScale;
2357 float bottomOffset = (pixelsButtomCushion - gtk_glwidget_font_descent()) / m_fScale;
2359 // This renders the numbers along varying X on top of the grid view (labels vertical grid lines).
2360 for (x = xb - ((int) xb) % stepx; x <= xe; x += stepx) {
2361 qglRasterPos2f(x + leftCushion, yPosLabelsTop);
2362 sprintf(text, "%i", (int) x);
2363 gtk_glwidget_print_string(text);
2366 // This renders the numbers along varying Y on the left of the grid view (labels horizontal grid lines).
2367 for (y = yb - ((int) yb) % stepy; y <= ye; y += stepy) {
2368 qglRasterPos2f(xPosLabelsLeft, y + bottomOffset);
2369 sprintf(text, "%i", (int) y);
2370 gtk_glwidget_print_string(text);
2374 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
2376 // we do this part (the old way) only if show_axis is disabled
2377 if (!g_qeglobals.d_savedinfo.show_axis)
2379 qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
2382 if (m_nViewType == XY)
2383 strcpy(cView, "XY Top");
2385 if (m_nViewType == XZ)
2386 strcpy(cView, "XZ Front");
2388 strcpy(cView, "YZ Side");
2390 gtk_glwidget_print_string(cView);
2394 if ( g_qeglobals.d_savedinfo.show_axis)
2396 // draw two lines with corresponding axis colors to highlight current view
2397 // horizontal line: nDim1 color
2399 qglBegin( GL_LINES );
2400 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
2401 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2402 qglVertex2f( m_vOrigin[nDim1] - w + 65 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2403 qglVertex2f( 0, 0 );
2404 qglVertex2f( 32 / m_fScale, 0 );
2405 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
2406 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2407 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
2408 qglVertex2f( 0, 0 );
2409 qglVertex2f( 0, 32 / m_fScale );
2412 // now print axis symbols
2413 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
2414 qglRasterPos2f ( m_vOrigin[nDim1] - w + 55 / m_fScale, m_vOrigin[nDim2] + h - 55 / m_fScale );
2415 gtk_glwidget_print_char(g_AxisName[nDim1]);
2416 qglRasterPos2f (28 / m_fScale, -10 / m_fScale );
2417 gtk_glwidget_print_char(g_AxisName[nDim1]);
2418 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
2419 qglRasterPos2f ( m_vOrigin[nDim1] - w + 25 / m_fScale, m_vOrigin[nDim2] + h - 30 / m_fScale );
2420 gtk_glwidget_print_char(g_AxisName[nDim2]);
2421 qglRasterPos2f ( -10 / m_fScale, 28 / m_fScale );
2422 gtk_glwidget_print_char(g_AxisName[nDim2]);
2426 // show current work zone?
2427 // the work zone is used to place dropped points and brushes
2428 if (g_qeglobals.d_show_work)
2430 qglColor3f( 1.0f, 0.0f, 0.0f );
2431 qglBegin( GL_LINES );
2432 qglVertex2f( xb, g_qeglobals.d_work_min[nDim2] );
2433 qglVertex2f( xe, g_qeglobals.d_work_min[nDim2] );
2434 qglVertex2f( xb, g_qeglobals.d_work_max[nDim2] );
2435 qglVertex2f( xe, g_qeglobals.d_work_max[nDim2] );
2436 qglVertex2f( g_qeglobals.d_work_min[nDim1], yb );
2437 qglVertex2f( g_qeglobals.d_work_min[nDim1], ye );
2438 qglVertex2f( g_qeglobals.d_work_max[nDim1], yb );
2439 qglVertex2f( g_qeglobals.d_work_max[nDim1], ye );
2449 void XYWnd::XY_DrawBlockGrid()
2451 const char *value = ValueForKey( world_entity, "_blocksize" );
2453 sscanf( value, "%i", &g_qeglobals.blockSize );
2455 if (!g_qeglobals.blockSize || g_qeglobals.blockSize > 65536 || g_qeglobals.blockSize < 1024)
2456 // don't use custom blocksize if it is less than the default, or greater than the maximum world coordinate
2457 g_qeglobals.blockSize = 1024;
2459 float x, y, xb, xe, yb, ye;
2463 qglDisable(GL_TEXTURE_2D);
2464 qglDisable(GL_TEXTURE_1D);
2465 qglDisable(GL_DEPTH_TEST);
2466 qglDisable(GL_BLEND);
2468 w = (m_nWidth / 2 / m_fScale);
2469 h = (m_nHeight / 2 / m_fScale);
2471 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2472 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2474 xb = m_vOrigin[nDim1] - w;
2475 if (xb < region_mins[nDim1])
2476 xb = region_mins[nDim1];
2477 xb = g_qeglobals.blockSize * floor (xb/g_qeglobals.blockSize);
2479 xe = m_vOrigin[nDim1] + w;
2480 if (xe > region_maxs[nDim1])
2481 xe = region_maxs[nDim1];
2482 xe = g_qeglobals.blockSize * ceil (xe/g_qeglobals.blockSize);
2484 yb = m_vOrigin[nDim2] - h;
2485 if (yb < region_mins[nDim2])
2486 yb = region_mins[nDim2];
2487 yb = g_qeglobals.blockSize * floor (yb/g_qeglobals.blockSize);
2489 ye = m_vOrigin[nDim2] + h;
2490 if (ye > region_maxs[nDim2])
2491 ye = region_maxs[nDim2];
2492 ye = g_qeglobals.blockSize * ceil (ye/g_qeglobals.blockSize);
2494 // draw major blocks
2496 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]);
2499 qglBegin (GL_LINES);
2501 for (x=xb ; x<=xe ; x+=g_qeglobals.blockSize)
2503 qglVertex2f (x, yb);
2504 qglVertex2f (x, ye);
2507 if (m_nViewType == XY)
2509 for (y=yb ; y<=ye ; y+=g_qeglobals.blockSize)
2511 qglVertex2f (xb, y);
2512 qglVertex2f (xe, y);
2519 // draw coordinate text if needed
2521 if (m_nViewType == XY && m_fScale > .1)
2523 for (x=xb ; x<xe ; x+=g_qeglobals.blockSize)
2524 for (y=yb ; y<ye ; y+=g_qeglobals.blockSize)
2526 qglRasterPos2f (x+(g_qeglobals.blockSize/2), y+(g_qeglobals.blockSize/2));
2527 sprintf (text, "%i,%i",(int)floor(x/g_qeglobals.blockSize), (int)floor(y/g_qeglobals.blockSize) );
2528 gtk_glwidget_print_string(text);
2532 qglColor4f(0, 0, 0, 0);
2535 void XYWnd::DrawRotateIcon()
2539 a = 4.0 / m_fScale; // compensate for zoom level
2542 if (m_nViewType == XY)
2544 x = g_vRotateOrigin[0];
2545 y = g_vRotateOrigin[1];
2547 else if (m_nViewType == YZ)
2549 x = g_vRotateOrigin[1];
2550 y = g_vRotateOrigin[2];
2554 x = g_vRotateOrigin[0];
2555 y = g_vRotateOrigin[2];
2558 qglEnable (GL_BLEND);
2559 qglDisable (GL_TEXTURE_2D);
2560 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
2561 qglDisable (GL_CULL_FACE);
2562 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2563 qglColor4f (0.8f, 0.1f, 0.9f, 0.25f);
2566 qglVertex3f (x-a,y-a,0);
2567 qglVertex3f (x+a,y-a,0);
2568 qglVertex3f (x+a,y+a,0);
2569 qglVertex3f (x-a,y+a,0);
2571 qglDisable (GL_BLEND);
2573 qglColor4f (1.0f, 0.2f, 1.0f, 1.f);
2574 qglBegin(GL_POINTS);
2575 qglVertex3f (x,y,0);
2580 qglVertex3f (x-b,y+b,0);
2581 qglVertex3f (x+b,y+b,0);
2582 qglVertex3f (x-b,y-b,0);
2583 qglVertex3f (x+b,y-b,0);
2589 void XYWnd::DrawCameraIcon()
2591 float x, y, a, fov, box;
2593 fov = 48 / m_fScale;
2594 box = 16 / m_fScale;
2596 if (m_nViewType == XY)
2598 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
2599 y = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
2600 a = g_pParentWnd->GetCamWnd()->Camera()->angles[YAW]/180*Q_PI;
2602 else if (m_nViewType == YZ)
2604 x = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
2605 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
2606 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
2610 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
2611 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
2612 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
2615 qglColor3f (0.0, 0.0, 1.0);
2616 qglBegin(GL_LINE_STRIP);
2617 qglVertex3f (x-box,y,0);
2618 qglVertex3f (x,y+(box/2),0);
2619 qglVertex3f (x+box,y,0);
2620 qglVertex3f (x,y-(box/2),0);
2621 qglVertex3f (x-box,y,0);
2622 qglVertex3f (x+box,y,0);
2625 qglBegin(GL_LINE_STRIP);
2626 qglVertex3f (x+fov*cos(a+Q_PI/4), y+fov*sin(a+Q_PI/4), 0);
2627 qglVertex3f (x, y, 0);
2628 qglVertex3f (x+fov*cos(a-Q_PI/4), y+fov*sin(a-Q_PI/4), 0);
2633 void XYWnd::DrawZIcon (void)
2635 if (m_nViewType == XY)
2637 float x = z.origin[0];
2638 float y = z.origin[1];
2639 float zdim = 8 / m_fScale;
2640 qglEnable (GL_BLEND);
2641 qglDisable (GL_TEXTURE_2D);
2642 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
2643 qglDisable (GL_CULL_FACE);
2644 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2645 qglColor4f (0.0, 0.0, 1.0, 0.25);
2647 qglVertex3f (x-zdim,y-zdim,0);
2648 qglVertex3f (x+zdim,y-zdim,0);
2649 qglVertex3f (x+zdim,y+zdim,0);
2650 qglVertex3f (x-zdim,y+zdim,0);
2652 qglDisable (GL_BLEND);
2654 qglColor4f (0.0, 0.0, 1.0, 1);
2656 qglBegin(GL_LINE_LOOP);
2657 qglVertex3f (x-zdim,y-zdim,0);
2658 qglVertex3f (x+zdim,y-zdim,0);
2659 qglVertex3f (x+zdim,y+zdim,0);
2660 qglVertex3f (x-zdim,y+zdim,0);
2663 qglBegin(GL_LINE_STRIP);
2664 qglVertex3f (x-(zdim/2),y+(zdim/2),0);
2665 qglVertex3f (x+(zdim/2),y+(zdim/2),0);
2666 qglVertex3f (x-(zdim/2),y-(zdim/2),0);
2667 qglVertex3f (x+(zdim/2),y-(zdim/2),0);
2672 // can be greatly simplified but per usual i am in a hurry
2673 // which is not an excuse, just a fact
2674 void XYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds)
2676 const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"};
2677 const char* g_pOrgStrings[] = {"(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)"};
2682 VectorSubtract(vMaxBounds, vMinBounds, vSize);
2684 qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
2685 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
2686 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65);
2688 if (m_nViewType == XY)
2690 qglBegin (GL_LINES);
2692 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
2693 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2695 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2696 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2698 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
2699 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2702 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2703 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2705 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2706 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2708 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2709 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2713 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
2714 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2715 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2717 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
2718 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2719 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2721 qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
2722 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
2723 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2725 else if (m_nViewType == XZ)
2727 qglBegin (GL_LINES);
2729 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
2730 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
2732 qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2733 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2735 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale);
2736 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2739 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2]);
2740 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
2742 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
2743 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
2745 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2]);
2746 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
2750 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
2751 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2752 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2754 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
2755 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2756 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2758 qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
2759 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
2760 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2764 qglBegin (GL_LINES);
2766 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
2767 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2769 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2770 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2772 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
2773 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2776 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
2777 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
2779 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
2780 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
2782 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
2783 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
2787 qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
2788 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2789 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2791 qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
2792 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2793 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2795 qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
2796 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
2797 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2806 #define ALT_POINT_SIZE 4
2807 // Alternative to GL_POINTS (for; vertex handles, patch handles, clip points, path points)
2808 void DrawAlternatePoint(vec3_t v, float scale)
2812 scale = g_pParentWnd->GetXYWnd()->Scale();
2813 //scale = g_qeglobals.d_xyOld.scale;
2816 // ugly gl_line cross
2817 qglVertex3f ( v[0]+(ALT_POINT_SIZE/scale), v[1], v[2] );
2818 qglVertex3f ( v[0]-(ALT_POINT_SIZE/scale), v[1], v[2] );
2819 qglVertex3f ( v[0], v[1]+(ALT_POINT_SIZE/scale), v[2] );
2820 qglVertex3f ( v[0], v[1]-(ALT_POINT_SIZE/scale), v[2] );
2821 qglVertex3f ( v[0], v[1], v[2]+(ALT_POINT_SIZE/scale) );
2822 qglVertex3f ( v[0], v[1], v[2]-(ALT_POINT_SIZE/scale) );
2828 extern void DrawBrushEntityName (brush_t *b);
2830 //#define DBG_SCENEDUMP
2832 void XYWnd::XY_Draw()
2834 #ifdef DBG_SCENEDUMP
2835 static time_t s_start = 0; // we use that to dump the selected stuff every 2 seconds
2840 if ((now - s_start) > 3)
2844 Sys_FPrintf(SYS_WRN, "Starting scene dump\n");
2853 double start2, end2;
2858 if (!active_brushes.next)
2859 return; // not valid yet
2861 Patch_LODMatchAll(); // spog
2864 start = Sys_DoubleTime();
2870 qglViewport(0, 0, m_nWidth, m_nHeight);
2871 qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
2872 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
2873 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0);
2875 qglClear(GL_COLOR_BUFFER_BIT);
2880 qglMatrixMode(GL_PROJECTION);
2883 w = m_nWidth / 2 / m_fScale;
2884 h = m_nHeight / 2/ m_fScale;
2886 // fix GL_INVALID_VALUE error on first time the window is updated (win32)
2890 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2891 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2892 mins[0] = m_vOrigin[nDim1] - w;
2893 maxs[0] = m_vOrigin[nDim1] + w;
2894 mins[1] = m_vOrigin[nDim2] - h;
2895 maxs[1] = m_vOrigin[nDim2] + h;
2897 qglOrtho (mins[0], maxs[0], mins[1], maxs[1], g_MinWorldCoord, g_MaxWorldCoord);
2899 qglMatrixMode(GL_MODELVIEW);
2903 // now draw the grid
2910 if ( g_qeglobals.show_blocks)
2911 XY_DrawBlockGrid ();
2913 if (m_nViewType != XY)
2916 if (m_nViewType == YZ)
2917 qglRotatef (-90, 0, 1, 0); // put Z going up
2918 qglRotatef (-90, 1, 0, 0); // put Z going up
2924 qglShadeModel (GL_FLAT);
2925 qglDisable(GL_TEXTURE_2D);
2926 qglDisable(GL_TEXTURE_1D);
2927 qglDisable(GL_DEPTH_TEST);
2928 qglDisable(GL_BLEND);
2929 qglDisable(GL_CULL_FACE);
2930 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
2931 qglColor3f(0, 0, 0);
2932 qglEnableClientState(GL_VERTEX_ARRAY);
2934 // Fishman - Add antialiazed points and lines support. 09/15/00
2935 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
2937 qglEnable(GL_BLEND);
2938 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2939 qglEnable(GL_POINT_SMOOTH);
2940 qglEnable(GL_LINE_SMOOTH);
2948 start2 = Sys_DoubleTime();
2950 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
2952 if (brush->bFiltered)
2955 if (brush->mins[nDim1] > maxs[0] ||
2956 brush->mins[nDim2] > maxs[1] ||
2957 brush->maxs[nDim1] < mins[0] ||
2958 brush->maxs[nDim2] < mins[1])
2961 continue; // off screen
2966 if (brush->owner != e && brush->owner)
2968 qglColor3fv(brush->owner->eclass->color);
2972 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
2975 #ifdef DBG_SCENEDUMP
2978 Sys_FPrintf(SYS_WRN, "Active brush: %p ", brush);
2979 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
2983 Brush_DrawXY(brush, m_nViewType);
2987 end2 = Sys_DoubleTime();
2994 //++timo why is the display list broken?
2995 if ( g_qeglobals.d_pointfile_display_list)
2999 // now draw selected brushes
3003 qglColor3f(0.8f, 0.1f, 0.9f);
3006 qglColor3f(0.1f, 0.8f, 0.1f);
3008 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
3011 if (g_PrefsDlg.m_bNoStipple == FALSE)
3013 qglEnable (GL_LINE_STIPPLE);
3014 qglLineStipple (3, 0xaaaa);
3020 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = g_MaxWorldCoord;
3021 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = g_MinWorldCoord;
3023 int nSaveDrawn = drawn;
3024 bool bFixedSize = false;
3025 for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
3027 // spog - added culling of selected brushes in XY window
3028 if (brush->mins[nDim1] > maxs[0] ||
3029 brush->mins[nDim2] > maxs[1] ||
3030 brush->maxs[nDim1] < mins[0] ||
3031 brush->maxs[nDim2] < mins[1])
3034 continue; // off screen
3037 #ifdef DBG_SCENEDUMP
3040 Sys_FPrintf(SYS_WRN, "Selected brush: %p ", brush);
3041 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
3044 Brush_DrawXY(brush, m_nViewType);
3048 if (brush->owner->eclass->fixedsize)
3050 if (g_PrefsDlg.m_bSizePaint)
3052 for (i = 0; i < 3; i ++)
3054 if (brush->mins[i] < vMinBounds[i])
3055 vMinBounds[i] = brush->mins[i];
3056 if (brush->maxs[i] > vMaxBounds[i])
3057 vMaxBounds[i] = brush->maxs[i];
3063 if (g_PrefsDlg.m_bNoStipple == FALSE)
3065 qglDisable (GL_LINE_STIPPLE);
3069 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint)
3070 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
3072 // edge / vertex flags
3073 if (g_qeglobals.d_select_mode == sel_vertex)
3075 if(!g_PrefsDlg.m_bGlPtWorkaround)
3080 qglBegin (GL_POINTS);
3081 for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
3082 qglVertex3fv (g_qeglobals.d_points[i]);
3085 if(g_qeglobals.d_num_move_points)
3087 // selected brush verts
3090 qglBegin (GL_POINTS);
3091 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
3092 qglVertex3fv (g_qeglobals.d_move_points[i]);
3102 qglBegin (GL_LINES);
3103 for (i=0; i < g_qeglobals.d_numpoints; i++)
3104 DrawAlternatePoint(g_qeglobals.d_points[i], m_fScale);
3107 if(g_qeglobals.d_num_move_points)
3109 // selected brush verts
3112 qglBegin (GL_LINES);
3113 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
3114 qglVertex3fv (g_qeglobals.d_move_points[i]);
3120 else if (g_qeglobals.d_select_mode == sel_edge)
3123 if(!g_PrefsDlg.m_bGlPtWorkaround)
3127 qglBegin (GL_POINTS);
3128 for (i=0 ; i<g_qeglobals.d_numedges ; i++)
3130 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
3131 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
3132 qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
3140 qglBegin (GL_LINES);
3141 for (i=0; i < g_qeglobals.d_numedges; i++)
3143 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
3144 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
3146 v3[0] = (v1[0]+v2[0])*0.5;
3147 v3[1] = (v1[1]+v2[1])*0.5;
3148 v3[2] = (v1[2]+v2[2])*0.5;
3149 DrawAlternatePoint(v3, m_fScale);
3156 if (!(m_nViewType == XY))
3159 // area selection hack
3160 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)))
3162 qglEnable (GL_BLEND);
3163 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
3164 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3165 qglColor4f(0.0, 0.0, 1.0, 0.25);
3166 qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]);
3167 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
3168 qglDisable (GL_BLEND);
3174 // now draw camera point
3185 //++timo TODO: use an object for the 2D view
3186 Draw2DPluginEntities( (VIEWTYPE)m_nViewType );
3188 if (g_qeglobals.d_savedinfo.show_outline)
3192 qglMatrixMode (GL_PROJECTION);
3195 qglOrtho (0, m_nWidth, 0, m_nHeight, 0, 1);
3196 qglMatrixMode (GL_MODELVIEW);
3200 // four view mode doesn't colorize
3201 if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit)
3202 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
3204 qglColor3fv( g_qeglobals.d_savedinfo.AxisColors[m_nViewType]);
3205 qglBegin (GL_LINE_LOOP);
3207 qglVertex2i (m_nWidth-1, 0);
3208 qglVertex2i (m_nWidth-1, m_nHeight-1);
3209 qglVertex2i (0, m_nHeight-1);
3212 qglMatrixMode (GL_PROJECTION);
3214 qglMatrixMode (GL_MODELVIEW);
3223 end = Sys_DoubleTime ();
3224 i = (int)(1000*(end-start));
3225 int i3 = (int)(1000*(end2-start2));
3228 int i2 = g_lTotal / g_lCount;
3229 Sys_Printf ("xy: %i ab: %i avg: %i\n", i, i3, i2);
3232 // Fishman - Add antialiazed points and lines support. 09/03/00
3233 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
3235 qglDisable(GL_POINT_SMOOTH);
3236 qglDisable(GL_LINE_SMOOTH);
3237 qglDisable(GL_BLEND);
3249 void XYWnd::UndoClear()
3253 void XYWnd::UndoCopy()
3257 bool XYWnd::UndoAvailable()
3259 return (g_brUndo.next != &g_brUndo);
3266 // should be static as should be the rotate scale stuff
3267 bool XYWnd::AreaSelectOK()
3269 return RotateMode() ? false : ScaleMode() ? false : true;
3272 void XYWnd::OnCreate ()
3274 if (!MakeCurrent ())
3275 Error ("glXMakeCurrent failed");
3277 qglPolygonStipple ((unsigned char *)s_stipple);
3278 qglLineStipple (3, 0xaaaa);
3281 void XYWnd::OnExpose ()
3284 if (!MakeCurrent ())
3286 Sys_Printf("ERROR: glXMakeCurrent failed.. Error:%i\n",qglGetError());
3287 Sys_Printf("Please restart Radiant if the Map view is not working\n");
3292 QE_CheckOpenGLForErrors();
3294 QE_CheckOpenGLForErrors();
3296 if (m_nViewType != XY)
3299 if (m_nViewType == YZ)
3300 qglRotatef (-90, 0, 1, 0); // put Z going up
3301 qglRotatef (-90, 1, 0, 0); // put Z going up
3306 qglColor4f(0.2f, 0.9f, 0.2f, 0.8f);
3307 qglBegin (GL_LINES);
3308 if (m_nViewType == XY)
3310 qglVertex2f(2*g_MinWorldCoord, tdp[1]);
3311 qglVertex2f(2*g_MaxWorldCoord, tdp[1]);
3312 qglVertex2f(tdp[0], 2*g_MinWorldCoord);
3313 qglVertex2f(tdp[0], 2*g_MaxWorldCoord);
3315 else if (m_nViewType == YZ)
3317 qglVertex3f(tdp[0], 2*g_MinWorldCoord, tdp[2]);
3318 qglVertex3f(tdp[0], 2*g_MaxWorldCoord, tdp[2]);
3319 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
3320 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
3324 qglVertex3f (2*g_MinWorldCoord, tdp[1], tdp[2]);
3325 qglVertex3f (2*g_MaxWorldCoord, tdp[1], tdp[2]);
3326 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
3327 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
3336 g_Clip1.Draw(m_fScale, 1); // qglVertex3fv (g_Clip1);
3338 g_Clip2.Draw(m_fScale, 2); // qglVertex3fv (g_Clip2);
3340 g_Clip3.Draw(m_fScale, 3); // qglVertex3fv (g_Clip3);
3341 if (g_Clip1.Set() && g_Clip2.Set())
3343 ProduceSplitLists();
3345 brush_t* pList = (g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
3346 for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next)
3351 for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++)
3353 winding_t* w = face->face_winding;
3357 qglBegin(GL_LINE_LOOP);
3358 for (int i=0 ; i<w->numpoints ; i++)
3359 qglVertex3fv(w->points[i]);
3369 for (n = 0; n < g_nPathCount; n++)
3370 g_PathPoints[n].Draw(m_fScale, n+1); // qglVertex3fv(g_PathPoints[n]);
3372 if (m_nViewType != XY)
3375 m_XORRectangle.set(rectangle_t());
3380 void XYWnd::KillPathMode()
3383 g_bPathMode = false;
3385 g_pPathFunc(false, g_nPathCount);
3388 Sys_UpdateWindows(W_ALL);
3391 // gets called for drop down menu messages
3392 // TIP: it's not always about EntityCreate
3393 void XYWnd::OnEntityCreate (const char* item)
3395 Undo_Start("create entity");
3396 Undo_AddBrushList(&selected_brushes);
3398 if (m_mnuDrop != NULL)
3403 if (strItem.CompareNoCase("Add to...") == 0)
3405 //++timo TODO: fill the menu with current groups?
3406 // this one is for adding to existing groups only
3407 Sys_Printf("TODO: Add to... in XYWnd::OnEntityCreate\n");
3409 else if (strItem.CompareNoCase("Remove") == 0)
3411 // remove selected brushes from their current group
3413 for( b = selected_brushes.next; b != &selected_brushes; b = b->next )
3419 //++timo FIXME: remove when all hooks are in
3420 if (strItem.CompareNoCase("Add to...") == 0
3421 || strItem.CompareNoCase("Remove") == 0
3422 || strItem.CompareNoCase("Name...") == 0
3423 || strItem.CompareNoCase("New group...") == 0)
3425 Sys_Printf("TODO: hook drop down group menu\n");
3429 if (strItem.Find("Smart_") >= 0)
3431 CreateSmartEntity(this, m_ptDownX, m_ptDownY, strItem);
3435 CreateRightClickEntity(this, m_ptDownX, m_ptDownY, (char*)strItem.GetBuffer());
3438 Sys_UpdateWindows(W_ALL);
3439 //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
3441 Undo_EndBrushList(&selected_brushes);
3445 /* Drawing clip points */
3446 void ClipPoint::Draw(float fScale, int num)
3449 strLabel.Format("%d", num);
3450 Draw(fScale, strLabel.GetBuffer());
3453 #define ALT_POINT_VERTS 6
3455 void ClipPoint::Draw(float fScale, const char *label)
3458 if(!g_PrefsDlg.m_bGlPtWorkaround)
3461 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
3462 qglBegin (GL_POINTS);
3463 qglVertex3fv (m_ptClip);
3469 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
3471 qglBegin (GL_LINES);
3472 DrawAlternatePoint(m_ptClip, fScale);
3478 qglRasterPos3f (m_ptClip[0]+2, m_ptClip[1]+2, m_ptClip[2]+2);
3479 qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);