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_bNoClamp)
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_bNoClamp)
2140 XY_ToPoint(x, y, point);
2144 XY_ToGridPoint(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) < 32.0f) // text step x must be at least 32
2237 while ((stepy * m_fScale) < 32.0f) // text step y must be at least 32
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]);
2337 float offx = m_vOrigin[nDim2] + h - 6 / m_fScale, offy = m_vOrigin[nDim1] - w + 1 / m_fScale;
2338 for (x=xb-((int)xb)%stepx; x<=xe ; x+=stepx)
2340 qglRasterPos2f (x, offx);
2341 sprintf (text, "%i",(int)x);
2342 gtk_glwidget_print_string(text);
2344 for (y=yb-((int)yb)%stepy; y<=ye ; y+=stepy)
2346 qglRasterPos2f (offy, y);
2347 sprintf (text, "%i",(int)y);
2348 gtk_glwidget_print_string(text);
2352 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
2354 // we do this part (the old way) only if show_axis is disabled
2355 if (!g_qeglobals.d_savedinfo.show_axis)
2357 qglRasterPos2f ( m_vOrigin[nDim1] - w + 35 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
2360 if (m_nViewType == XY)
2361 strcpy(cView, "XY Top");
2363 if (m_nViewType == XZ)
2364 strcpy(cView, "XZ Front");
2366 strcpy(cView, "YZ Side");
2368 gtk_glwidget_print_string(cView);
2372 if ( g_qeglobals.d_savedinfo.show_axis)
2374 // draw two lines with corresponding axis colors to highlight current view
2375 // horizontal line: nDim1 color
2377 qglBegin( GL_LINES );
2378 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
2379 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2380 qglVertex2f( m_vOrigin[nDim1] - w + 65 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2381 qglVertex2f( 0, 0 );
2382 qglVertex2f( 32 / m_fScale, 0 );
2383 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
2384 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 45 / m_fScale );
2385 qglVertex2f( m_vOrigin[nDim1] - w + 40 / m_fScale, m_vOrigin[nDim2] + h - 20 / m_fScale );
2386 qglVertex2f( 0, 0 );
2387 qglVertex2f( 0, 32 / m_fScale );
2390 // now print axis symbols
2391 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim1]);
2392 qglRasterPos2f ( m_vOrigin[nDim1] - w + 55 / m_fScale, m_vOrigin[nDim2] + h - 55 / m_fScale );
2393 gtk_glwidget_print_char(g_AxisName[nDim1]);
2394 qglRasterPos2f (28 / m_fScale, -10 / m_fScale );
2395 gtk_glwidget_print_char(g_AxisName[nDim1]);
2396 qglColor3fv (g_qeglobals.d_savedinfo.AxisColors[nDim2]);
2397 qglRasterPos2f ( m_vOrigin[nDim1] - w + 25 / m_fScale, m_vOrigin[nDim2] + h - 30 / m_fScale );
2398 gtk_glwidget_print_char(g_AxisName[nDim2]);
2399 qglRasterPos2f ( -10 / m_fScale, 28 / m_fScale );
2400 gtk_glwidget_print_char(g_AxisName[nDim2]);
2404 // show current work zone?
2405 // the work zone is used to place dropped points and brushes
2406 if (g_qeglobals.d_show_work)
2408 qglColor3f( 1.0f, 0.0f, 0.0f );
2409 qglBegin( GL_LINES );
2410 qglVertex2f( xb, g_qeglobals.d_work_min[nDim2] );
2411 qglVertex2f( xe, g_qeglobals.d_work_min[nDim2] );
2412 qglVertex2f( xb, g_qeglobals.d_work_max[nDim2] );
2413 qglVertex2f( xe, g_qeglobals.d_work_max[nDim2] );
2414 qglVertex2f( g_qeglobals.d_work_min[nDim1], yb );
2415 qglVertex2f( g_qeglobals.d_work_min[nDim1], ye );
2416 qglVertex2f( g_qeglobals.d_work_max[nDim1], yb );
2417 qglVertex2f( g_qeglobals.d_work_max[nDim1], ye );
2427 void XYWnd::XY_DrawBlockGrid()
2429 const char *value = ValueForKey( world_entity, "_blocksize" );
2431 sscanf( value, "%i", &g_qeglobals.blockSize );
2433 if (!g_qeglobals.blockSize || g_qeglobals.blockSize > 65536 || g_qeglobals.blockSize < 1024)
2434 // don't use custom blocksize if it is less than the default, or greater than the maximum world coordinate
2435 g_qeglobals.blockSize = 1024;
2437 float x, y, xb, xe, yb, ye;
2441 qglDisable(GL_TEXTURE_2D);
2442 qglDisable(GL_TEXTURE_1D);
2443 qglDisable(GL_DEPTH_TEST);
2444 qglDisable(GL_BLEND);
2446 w = (m_nWidth / 2 / m_fScale);
2447 h = (m_nHeight / 2 / m_fScale);
2449 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2450 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2452 xb = m_vOrigin[nDim1] - w;
2453 if (xb < region_mins[nDim1])
2454 xb = region_mins[nDim1];
2455 xb = g_qeglobals.blockSize * floor (xb/g_qeglobals.blockSize);
2457 xe = m_vOrigin[nDim1] + w;
2458 if (xe > region_maxs[nDim1])
2459 xe = region_maxs[nDim1];
2460 xe = g_qeglobals.blockSize * ceil (xe/g_qeglobals.blockSize);
2462 yb = m_vOrigin[nDim2] - h;
2463 if (yb < region_mins[nDim2])
2464 yb = region_mins[nDim2];
2465 yb = g_qeglobals.blockSize * floor (yb/g_qeglobals.blockSize);
2467 ye = m_vOrigin[nDim2] + h;
2468 if (ye > region_maxs[nDim2])
2469 ye = region_maxs[nDim2];
2470 ye = g_qeglobals.blockSize * ceil (ye/g_qeglobals.blockSize);
2472 // draw major blocks
2474 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_GRIDBLOCK]);
2477 qglBegin (GL_LINES);
2479 for (x=xb ; x<=xe ; x+=g_qeglobals.blockSize)
2481 qglVertex2f (x, yb);
2482 qglVertex2f (x, ye);
2485 if (m_nViewType == XY)
2487 for (y=yb ; y<=ye ; y+=g_qeglobals.blockSize)
2489 qglVertex2f (xb, y);
2490 qglVertex2f (xe, y);
2497 // draw coordinate text if needed
2499 if (m_nViewType == XY && m_fScale > .1)
2501 for (x=xb ; x<xe ; x+=g_qeglobals.blockSize)
2502 for (y=yb ; y<ye ; y+=g_qeglobals.blockSize)
2504 qglRasterPos2f (x+(g_qeglobals.blockSize/2), y+(g_qeglobals.blockSize/2));
2505 sprintf (text, "%i,%i",(int)floor(x/g_qeglobals.blockSize), (int)floor(y/g_qeglobals.blockSize) );
2506 gtk_glwidget_print_string(text);
2510 qglColor4f(0, 0, 0, 0);
2513 void XYWnd::DrawRotateIcon()
2517 a = 4.0 / m_fScale; // compensate for zoom level
2520 if (m_nViewType == XY)
2522 x = g_vRotateOrigin[0];
2523 y = g_vRotateOrigin[1];
2525 else if (m_nViewType == YZ)
2527 x = g_vRotateOrigin[1];
2528 y = g_vRotateOrigin[2];
2532 x = g_vRotateOrigin[0];
2533 y = g_vRotateOrigin[2];
2536 qglEnable (GL_BLEND);
2537 qglDisable (GL_TEXTURE_2D);
2538 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
2539 qglDisable (GL_CULL_FACE);
2540 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2541 qglColor4f (0.8f, 0.1f, 0.9f, 0.25f);
2544 qglVertex3f (x-a,y-a,0);
2545 qglVertex3f (x+a,y-a,0);
2546 qglVertex3f (x+a,y+a,0);
2547 qglVertex3f (x-a,y+a,0);
2549 qglDisable (GL_BLEND);
2551 qglColor4f (1.0f, 0.2f, 1.0f, 1.f);
2552 qglBegin(GL_POINTS);
2553 qglVertex3f (x,y,0);
2558 qglVertex3f (x-b,y+b,0);
2559 qglVertex3f (x+b,y+b,0);
2560 qglVertex3f (x-b,y-b,0);
2561 qglVertex3f (x+b,y-b,0);
2567 void XYWnd::DrawCameraIcon()
2569 float x, y, a, fov, box;
2571 fov = 48 / m_fScale;
2572 box = 16 / m_fScale;
2574 if (m_nViewType == XY)
2576 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
2577 y = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
2578 a = g_pParentWnd->GetCamWnd()->Camera()->angles[YAW]/180*Q_PI;
2580 else if (m_nViewType == YZ)
2582 x = g_pParentWnd->GetCamWnd()->Camera()->origin[1];
2583 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
2584 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
2588 x = g_pParentWnd->GetCamWnd()->Camera()->origin[0];
2589 y = g_pParentWnd->GetCamWnd()->Camera()->origin[2];
2590 a = g_pParentWnd->GetCamWnd()->Camera()->angles[PITCH]/180*Q_PI;
2593 qglColor3f (0.0, 0.0, 1.0);
2594 qglBegin(GL_LINE_STRIP);
2595 qglVertex3f (x-box,y,0);
2596 qglVertex3f (x,y+(box/2),0);
2597 qglVertex3f (x+box,y,0);
2598 qglVertex3f (x,y-(box/2),0);
2599 qglVertex3f (x-box,y,0);
2600 qglVertex3f (x+box,y,0);
2603 qglBegin(GL_LINE_STRIP);
2604 qglVertex3f (x+fov*cos(a+Q_PI/4), y+fov*sin(a+Q_PI/4), 0);
2605 qglVertex3f (x, y, 0);
2606 qglVertex3f (x+fov*cos(a-Q_PI/4), y+fov*sin(a-Q_PI/4), 0);
2611 void XYWnd::DrawZIcon (void)
2613 if (m_nViewType == XY)
2615 float x = z.origin[0];
2616 float y = z.origin[1];
2617 float zdim = 8 / m_fScale;
2618 qglEnable (GL_BLEND);
2619 qglDisable (GL_TEXTURE_2D);
2620 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
2621 qglDisable (GL_CULL_FACE);
2622 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2623 qglColor4f (0.0, 0.0, 1.0, 0.25);
2625 qglVertex3f (x-zdim,y-zdim,0);
2626 qglVertex3f (x+zdim,y-zdim,0);
2627 qglVertex3f (x+zdim,y+zdim,0);
2628 qglVertex3f (x-zdim,y+zdim,0);
2630 qglDisable (GL_BLEND);
2632 qglColor4f (0.0, 0.0, 1.0, 1);
2634 qglBegin(GL_LINE_LOOP);
2635 qglVertex3f (x-zdim,y-zdim,0);
2636 qglVertex3f (x+zdim,y-zdim,0);
2637 qglVertex3f (x+zdim,y+zdim,0);
2638 qglVertex3f (x-zdim,y+zdim,0);
2641 qglBegin(GL_LINE_STRIP);
2642 qglVertex3f (x-(zdim/2),y+(zdim/2),0);
2643 qglVertex3f (x+(zdim/2),y+(zdim/2),0);
2644 qglVertex3f (x-(zdim/2),y-(zdim/2),0);
2645 qglVertex3f (x+(zdim/2),y-(zdim/2),0);
2650 // can be greatly simplified but per usual i am in a hurry
2651 // which is not an excuse, just a fact
2652 void XYWnd::PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds)
2654 const char* g_pDimStrings[] = {"x:%.f", "y:%.f", "z:%.f"};
2655 const char* g_pOrgStrings[] = {"(x:%.f y:%.f)", "(x:%.f z:%.f)", "(y:%.f z:%.f)"};
2660 VectorSubtract(vMaxBounds, vMinBounds, vSize);
2662 qglColor3f(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][0] * .65,
2663 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][1] * .65,
2664 g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES][2] * .65);
2666 if (m_nViewType == XY)
2668 qglBegin (GL_LINES);
2670 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
2671 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2673 qglVertex3f(vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2674 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2676 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale, 0.0f);
2677 qglVertex3f(vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale, 0.0f);
2680 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2681 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2683 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2], 0.0f);
2684 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2686 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2687 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2], 0.0f);
2691 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale, 0.0f);
2692 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2693 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2695 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]), 0.0f);
2696 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2697 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2699 qglRasterPos3f (vMinBounds[nDim1] + 4, vMaxBounds[nDim2] + 8 / m_fScale, 0.0f);
2700 g_strDim.Format(g_pOrgStrings[0], vMinBounds[nDim1], vMaxBounds[nDim2]);
2701 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2703 else if (m_nViewType == XZ)
2705 qglBegin (GL_LINES);
2707 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 6.0f / m_fScale);
2708 qglVertex3f(vMinBounds[nDim1], 0, vMinBounds[nDim2] - 10.0f / m_fScale);
2710 qglVertex3f(vMinBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2711 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2713 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 6.0f / m_fScale);
2714 qglVertex3f(vMaxBounds[nDim1], 0,vMinBounds[nDim2] - 10.0f / m_fScale);
2717 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMinBounds[nDim2]);
2718 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
2720 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMinBounds[nDim2]);
2721 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
2723 qglVertex3f(vMaxBounds[nDim1] + 6.0f / m_fScale, 0,vMaxBounds[nDim2]);
2724 qglVertex3f(vMaxBounds[nDim1] + 10.0f / m_fScale, 0,vMaxBounds[nDim2]);
2728 qglRasterPos3f (Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), 0, vMinBounds[nDim2] - 20.0 / m_fScale);
2729 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2730 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2732 qglRasterPos3f (vMaxBounds[nDim1] + 16.0 / m_fScale, 0, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
2733 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2734 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2736 qglRasterPos3f (vMinBounds[nDim1] + 4, 0, vMaxBounds[nDim2] + 8 / m_fScale);
2737 g_strDim.Format(g_pOrgStrings[1], vMinBounds[nDim1], vMaxBounds[nDim2]);
2738 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2742 qglBegin (GL_LINES);
2744 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
2745 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2747 qglVertex3f(0, vMinBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2748 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2750 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 6.0f / m_fScale);
2751 qglVertex3f(0, vMaxBounds[nDim1], vMinBounds[nDim2] - 10.0f / m_fScale);
2754 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMinBounds[nDim2]);
2755 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
2757 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMinBounds[nDim2]);
2758 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
2760 qglVertex3f(0, vMaxBounds[nDim1] + 6.0f / m_fScale, vMaxBounds[nDim2]);
2761 qglVertex3f(0, vMaxBounds[nDim1] + 10.0f / m_fScale, vMaxBounds[nDim2]);
2765 qglRasterPos3f (0, Betwixt(vMinBounds[nDim1], vMaxBounds[nDim1]), vMinBounds[nDim2] - 20.0 / m_fScale);
2766 g_strDim.Format(g_pDimStrings[nDim1], vSize[nDim1]);
2767 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2769 qglRasterPos3f (0, vMaxBounds[nDim1] + 16.0 / m_fScale, Betwixt(vMinBounds[nDim2], vMaxBounds[nDim2]));
2770 g_strDim.Format(g_pDimStrings[nDim2], vSize[nDim2]);
2771 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2773 qglRasterPos3f (0, vMinBounds[nDim1] + 4.0, vMaxBounds[nDim2] + 8 / m_fScale);
2774 g_strDim.Format(g_pOrgStrings[2], vMinBounds[nDim1], vMaxBounds[nDim2]);
2775 gtk_glwidget_print_string((char *) g_strDim.GetBuffer());
2784 #define ALT_POINT_SIZE 4
2785 // Alternative to GL_POINTS (for; vertex handles, patch handles, clip points, path points)
2786 void DrawAlternatePoint(vec3_t v, float scale)
2790 scale = g_pParentWnd->GetXYWnd()->Scale();
2791 //scale = g_qeglobals.d_xyOld.scale;
2794 // ugly gl_line cross
2795 qglVertex3f ( v[0]+(ALT_POINT_SIZE/scale), v[1], v[2] );
2796 qglVertex3f ( v[0]-(ALT_POINT_SIZE/scale), v[1], v[2] );
2797 qglVertex3f ( v[0], v[1]+(ALT_POINT_SIZE/scale), v[2] );
2798 qglVertex3f ( v[0], v[1]-(ALT_POINT_SIZE/scale), v[2] );
2799 qglVertex3f ( v[0], v[1], v[2]+(ALT_POINT_SIZE/scale) );
2800 qglVertex3f ( v[0], v[1], v[2]-(ALT_POINT_SIZE/scale) );
2806 extern void DrawBrushEntityName (brush_t *b);
2808 //#define DBG_SCENEDUMP
2810 void XYWnd::XY_Draw()
2812 #ifdef DBG_SCENEDUMP
2813 static time_t s_start = 0; // we use that to dump the selected stuff every 2 seconds
2818 if ((now - s_start) > 3)
2822 Sys_FPrintf(SYS_WRN, "Starting scene dump\n");
2831 double start2, end2;
2836 if (!active_brushes.next)
2837 return; // not valid yet
2839 Patch_LODMatchAll(); // spog
2842 start = Sys_DoubleTime();
2848 qglViewport(0, 0, m_nWidth, m_nHeight);
2849 qglClearColor (g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][0],
2850 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][1],
2851 g_qeglobals.d_savedinfo.colors[COLOR_GRIDBACK][2],0);
2853 qglClear(GL_COLOR_BUFFER_BIT);
2858 qglMatrixMode(GL_PROJECTION);
2861 w = m_nWidth / 2 / m_fScale;
2862 h = m_nHeight / 2/ m_fScale;
2864 // fix GL_INVALID_VALUE error on first time the window is updated (win32)
2868 int nDim1 = (m_nViewType == YZ) ? 1 : 0;
2869 int nDim2 = (m_nViewType == XY) ? 1 : 2;
2870 mins[0] = m_vOrigin[nDim1] - w;
2871 maxs[0] = m_vOrigin[nDim1] + w;
2872 mins[1] = m_vOrigin[nDim2] - h;
2873 maxs[1] = m_vOrigin[nDim2] + h;
2875 qglOrtho (mins[0], maxs[0], mins[1], maxs[1], g_MinWorldCoord, g_MaxWorldCoord);
2877 qglMatrixMode(GL_MODELVIEW);
2881 // now draw the grid
2888 if ( g_qeglobals.show_blocks)
2889 XY_DrawBlockGrid ();
2891 if (m_nViewType != XY)
2894 if (m_nViewType == YZ)
2895 qglRotatef (-90, 0, 1, 0); // put Z going up
2896 qglRotatef (-90, 1, 0, 0); // put Z going up
2902 qglShadeModel (GL_FLAT);
2903 qglDisable(GL_TEXTURE_2D);
2904 qglDisable(GL_TEXTURE_1D);
2905 qglDisable(GL_DEPTH_TEST);
2906 qglDisable(GL_BLEND);
2907 qglDisable(GL_CULL_FACE);
2908 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
2909 qglColor3f(0, 0, 0);
2910 qglEnableClientState(GL_VERTEX_ARRAY);
2912 // Fishman - Add antialiazed points and lines support. 09/15/00
2913 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
2915 qglEnable(GL_BLEND);
2916 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2917 qglEnable(GL_POINT_SMOOTH);
2918 qglEnable(GL_LINE_SMOOTH);
2926 start2 = Sys_DoubleTime();
2928 for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
2930 if (brush->bFiltered)
2933 if (brush->mins[nDim1] > maxs[0] ||
2934 brush->mins[nDim2] > maxs[1] ||
2935 brush->maxs[nDim1] < mins[0] ||
2936 brush->maxs[nDim2] < mins[1])
2939 continue; // off screen
2944 if (brush->owner != e && brush->owner)
2946 qglColor3fv(brush->owner->eclass->color);
2950 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_BRUSHES]);
2953 #ifdef DBG_SCENEDUMP
2956 Sys_FPrintf(SYS_WRN, "Active brush: %p ", brush);
2957 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
2961 Brush_DrawXY(brush, m_nViewType);
2965 end2 = Sys_DoubleTime();
2972 //++timo why is the display list broken?
2973 if ( g_qeglobals.d_pointfile_display_list)
2977 // now draw selected brushes
2981 qglColor3f(0.8f, 0.1f, 0.9f);
2984 qglColor3f(0.1f, 0.8f, 0.1f);
2986 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_SELBRUSHES]);
2989 if (g_PrefsDlg.m_bNoStipple == FALSE)
2991 qglEnable (GL_LINE_STIPPLE);
2992 qglLineStipple (3, 0xaaaa);
2998 vMinBounds[0] = vMinBounds[1] = vMinBounds[2] = g_MaxWorldCoord;
2999 vMaxBounds[0] = vMaxBounds[1] = vMaxBounds[2] = g_MinWorldCoord;
3001 int nSaveDrawn = drawn;
3002 bool bFixedSize = false;
3003 for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
3005 // spog - added culling of selected brushes in XY window
3006 if (brush->mins[nDim1] > maxs[0] ||
3007 brush->mins[nDim2] > maxs[1] ||
3008 brush->maxs[nDim1] < mins[0] ||
3009 brush->maxs[nDim2] < mins[1])
3012 continue; // off screen
3015 #ifdef DBG_SCENEDUMP
3018 Sys_FPrintf(SYS_WRN, "Selected brush: %p ", brush);
3019 Sys_FPrintf(SYS_WRN, "owner->eclass: %s\n", brush->owner->eclass->name);
3022 Brush_DrawXY(brush, m_nViewType);
3026 if (brush->owner->eclass->fixedsize)
3028 if (g_PrefsDlg.m_bSizePaint)
3030 for (i = 0; i < 3; i ++)
3032 if (brush->mins[i] < vMinBounds[i])
3033 vMinBounds[i] = brush->mins[i];
3034 if (brush->maxs[i] > vMaxBounds[i])
3035 vMaxBounds[i] = brush->maxs[i];
3041 if (g_PrefsDlg.m_bNoStipple == FALSE)
3043 qglDisable (GL_LINE_STIPPLE);
3047 if (!bFixedSize && !RotateMode() && !ScaleMode() && drawn - nSaveDrawn > 0 && g_PrefsDlg.m_bSizePaint)
3048 PaintSizeInfo(nDim1, nDim2, vMinBounds, vMaxBounds);
3050 // edge / vertex flags
3051 if (g_qeglobals.d_select_mode == sel_vertex)
3053 if(!g_PrefsDlg.m_bGlPtWorkaround)
3058 qglBegin (GL_POINTS);
3059 for (i=0 ; i<g_qeglobals.d_numpoints ; i++)
3060 qglVertex3fv (g_qeglobals.d_points[i]);
3063 if(g_qeglobals.d_num_move_points)
3065 // selected brush verts
3068 qglBegin (GL_POINTS);
3069 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
3070 qglVertex3fv (g_qeglobals.d_move_points[i]);
3080 qglBegin (GL_LINES);
3081 for (i=0; i < g_qeglobals.d_numpoints; i++)
3082 DrawAlternatePoint(g_qeglobals.d_points[i], m_fScale);
3085 if(g_qeglobals.d_num_move_points)
3087 // selected brush verts
3090 qglBegin (GL_LINES);
3091 for(i = 0; i < g_qeglobals.d_num_move_points; i++)
3092 qglVertex3fv (g_qeglobals.d_move_points[i]);
3098 else if (g_qeglobals.d_select_mode == sel_edge)
3101 if(!g_PrefsDlg.m_bGlPtWorkaround)
3105 qglBegin (GL_POINTS);
3106 for (i=0 ; i<g_qeglobals.d_numedges ; i++)
3108 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
3109 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
3110 qglVertex3f ( (v1[0]+v2[0])*0.5,(v1[1]+v2[1])*0.5,(v1[2]+v2[2])*0.5);
3118 qglBegin (GL_LINES);
3119 for (i=0; i < g_qeglobals.d_numedges; i++)
3121 v1 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p1];
3122 v2 = g_qeglobals.d_points[g_qeglobals.d_edges[i].p2];
3124 v3[0] = (v1[0]+v2[0])*0.5;
3125 v3[1] = (v1[1]+v2[1])*0.5;
3126 v3[2] = (v1[2]+v2[2])*0.5;
3127 DrawAlternatePoint(v3, m_fScale);
3134 if (!(m_nViewType == XY))
3137 // area selection hack
3138 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)))
3140 qglEnable (GL_BLEND);
3141 qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
3142 qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3143 qglColor4f(0.0, 0.0, 1.0, 0.25);
3144 qglRectf(g_qeglobals.d_vAreaTL[nDim1], g_qeglobals.d_vAreaTL[nDim2], g_qeglobals.d_vAreaBR[nDim1], g_qeglobals.d_vAreaBR[nDim2]);
3145 qglPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
3146 qglDisable (GL_BLEND);
3152 // now draw camera point
3163 //++timo TODO: use an object for the 2D view
3164 Draw2DPluginEntities( (VIEWTYPE)m_nViewType );
3166 if (g_qeglobals.d_savedinfo.show_outline)
3170 qglMatrixMode (GL_PROJECTION);
3173 qglOrtho (0, m_nWidth, 0, m_nHeight, 0, 1);
3174 qglMatrixMode (GL_MODELVIEW);
3178 // four view mode doesn't colorize
3179 if (g_pParentWnd->CurrentStyle() == MainFrame::eSplit)
3180 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_VIEWNAME]);
3182 qglColor3fv( g_qeglobals.d_savedinfo.AxisColors[m_nViewType]);
3183 qglBegin (GL_LINE_LOOP);
3185 qglVertex2i (m_nWidth-1, 0);
3186 qglVertex2i (m_nWidth-1, m_nHeight-1);
3187 qglVertex2i (0, m_nHeight-1);
3190 qglMatrixMode (GL_PROJECTION);
3192 qglMatrixMode (GL_MODELVIEW);
3201 end = Sys_DoubleTime ();
3202 i = (int)(1000*(end-start));
3203 int i3 = (int)(1000*(end2-start2));
3206 int i2 = g_lTotal / g_lCount;
3207 Sys_Printf ("xy: %i ab: %i avg: %i\n", i, i3, i2);
3210 // Fishman - Add antialiazed points and lines support. 09/03/00
3211 if (g_PrefsDlg.m_bAntialiasedPointsAndLines)
3213 qglDisable(GL_POINT_SMOOTH);
3214 qglDisable(GL_LINE_SMOOTH);
3215 qglDisable(GL_BLEND);
3227 void XYWnd::UndoClear()
3231 void XYWnd::UndoCopy()
3235 bool XYWnd::UndoAvailable()
3237 return (g_brUndo.next != &g_brUndo);
3244 // should be static as should be the rotate scale stuff
3245 bool XYWnd::AreaSelectOK()
3247 return RotateMode() ? false : ScaleMode() ? false : true;
3250 void XYWnd::OnCreate ()
3252 if (!MakeCurrent ())
3253 Error ("glXMakeCurrent failed");
3255 qglPolygonStipple ((unsigned char *)s_stipple);
3256 qglLineStipple (3, 0xaaaa);
3259 void XYWnd::OnExpose ()
3262 if (!MakeCurrent ())
3264 Sys_Printf("ERROR: glXMakeCurrent failed.. Error:%i\n",qglGetError());
3265 Sys_Printf("Please restart Radiant if the Map view is not working\n");
3270 QE_CheckOpenGLForErrors();
3272 QE_CheckOpenGLForErrors();
3274 if (m_nViewType != XY)
3277 if (m_nViewType == YZ)
3278 qglRotatef (-90, 0, 1, 0); // put Z going up
3279 qglRotatef (-90, 1, 0, 0); // put Z going up
3284 qglColor4f(0.2f, 0.9f, 0.2f, 0.8f);
3285 qglBegin (GL_LINES);
3286 if (m_nViewType == XY)
3288 qglVertex2f(2*g_MinWorldCoord, tdp[1]);
3289 qglVertex2f(2*g_MaxWorldCoord, tdp[1]);
3290 qglVertex2f(tdp[0], 2*g_MinWorldCoord);
3291 qglVertex2f(tdp[0], 2*g_MaxWorldCoord);
3293 else if (m_nViewType == YZ)
3295 qglVertex3f(tdp[0], 2*g_MinWorldCoord, tdp[2]);
3296 qglVertex3f(tdp[0], 2*g_MaxWorldCoord, tdp[2]);
3297 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
3298 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
3302 qglVertex3f (2*g_MinWorldCoord, tdp[1], tdp[2]);
3303 qglVertex3f (2*g_MaxWorldCoord, tdp[1], tdp[2]);
3304 qglVertex3f(tdp[0], tdp[1], 2*g_MinWorldCoord);
3305 qglVertex3f(tdp[0], tdp[1], 2*g_MaxWorldCoord);
3314 g_Clip1.Draw(m_fScale, 1); // qglVertex3fv (g_Clip1);
3316 g_Clip2.Draw(m_fScale, 2); // qglVertex3fv (g_Clip2);
3318 g_Clip3.Draw(m_fScale, 3); // qglVertex3fv (g_Clip3);
3319 if (g_Clip1.Set() && g_Clip2.Set())
3321 ProduceSplitLists();
3323 brush_t* pList = (g_bSwitch) ? &g_brBackSplits : &g_brFrontSplits;
3324 for (pBrush = pList->next ; pBrush != NULL && pBrush != pList ; pBrush=pBrush->next)
3329 for (face = pBrush->brush_faces,order = 0 ; face ; face=face->next, order++)
3331 winding_t* w = face->face_winding;
3335 qglBegin(GL_LINE_LOOP);
3336 for (int i=0 ; i<w->numpoints ; i++)
3337 qglVertex3fv(w->points[i]);
3347 for (n = 0; n < g_nPathCount; n++)
3348 g_PathPoints[n].Draw(m_fScale, n+1); // qglVertex3fv(g_PathPoints[n]);
3350 if (m_nViewType != XY)
3353 m_XORRectangle.set(rectangle_t());
3358 void XYWnd::KillPathMode()
3361 g_bPathMode = false;
3363 g_pPathFunc(false, g_nPathCount);
3366 Sys_UpdateWindows(W_ALL);
3369 // gets called for drop down menu messages
3370 // TIP: it's not always about EntityCreate
3371 void XYWnd::OnEntityCreate (const char* item)
3373 Undo_Start("create entity");
3374 Undo_AddBrushList(&selected_brushes);
3376 if (m_mnuDrop != NULL)
3381 if (strItem.CompareNoCase("Add to...") == 0)
3383 //++timo TODO: fill the menu with current groups?
3384 // this one is for adding to existing groups only
3385 Sys_Printf("TODO: Add to... in XYWnd::OnEntityCreate\n");
3387 else if (strItem.CompareNoCase("Remove") == 0)
3389 // remove selected brushes from their current group
3391 for( b = selected_brushes.next; b != &selected_brushes; b = b->next )
3397 //++timo FIXME: remove when all hooks are in
3398 if (strItem.CompareNoCase("Add to...") == 0
3399 || strItem.CompareNoCase("Remove") == 0
3400 || strItem.CompareNoCase("Name...") == 0
3401 || strItem.CompareNoCase("New group...") == 0)
3403 Sys_Printf("TODO: hook drop down group menu\n");
3407 if (strItem.Find("Smart_") >= 0)
3409 CreateSmartEntity(this, m_ptDownX, m_ptDownY, strItem);
3413 CreateRightClickEntity(this, m_ptDownX, m_ptDownY, (char*)strItem.GetBuffer());
3416 Sys_UpdateWindows(W_ALL);
3417 //OnLButtonDown((MK_LBUTTON | MK_SHIFT), CPoint(m_ptDown.x+2, m_ptDown.y+2));
3419 Undo_EndBrushList(&selected_brushes);
3423 /* Drawing clip points */
3424 void ClipPoint::Draw(float fScale, int num)
3427 strLabel.Format("%d", num);
3428 Draw(fScale, strLabel.GetBuffer());
3431 #define ALT_POINT_VERTS 6
3433 void ClipPoint::Draw(float fScale, const char *label)
3436 if(!g_PrefsDlg.m_bGlPtWorkaround)
3439 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
3440 qglBegin (GL_POINTS);
3441 qglVertex3fv (m_ptClip);
3447 qglColor3fv(g_qeglobals.d_savedinfo.colors[COLOR_CLIPPER]);
3449 qglBegin (GL_LINES);
3450 DrawAlternatePoint(m_ptClip, fScale);
3456 qglRasterPos3f (m_ptClip[0]+2, m_ptClip[1]+2, m_ptClip[2]+2);
3457 qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);