From 952c5c128f9efaea89d41d882c4ea3ade7df4591 Mon Sep 17 00:00:00 2001 From: zakk Date: Fri, 26 Aug 2005 04:48:05 +0000 Subject: Itsa me, quake3io! git-svn-id: svn://svn.icculus.org/quake3/trunk@2 edf5b092-35ff-0310-97b2-ce42778d08ea --- q3radiant/SELECT.CPP | 1800 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1800 insertions(+) create mode 100755 q3radiant/SELECT.CPP (limited to 'q3radiant/SELECT.CPP') diff --git a/q3radiant/SELECT.CPP b/q3radiant/SELECT.CPP new file mode 100755 index 0000000..8ccf7f0 --- /dev/null +++ b/q3radiant/SELECT.CPP @@ -0,0 +1,1800 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// select.c +#include "stdafx.h" +#include "qe3.h" + + +// externs +CPtrArray g_SelectedFaces; +CPtrArray g_SelectedFaceBrushes; +CPtrArray& g_ptrSelectedFaces = g_SelectedFaces; +CPtrArray& g_ptrSelectedFaceBrushes = g_SelectedFaceBrushes; + + +void clearSelection() { + g_qeglobals.d_select_mode = sel_brush; + g_qeglobals.selectObject = NULL; +} + +/* +=========== +Test_Ray +=========== +*/ +#define DIST_START 999999 +trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags) +{ + brush_t *brush; + face_t *face; + float dist; + trace_t t; + + memset (&t, 0, sizeof(t)); + t.dist = DIST_START; + + if (flags & SF_CYCLE) + { + CPtrArray array; + brush_t *pToSelect = (selected_brushes.next != &selected_brushes) ? selected_brushes.next : NULL; + Select_Deselect(); + + // go through active brushes and accumulate all "hit" brushes + for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) + { + //if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) + // continue; + + if (FilterBrush (brush)) + continue; + + if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush) + continue; + + if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush ) + continue; + + //if (!g_bShowPatchBounds && brush->patchBrush) + // continue; + + face = Brush_Ray (origin, dir, brush, &dist); + + if (face) + { + if ( brush->terrainBrush ) + { + Terrain_Ray( origin, dir, brush, &dist ); + if( dist == 0 ) + { + // didn't actually hit the terrain + continue; + } + } + array.Add(brush); + } + } + + int nSize = array.GetSize(); + if (nSize > 0) + { + bool bFound = false; + for (int i = 0; i < nSize; i++) + { + brush_t *b = reinterpret_cast(array.GetAt(i)); + // did we hit the last one selected yet ? + if (b == pToSelect) + { + // yes we want to select the next one in the list + int n = (i > 0) ? i-1 : nSize-1; + pToSelect = reinterpret_cast(array.GetAt(n)); + bFound = true; + break; + } + } + if (!bFound) + pToSelect = reinterpret_cast(array.GetAt(0)); + } + if (pToSelect) + { + face = Brush_Ray (origin, dir, pToSelect, &dist); + if ( pToSelect->terrainBrush ) + { + t.terraface = Terrain_Ray( origin, dir, pToSelect, &dist ); + } + + t.dist = dist; + t.brush = pToSelect; + t.face = face; + t.selected = false; + return t; + } + } + + if (! (flags & SF_SELECTED_ONLY) ) + { + for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next) + { + if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) + continue; + + if (FilterBrush (brush)) + continue; + + if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush) + continue; + + if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush ) + continue; + + //if (!g_bShowPatchBounds && brush->patchBrush) + // continue; + + face = Brush_Ray (origin, dir, brush, &dist); + if ( face ) { + if ( brush->terrainBrush ) + { + t.terraface = Terrain_Ray( origin, dir, brush, &dist ); + } + } + if (dist > 0 && dist < t.dist) + { + t.dist = dist; + t.brush = brush; + t.face = face; + t.selected = false; + } + } + } + + + for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next) + { + if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity) + continue; + + if (FilterBrush (brush)) + continue; + + if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush) + continue; + + if( !g_PrefsDlg.m_bSelectTerrain && brush->terrainBrush ) + continue; + + face = Brush_Ray (origin, dir, brush, &dist); + if ( face ) { + if ( brush->terrainBrush ) + { + t.terraface = Terrain_Ray( origin, dir, brush, &dist ); + } + } + if (dist > 0 && dist < t.dist) + { + t.dist = dist; + t.brush = brush; + t.face = face; + t.selected = true; + } + } + + // if entites first, but didn't find any, check regular + + if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL) + return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST); + + return t; + +} + + +/* +============ +Select_Brush + +============ +*/ +void Select_Brush (brush_t *brush, bool bComplete, bool bStatus) +{ + brush_t *b; + entity_t *e; + + g_ptrSelectedFaces.RemoveAll(); + g_ptrSelectedFaceBrushes.RemoveAll(); + //selected_face = NULL; + if (g_qeglobals.d_select_count < 2) + g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush; + g_qeglobals.d_select_count++; + + //if (brush->patchBrush) + // Patch_Select(brush->nPatchID); + + e = brush->owner; + if (e) + { + // select complete entity on first click + if (e != world_entity && bComplete == true) + { + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + if (b->owner == e) + goto singleselect; + for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + else + { +singleselect: + Brush_RemoveFromList (brush); + Brush_AddToList (brush, &selected_brushes); + UpdateSurfaceDialog(); + UpdatePatchInspector(); + } + + if (e->eclass) + { + UpdateEntitySel(brush->owner->eclass); + } + } + if (bStatus) + { + vec3_t vMin, vMax, vSize; + Select_GetBounds (vMin, vMax); + VectorSubtract(vMax, vMin, vSize); + CString strStatus; + strStatus.Format("Selection X:: %.1f Y:: %.1f Z:: %.1f", vSize[0], vSize[1], vSize[2]); + g_pParentWnd->SetStatusText(2, strStatus); + } +} + + +/* +============ +Select_Ray + +If the origin is inside a brush, that brush will be ignored. +============ +*/ +void Select_Ray (vec3_t origin, vec3_t dir, int flags) +{ + trace_t t; + + t = Test_Ray (origin, dir, flags); + if (!t.brush) + return; + + if (flags == SF_SINGLEFACE) + { + int nCount = g_SelectedFaces.GetSize(); + bool bOk = true; + for (int i = 0; i < nCount; i++) + { + if (t.face == reinterpret_cast(g_SelectedFaces.GetAt(i))) + { + bOk = false; + // need to move remove i'th entry + g_SelectedFaces.RemoveAt(i, 1); + g_SelectedFaceBrushes.RemoveAt(i, 1); + } + } + if (bOk) + { + g_SelectedFaces.Add(t.face); + g_SelectedFaceBrushes.Add(t.brush); + } + //selected_face = t.face; + //selected_face_brush = t.brush; + Sys_UpdateWindows (W_ALL); + clearSelection(); + // Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2 height=2 texture + brushprimit_texdef_t brushprimit_texdef; + ConvertTexMatWithQTexture ( &t.face->brushprimit_texdef, t.face->d_texture, &brushprimit_texdef, NULL ); + Texture_SetTexture ( &t.face->texdef, &brushprimit_texdef, false, GETPLUGINTEXDEF(t.face), false ); + UpdateSurfaceDialog(); + return; + } + + // move the brush to the other list + + clearSelection(); + + if (t.selected) + { + Brush_RemoveFromList (t.brush); + Brush_AddToList (t.brush, &active_brushes); + UpdatePatchInspector(); + } + else + { + Select_Brush (t.brush, !(GetKeyState(VK_MENU) & 0x8000)); + } + + Sys_UpdateWindows (W_ALL); +} + + +void Select_Delete (void) +{ + brush_t *brush; + + g_ptrSelectedFaces.RemoveAll(); + g_ptrSelectedFaceBrushes.RemoveAll(); + //selected_face = NULL; + + clearSelection(); + + g_qeglobals.d_select_count = 0; + g_qeglobals.d_num_move_points = 0; + while (selected_brushes.next != &selected_brushes) + { + brush = selected_brushes.next; + if (brush->patchBrush) + { + //Patch_Delete(brush->nPatchID); + Patch_Delete(brush->pPatch); + } + if (brush->terrainBrush) + { + Terrain_Delete(brush->pTerrain ); + } + + Brush_Free (brush); + } + + // FIXME: remove any entities with no brushes + + Sys_UpdateWindows (W_ALL); +} + +void Select_Deselect (bool bDeselectFaces) +{ + brush_t *b; + + Patch_Deselect(); + + g_pParentWnd->ActiveXY()->UndoClear(); + + g_qeglobals.d_workcount++; + g_qeglobals.d_select_count = 0; + g_qeglobals.d_num_move_points = 0; + b = selected_brushes.next; + + if (b == &selected_brushes) + { + if (bDeselectFaces) + { + g_ptrSelectedFaces.RemoveAll(); + g_ptrSelectedFaceBrushes.RemoveAll(); + //selected_face = NULL; + } + Sys_UpdateWindows (W_ALL); + return; + } + + if (bDeselectFaces) + { + g_ptrSelectedFaces.RemoveAll(); + g_ptrSelectedFaceBrushes.RemoveAll(); + //selected_face = NULL; + } + + clearSelection(); + + // grab top / bottom height for new brushes + if (b->mins[2] < b->maxs[2]) + { + g_qeglobals.d_new_brush_bottom_z = b->mins[2]; + g_qeglobals.d_new_brush_top_z = b->maxs[2]; + } + + selected_brushes.next->prev = &active_brushes; + selected_brushes.prev->next = active_brushes.next; + active_brushes.next->prev = selected_brushes.prev; + active_brushes.next = selected_brushes.next; + selected_brushes.prev = selected_brushes.next = &selected_brushes; + + Sys_UpdateWindows (W_ALL); +} + +/* +============ +Select_Move +============ +*/ +void Select_Move (vec3_t delta, bool bSnap) +{ + brush_t *b; + + +// actually move the selected brushes + for (b = selected_brushes.next ; b != &selected_brushes ; b=b->next) + Brush_Move (b, delta, bSnap); + + vec3_t vMin, vMax; + Select_GetBounds (vMin, vMax); + CString strStatus; + strStatus.Format("Origin X:: %.1f Y:: %.1f Z:: %.1f", vMin[0], vMax[1], vMax[2]); + g_pParentWnd->SetStatusText(2, strStatus); + +// Sys_UpdateWindows (W_ALL); +} + +/* +============ +Select_Clone + +Creates an exact duplicate of the selection in place, then moves +the selected brushes off of their old positions +============ +*/ +void Select_Clone (void) +{ +#if 1 + ASSERT(g_pParentWnd->ActiveXY()); + g_bScreenUpdates = false; + g_pParentWnd->ActiveXY()->Copy(); + g_pParentWnd->ActiveXY()->Paste(); + g_pParentWnd->NudgeSelection(2, g_qeglobals.d_gridsize); + g_pParentWnd->NudgeSelection(3, g_qeglobals.d_gridsize); + g_bScreenUpdates = true; + Sys_UpdateWindows(W_ALL); +#else + + brush_t *b, *b2, *n, *next, *next2; + vec3_t delta; + entity_t *e; + + g_qeglobals.d_workcount++; + clearSelection(); + + delta[0] = g_qeglobals.d_gridsize; + delta[1] = g_qeglobals.d_gridsize; + delta[2] = 0; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=next) + { + next = b->next; + // if the brush is a world brush, handle simply + if (b->owner == world_entity) + { + n = Brush_Clone (b); + Brush_AddToList (n, &active_brushes); + Entity_LinkBrush (world_entity, n); + Brush_Build( n ); + Brush_Move (b, delta); + continue; + } + + e = Entity_Clone (b->owner); + // clear the target / targetname + DeleteKey (e, "target"); + DeleteKey (e, "targetname"); + + // if the brush is a fixed size entity, create a new entity + if (b->owner->eclass->fixedsize) + { + n = Brush_Clone (b); + Brush_AddToList (n, &active_brushes); + Entity_LinkBrush (e, n); + Brush_Build( n ); + Brush_Move (b, delta); + continue; + } + + // brush is a complex entity, grab all the other ones now + + next = &selected_brushes; + + for ( b2 = b ; b2 != &selected_brushes ; b2=next2) + { + next2 = b2->next; + if (b2->owner != b->owner) + { + if (next == &selected_brushes) + next = b2; + continue; + } + + // move b2 to the start of selected_brushes, + // so it won't be hit again + Brush_RemoveFromList (b2); + Brush_AddToList (b2, &selected_brushes); + + n = Brush_Clone (b2); + Brush_AddToList (n, &active_brushes); + Entity_LinkBrush (e, n); + Brush_Build( n ); + Brush_Move (b2, delta, true); + } + + } + Sys_UpdateWindows (W_ALL); +#endif +} + + + +/* +============ +Select_SetTexture +Timo : bFitScale to compute scale on the plane and counteract plane / axial plane snapping +Timo : brush primitive texturing + the brushprimit_texdef given must be understood as a qtexture_t width=2 height=2 ( HiRes ) +Timo : texture plugin, added an IPluginTexdef* parameter + must be casted to an IPluginTexdef! + if not NULL, get ->Copy() of it into each face or brush ( and remember to hook ) + if NULL, means we have no information, ask for a default +============ +*/ +void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef ) +{ + brush_t *b; + int nCount = g_ptrSelectedFaces.GetSize(); + if (nCount > 0) + { + Undo_Start("set face textures"); + ASSERT(g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize()); + for (int i = 0; i < nCount; i++) + { + face_t *selFace = reinterpret_cast(g_ptrSelectedFaces.GetAt(i)); + brush_t *selBrush = reinterpret_cast(g_ptrSelectedFaceBrushes.GetAt(i)); + Undo_AddBrush(selBrush); + SetFaceTexdef (selBrush, selFace, texdef, brushprimit_texdef, bFitScale, static_cast(pPlugTexdef) ); + Brush_Build(selBrush, bFitScale); + Undo_EndBrush(selBrush); + } + Undo_End(); + } + else if (selected_brushes.next != &selected_brushes) + { + Undo_Start("set brush textures"); + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + if (!b->owner->eclass->fixedsize) + { + Undo_AddBrush(b); + Brush_SetTexture (b, texdef, brushprimit_texdef, bFitScale, static_cast(pPlugTexdef) ); + Undo_EndBrush(b); + } + Undo_End(); + } + Sys_UpdateWindows (W_ALL); +} + + +/* +================================================================ + + TRANSFORMATIONS + +================================================================ +*/ + +void Select_GetBounds (vec3_t mins, vec3_t maxs) +{ + brush_t *b; + int i; + + for (i=0 ; i<3 ; i++) + { + mins[i] = 99999; + maxs[i] = -99999; + } + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + for (i=0 ; i<3 ; i++) + { + if (b->mins[i] < mins[i]) + mins[i] = b->mins[i]; + if (b->maxs[i] > maxs[i]) + maxs[i] = b->maxs[i]; + } +} + + +void Select_GetTrueMid (vec3_t mid) +{ + vec3_t mins, maxs; + Select_GetBounds (mins, maxs); + + for (int i=0 ; i<3 ; i++) + mid[i] = (mins[i] + ((maxs[i] - mins[i]) / 2)); +} + + +void Select_GetMid (vec3_t mid) +{ + vec3_t mins, maxs; + int i; + + if (g_PrefsDlg.m_bNoClamp) + { + Select_GetTrueMid(mid); + return; + } + + Select_GetBounds (mins, maxs); + + for (i=0 ; i<3 ; i++) + mid[i] = g_qeglobals.d_gridsize*floor ( ( (mins[i] + maxs[i])*0.5 )/g_qeglobals.d_gridsize ); + +} + +vec3_t select_origin; +vec3_t select_matrix[3]; +qboolean select_fliporder; + +void Select_ApplyMatrix (bool bSnap, bool bRotation, int nAxis, float fDeg) +{ + brush_t *b; + face_t *f; + int i, j; + vec3_t temp; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (f=b->brush_faces ; f ; f=f->next) + { + for (i=0 ; i<3 ; i++) + { + VectorSubtract (f->planepts[i], select_origin, temp); + for (j=0 ; j<3 ; j++) + f->planepts[i][j] = DotProduct(temp, select_matrix[j]) + select_origin[j]; + } + if (select_fliporder) + { + VectorCopy (f->planepts[0], temp); + VectorCopy (f->planepts[2], f->planepts[0]); + VectorCopy (temp, f->planepts[2]); + } + } + + if(b->owner->eclass->fixedsize) + { + if (bRotation && b->owner->md3Class) + { + b->owner->vRotation[nAxis] += fDeg; + } + } + + Brush_Build(b, bSnap); + + if (b->patchBrush) + { + //Patch_ApplyMatrix(b->nPatchID, select_origin, select_matrix); + Patch_ApplyMatrix(b->pPatch, select_origin, select_matrix, bSnap); + } + + if (b->terrainBrush) + { + Terrain_ApplyMatrix(b->pTerrain, select_origin, select_matrix, bSnap); + } + + } +} + +void ProjectOnPlane(vec3_t& normal,float dist,vec3_t& ez, vec3_t& p) +{ + if (fabs(ez[0]) == 1) + p[0] = (dist - normal[1] * p[1] - normal[2] * p[2]) / normal[0]; + else if (fabs(ez[1]) == 1) + p[1] = (dist - normal[0] * p[0] - normal[2] * p[2]) / normal[1]; + else + p[2] = (dist - normal[0] * p[0] - normal[1] * p[1]) / normal[2]; +} + +void Back(vec3_t& dir, vec3_t& p) +{ + if (fabs(dir[0]) == 1) + p[0] = 0; + else if (fabs(dir[1]) == 1) + p[1] = 0; + else p[2] = 0; +} + + + +// using scale[0] and scale[1] +void ComputeScale(vec3_t& rex, vec3_t& rey, vec3_t& p, face_t* f) +{ + float px = DotProduct(rex, p); + float py = DotProduct(rey, p); + px *= f->texdef.scale[0]; + py *= f->texdef.scale[1]; + vec3_t aux; + VectorCopy(rex, aux); + VectorScale(aux, px, aux); + VectorCopy(aux, p); + VectorCopy(rey, aux); + VectorScale(aux, py, aux); + VectorAdd(p, aux, p); +} + +void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3) +{ + vec3_t ex,ey,ez; // local axis base + +#ifdef _DEBUG + if (g_qeglobals.m_bBrushPrimitMode) + Sys_Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n"); +#endif + + // compute first local axis base + TextureAxisFromPlane(&f->plane, ex, ey); + CrossProduct(ex, ey, ez); + + vec3_t aux; + VectorCopy(ex, aux); + VectorScale(aux, -f->texdef.shift[0], aux); + VectorCopy(aux, p1); + VectorCopy(ey, aux); + VectorScale(aux, -f->texdef.shift[1], aux); + VectorAdd(p1, aux, p1); + VectorCopy(p1, p2); + VectorAdd(p2, ex, p2); + VectorCopy(p1, p3); + VectorAdd(p3, ey, p3); + VectorCopy(ez, aux); + VectorScale(aux, -f->texdef.rotate, aux); + VectorRotate(p1, aux, p1); + VectorRotate(p2, aux, p2); + VectorRotate(p3, aux, p3); + // computing rotated local axis base + vec3_t rex,rey; + VectorCopy(ex, rex); + VectorRotate(rex, aux, rex); + VectorCopy(ey, rey); + VectorRotate(rey, aux, rey); + + ComputeScale(rex,rey,p1,f); + ComputeScale(rex,rey,p2,f); + ComputeScale(rex,rey,p3,f); + + // project on normal plane + // along ez + // assumes plane normal is normalized + ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p1); + ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p2); + ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p3); +}; + + +void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3) +{ + vec3_t ex,ey,ez; + +#ifdef _DEBUG + if (g_qeglobals.m_bBrushPrimitMode) + Sys_Printf("Warning : illegal call of AbsoluteToLocal in brush primitive mode\n"); +#endif + + // computing new local axis base + TextureAxisFromPlane(&normal2, ex, ey); + CrossProduct(ex, ey, ez); + + // projecting back on (ex,ey) + Back(ez,p1); + Back(ez,p2); + Back(ez,p3); + + vec3_t aux; + // rotation + VectorCopy(p2, aux); + VectorSubtract(aux, p1,aux); + + float x = DotProduct(aux,ex); + float y = DotProduct(aux,ey); + f->texdef.rotate = 180 * atan2(y,x) / Q_PI; + + vec3_t rex,rey; + // computing rotated local axis base + VectorCopy(ez, aux); + VectorScale(aux, f->texdef.rotate, aux); + VectorCopy(ex, rex); + VectorRotate(rex, aux, rex); + VectorCopy(ey, rey); + VectorRotate(rey, aux, rey); + + // scale + VectorCopy(p2, aux); + VectorSubtract(aux, p1, aux); + f->texdef.scale[0] = DotProduct(aux, rex); + VectorCopy(p3, aux); + VectorSubtract(aux, p1, aux); + f->texdef.scale[1] = DotProduct(aux, rey); + + // shift + // only using p1 + x = DotProduct(rex,p1); + y = DotProduct(rey,p1); + x /= f->texdef.scale[0]; + y /= f->texdef.scale[1]; + + VectorCopy(rex, p1); + VectorScale(p1, x, p1); + VectorCopy(rey, aux); + VectorScale(aux, y, aux); + VectorAdd(p1, aux, p1); + VectorCopy(ez, aux); + VectorScale(aux, -f->texdef.rotate, aux); + VectorRotate(p1, aux, p1); + f->texdef.shift[0] = -DotProduct(p1, ex); + f->texdef.shift[1] = -DotProduct(p1, ey); + + // stored rot is good considering local axis base + // change it if necessary + f->texdef.rotate = -f->texdef.rotate; + + Clamp(f->texdef.shift[0], f->d_texture->width); + Clamp(f->texdef.shift[1], f->d_texture->height); + Clamp(f->texdef.rotate, 360); + +} + +void RotateFaceTexture(face_t* f, int nAxis, float fDeg) +{ + vec3_t p1,p2,p3, rota; + p1[0] = p1[1] = p1[2] = 0; + VectorCopy(p1, p2); + VectorCopy(p1, p3); + VectorCopy(p1, rota); + ComputeAbsolute(f, p1, p2, p3); + + rota[nAxis] = fDeg; + VectorRotate(p1, rota, select_origin, p1); + VectorRotate(p2, rota, select_origin, p2); + VectorRotate(p3, rota, select_origin, p3); + + plane_t normal2; + vec3_t vNormal; + vNormal[0] = f->plane.normal[0]; + vNormal[1] = f->plane.normal[1]; + vNormal[2] = f->plane.normal[2]; + VectorRotate(vNormal, rota, vNormal); + normal2.normal[0] = vNormal[0]; + normal2.normal[1] = vNormal[1]; + normal2.normal[2] = vNormal[2]; + AbsoluteToLocal(normal2, f, p1, p2 ,p3); + +} + +void RotateTextures(int nAxis, float fDeg, vec3_t vOrigin) +{ + for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (face_t* f=b->brush_faces ; f ; f=f->next) + { + if (g_qeglobals.m_bBrushPrimitMode) + RotateFaceTexture_BrushPrimit( f, nAxis, fDeg, vOrigin ); + else + RotateFaceTexture(f, nAxis, fDeg); + //++timo removed that call .. works fine .. ??????? +// Brush_Build(b, false); + } + Brush_Build(b, false); + } +} + + +void Select_FlipAxis (int axis) +{ + int i; + + Select_GetMid (select_origin); + for (i=0 ; i<3 ; i++) + { + VectorCopy (vec3_origin, select_matrix[i]); + select_matrix[i][i] = 1; + } + select_matrix[axis][axis] = -1; + + select_fliporder = true; + Select_ApplyMatrix (true, false, 0, 0); + Sys_UpdateWindows (W_ALL); +} + + +void Select_Scale(float x, float y, float z) +{ + Select_GetMid (select_origin); + for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (face_t* f=b->brush_faces ; f ; f=f->next) + { + for (int i=0 ; i<3 ; i++) + { + f->planepts[i][0] -= select_origin[0]; + f->planepts[i][1] -= select_origin[1]; + f->planepts[i][2] -= select_origin[2]; + f->planepts[i][0] *= x; + //f->planepts[i][0] = floor(f->planepts[i][0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; + + f->planepts[i][1] *= y; + //f->planepts[i][1] = floor(f->planepts[i][1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; + + f->planepts[i][2] *= z; + //f->planepts[i][2] = floor(f->planepts[i][2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize; + + f->planepts[i][0] += select_origin[0]; + f->planepts[i][1] += select_origin[1]; + f->planepts[i][2] += select_origin[2]; + } + } + Brush_Build(b, false); + if (b->patchBrush) + { + vec3_t v; + v[0] = x; + v[1] = y; + v[2] = z; + //Patch_Scale(b->nPatchID, select_origin, v); + Patch_Scale(b->pPatch, select_origin, v); + } + if (b->terrainBrush) + { + vec3_t v; + v[0] = x; + v[1] = y; + v[2] = z; + Terrain_Scale(b->pTerrain, select_origin, v); + } + } +} + +void Select_RotateAxis (int axis, float deg, bool bPaint, bool bMouse) +{ + vec3_t temp; + int i, j; + vec_t c, s; + + if (deg == 0) + { + //Sys_Printf("0 deg\n"); + return; + } + + if (bMouse) + { + VectorCopy(g_pParentWnd->ActiveXY()->RotateOrigin(), select_origin); + } + else + { + Select_GetMid (select_origin); + } + + select_fliporder = false; + + if (deg == 90) + { + for (i=0 ; i<3 ; i++) + { + VectorCopy (vec3_origin, select_matrix[i]); + select_matrix[i][i] = 1; + } + i = (axis+1)%3; + j = (axis+2)%3; + VectorCopy (select_matrix[i], temp); + VectorCopy (select_matrix[j], select_matrix[i]); + VectorSubtract (vec3_origin, temp, select_matrix[j]); + } + else + { + deg = -deg; + if (deg == -180.0) + { + c = -1; + s = 0; + } + else if (deg == -270.0) + { + c = 0; + s = -1; + } + else + { + c = cos(deg * Q_PI / 180.0); + s = sin(deg * Q_PI / 180.0); + } + + for (i=0 ; i<3 ; i++) + { + VectorCopy (vec3_origin, select_matrix[i]); + select_matrix[i][i] = 1; + } + + switch (axis) + { + case 0: + select_matrix[1][1] = c; + select_matrix[1][2] = -s; + select_matrix[2][1] = s; + select_matrix[2][2] = c; + break; + case 1: + select_matrix[0][0] = c; + select_matrix[0][2] = s; + select_matrix[2][0] = -s; + select_matrix[2][2] = c; + break; + case 2: + select_matrix[0][0] = c; + select_matrix[0][1] = -s; + select_matrix[1][0] = s; + select_matrix[1][1] = c; + break; + } + } + + if (g_PrefsDlg.m_bRotateLock) + RotateTextures(axis, deg, select_origin); + Select_ApplyMatrix(!bMouse, true, axis, deg); + + if (bPaint) + Sys_UpdateWindows (W_ALL); +} + +/* +================================================================ + +GROUP SELECTIONS + +================================================================ +*/ + +void Select_CompleteTall (void) +{ + brush_t *b, *next; + //int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + clearSelection(); + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + Select_Delete (); + + int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0; + int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2; + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + + if ( (b->maxs[nDim1] > maxs[nDim1] || b->mins[nDim1] < mins[nDim1]) + || (b->maxs[nDim2] > maxs[nDim2] || b->mins[nDim2] < mins[nDim2]) ) + continue; + + if (FilterBrush (b)) + continue; + + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); +#if 0 + // old stuff + for (i=0 ; i<2 ; i++) + if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) + break; + if (i == 2) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } +#endif + } + Sys_UpdateWindows (W_ALL); +} + +void Select_PartialTall (void) +{ + brush_t *b, *next; + //int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + clearSelection(); + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + Select_Delete (); + + int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0; + int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2; + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + + if ( (b->mins[nDim1] > maxs[nDim1] || b->maxs[nDim1] < mins[nDim1]) + || (b->mins[nDim2] > maxs[nDim2] || b->maxs[nDim2] < mins[nDim2]) ) + continue; + + if (FilterBrush (b)) + continue; + + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + + +#if 0 +// old stuff + for (i=0 ; i<2 ; i++) + if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i]) + break; + if (i == 2) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } +#endif + } + Sys_UpdateWindows (W_ALL); +} + +void Select_Touching (void) +{ + brush_t *b, *next; + int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + clearSelection(); + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + + if (FilterBrush (b)) + continue; + + for (i=0 ; i<3 ; i++) + if (b->mins[i] > maxs[i]+1 || b->maxs[i] < mins[i]-1) + break; + + if (i == 3) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + Sys_UpdateWindows (W_ALL); +} + +void Select_Inside (void) +{ + brush_t *b, *next; + int i; + vec3_t mins, maxs; + + if (!QE_SingleBrush ()) + return; + + clearSelection(); + + VectorCopy (selected_brushes.next->mins, mins); + VectorCopy (selected_brushes.next->maxs, maxs); + Select_Delete (); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + + if (FilterBrush (b)) + continue; + + for (i=0 ; i<3 ; i++) + if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i]) + break; + if (i == 3) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + Sys_UpdateWindows (W_ALL); +} + +/* +============= +Select_Ungroup + +Turn the currently selected entity back into normal brushes +============= +*/ +void Select_Ungroup(void) +{ + int numselectedgroups; + entity_t *e; + brush_t *b, *sb; + + numselectedgroups = 0; + for (sb = selected_brushes.next; sb != &selected_brushes; sb = sb->next) + { + e = sb->owner; + + if (!e || e == world_entity || e->eclass->fixedsize) + { + continue; + } + + for (b = e->brushes.onext; b != &e->brushes; b = e->brushes.onext) + { + //Brush_RemoveFromList (b); + //Brush_AddToList (b, &active_brushes); + Entity_UnlinkBrush (b); + Entity_LinkBrush (world_entity, b); + Brush_Build( b ); + b->owner = world_entity; + } + Entity_Free (e); + numselectedgroups++; + } + + if (numselectedgroups <= 0) + { + Sys_Printf("No grouped entities selected.\n"); + return; + } + Sys_Printf("Ungrouped %d entit%s.\n", numselectedgroups, (numselectedgroups == 1)?"y":"ies"); + Sys_UpdateWindows (W_ALL); +} + + +/* +==================== +Select_MakeStructural +==================== +*/ +void Select_MakeStructural (void) +{ + brush_t *b; + face_t *f; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + for (f=b->brush_faces ; f ; f=f->next) + f->texdef.contents &= ~CONTENTS_DETAIL; + Select_Deselect (); + Sys_UpdateWindows (W_ALL); +} + +void Select_MakeDetail (void) +{ + brush_t *b; + face_t *f; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + for (f=b->brush_faces ; f ; f=f->next) + f->texdef.contents |= CONTENTS_DETAIL; + Select_Deselect (); + Sys_UpdateWindows (W_ALL); +} + +void Select_ShiftTexture(int x, int y) +{ + brush_t *b; + face_t *f; + + int nFaceCount = g_ptrSelectedFaces.GetSize(); + + if(selected_brushes.next == &selected_brushes && nFaceCount == 0) + return; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (f=b->brush_faces ; f ; f=f->next) + { + if (g_qeglobals.m_bBrushPrimitMode) + { + // use face normal to compute a true translation + Select_ShiftTexture_BrushPrimit( f, x, y ); + } + else + { + f->texdef.shift[0] += x; + f->texdef.shift[1] += y; + } + } + Brush_Build(b); + if (b->patchBrush) + { + //Patch_ShiftTexture(b->nPatchID, x, y); + Patch_ShiftTexture(b->pPatch, x, y); + } + } + + if (nFaceCount > 0) + { + for (int i = 0; i < nFaceCount; i++) + { + face_t *selFace = reinterpret_cast(g_ptrSelectedFaces.GetAt(i)); + brush_t *selBrush = reinterpret_cast(g_ptrSelectedFaceBrushes.GetAt(i)); + if (g_qeglobals.m_bBrushPrimitMode) + { + + // use face normal to compute a true translation + // Select_ShiftTexture_BrushPrimit( selected_face, x, y ); + // use camera view to compute texture shift + g_pParentWnd->GetCamera()->ShiftTexture_BrushPrimit( selFace, x, y ); + } + else + { + selFace->texdef.shift[0] += x; + selFace->texdef.shift[1] += y; + } + Brush_Build(selBrush); + } + } + + Sys_UpdateWindows (W_CAMERA); +} + +void Select_ScaleTexture(int x, int y) +{ + brush_t *b; + face_t *f; + + int nFaceCount = g_ptrSelectedFaces.GetSize(); + + if(selected_brushes.next == &selected_brushes && nFaceCount == 0) + { + return; + } + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (f=b->brush_faces ; f ; f=f->next) + { + if (g_qeglobals.m_bBrushPrimitMode) + { + // apply same scale as the spinner button of the surface inspector + float shift[2]; + float rotate; + float scale[2]; + brushprimit_texdef_t bp; + // compute normalized texture matrix + ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL ); + // compute fake shift scale rot + TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); + // update + scale[0]+=static_cast(x)*0.1; + scale[1]+=static_cast(y)*0.1; + // compute new normalized texture matrix + FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); + // apply to face texture matrix + ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture ); + } + else + { + f->texdef.scale[0] += x; + f->texdef.scale[1] += y; + } + } + Brush_Build(b); + if (b->patchBrush) + { + Patch_ScaleTexture(b->pPatch, x, y); + } + } + + if (nFaceCount > 0) + { + for (int i = 0; i < nFaceCount; i++) + { + face_t *selFace = reinterpret_cast(g_ptrSelectedFaces.GetAt(i)); + brush_t *selBrush = reinterpret_cast(g_ptrSelectedFaceBrushes.GetAt(i)); + if (g_qeglobals.m_bBrushPrimitMode) + { + float shift[2]; + float rotate; + float scale[2]; + brushprimit_texdef_t bp; + ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL ); + TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); + scale[0]+=static_cast(x)*0.1; + scale[1]+=static_cast(y)*0.1; + FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); + ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture ); + } + else + { + selFace->texdef.scale[0] += x; + selFace->texdef.scale[1] += y; + } + Brush_Build(selBrush); + } + } + + Sys_UpdateWindows (W_CAMERA); +} + +void Select_RotateTexture(int amt) +{ + brush_t *b; + face_t *f; + + int nFaceCount = g_ptrSelectedFaces.GetSize(); + + if(selected_brushes.next == &selected_brushes && nFaceCount == 0) + { + return; + } + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + for (f=b->brush_faces ; f ; f=f->next) + { + if (g_qeglobals.m_bBrushPrimitMode) + { + // apply same scale as the spinner button of the surface inspector + float shift[2]; + float rotate; + float scale[2]; + brushprimit_texdef_t bp; + // compute normalized texture matrix + ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL ); + // compute fake shift scale rot + TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); + // update + rotate += amt; + // compute new normalized texture matrix + FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); + // apply to face texture matrix + ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture ); + } + else + { + f->texdef.rotate += amt; + f->texdef.rotate = static_cast(f->texdef.rotate) % 360; + } + } + Brush_Build(b); + if (b->patchBrush) + { + //Patch_RotateTexture(b->nPatchID, amt); + Patch_RotateTexture(b->pPatch, amt); + } + } + + if (nFaceCount > 0) + { + for (int i = 0; i < nFaceCount; i++) + { + face_t *selFace = reinterpret_cast(g_ptrSelectedFaces.GetAt(i)); + brush_t *selBrush = reinterpret_cast(g_ptrSelectedFaceBrushes.GetAt(i)); + if (g_qeglobals.m_bBrushPrimitMode) + { + float shift[2]; + float rotate; + float scale[2]; + brushprimit_texdef_t bp; + ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL ); + TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale ); + rotate += amt; + FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords ); + ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture ); + } + else + { + selFace->texdef.rotate += amt; + selFace->texdef.rotate = static_cast(selFace->texdef.rotate) % 360; + } + Brush_Build(selBrush); + } + } + + Sys_UpdateWindows (W_CAMERA); +} + + +void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce) +{ + brush_t* pList = (bSelected) ? &selected_brushes : &active_brushes; + if (!bSelected) + { + Select_Deselect(); + } + + for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next) + { + if (pBrush->patchBrush) + { + Patch_FindReplaceTexture(pBrush, pFind, pReplace, bForce); + } + + if (pBrush->terrainBrush) + { + Terrain_FindReplaceTexture(pBrush->pTerrain, pFind, pReplace, bForce); + } + for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next) + { + if(bForce || strcmpi(pFace->texdef.name, pFind) == 0) + { + pFace->d_texture = Texture_ForName(pReplace); + //strcpy(pFace->texdef.name, pReplace); + pFace->texdef.SetName(pReplace); + } + } + Brush_Build(pBrush); + } + Sys_UpdateWindows (W_CAMERA); +} + + +void Select_AllOfType() +{ + brush_t *b, *next; + entity_t *e; + if ( (selected_brushes.next == &selected_brushes) + || (selected_brushes.next->next != &selected_brushes) ) + { + + CString strName; + if (g_ptrSelectedFaces.GetSize() == 0) + { + strName = g_qeglobals.d_texturewin.texdef.name; + } + else + { + face_t *selFace = reinterpret_cast(g_ptrSelectedFaces.GetAt(0)); + strName = selFace->texdef.name; + } + + Select_Deselect(); + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + + if (FilterBrush (b)) + continue; + + if (b->patchBrush) + { + if (strcmpi(strName, b->pPatch->d_texture->name) == 0) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + else + { + for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next) + { + if (strcmpi(strName, pFace->texdef.name) == 0) + { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + } + } + Sys_UpdateWindows(W_ALL); + return; + } + + + b = selected_brushes.next; + e = b->owner; + + if (e != NULL) + { + if (e != world_entity) + { + CString strName = e->eclass->name; + CString strKey, strVal; + bool bCriteria = GetSelectAllCriteria(strKey, strVal); + Sys_Printf("Selecting all %s(s)\n", strName); + Select_Deselect(); + + for (b=active_brushes.next ; b != &active_brushes ; b=next) + { + next = b->next; + + if (FilterBrush (b)) + continue; + + e = b->owner; + if (e != NULL) + { + if (strcmpi(e->eclass->name, strName) == 0) + { + bool doIt = true; + if (bCriteria) { + CString str = ValueForKey (e, strKey); + if (str.CompareNoCase(strVal) != 0) { + doIt = false; + } + } + if (doIt) { + Brush_RemoveFromList (b); + Brush_AddToList (b, &selected_brushes); + } + } + } + } + } + } + Sys_UpdateWindows (W_ALL); + +} + +void Select_Reselect() +{ + CPtrArray holdArray; + for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) + { + holdArray.Add(reinterpret_cast(b)); + } + + int n = holdArray.GetSize(); + while (n-- > 0) + { + b = reinterpret_cast(holdArray.GetAt(n)); + Select_Brush(b); + } + Sys_UpdateWindows (W_ALL); +} + + +void Select_FitTexture(int nHeight, int nWidth) +{ + brush_t *b; + + int nFaceCount = g_ptrSelectedFaces.GetSize(); + + if(selected_brushes.next == &selected_brushes && nFaceCount == 0) + return; + + for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) + { + Brush_FitTexture(b, nHeight, nWidth); + Brush_Build(b); + } + + if (nFaceCount > 0) + { + for (int i = 0; i < nFaceCount; i++) + { + face_t *selFace = reinterpret_cast(g_ptrSelectedFaces.GetAt(i)); + brush_t *selBrush = reinterpret_cast(g_ptrSelectedFaceBrushes.GetAt(i)); + Face_FitTexture(selFace, nHeight, nWidth); + Brush_Build(selBrush); + } + } + + Sys_UpdateWindows (W_CAMERA); +} + +void Select_AxialTexture() +{ + +} + +void Select_Hide() +{ + for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) + { + b->hiddenBrush = true; + } + Sys_UpdateWindows (W_ALL); +} + +void Select_ShowAllHidden() +{ + brush_t* b; + for (b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) + { + b->hiddenBrush = false; + } + for (b=active_brushes.next ; b && b != &active_brushes ; b=b->next) + { + b->hiddenBrush = false; + } + Sys_UpdateWindows (W_ALL); +} + + +/* +============ +Select_Invert +============ +*/ +void Select_Invert(void) +{ + brush_t *next, *prev; + + Sys_Printf("inverting selection...\n"); + + next = active_brushes.next; + prev = active_brushes.prev; + if (selected_brushes.next != &selected_brushes) + { + active_brushes.next = selected_brushes.next; + active_brushes.prev = selected_brushes.prev; + active_brushes.next->prev = &active_brushes; + active_brushes.prev->next = &active_brushes; + } + else + { + active_brushes.next = &active_brushes; + active_brushes.prev = &active_brushes; + } + if (next != &active_brushes) + { + selected_brushes.next = next; + selected_brushes.prev = prev; + selected_brushes.next->prev = &selected_brushes; + selected_brushes.prev->next = &selected_brushes; + } + else + { + selected_brushes.next = &selected_brushes; + selected_brushes.prev = &selected_brushes; + } + + Sys_UpdateWindows(W_ALL); + + Sys_Printf("done.\n"); +} + + +/* +=========== +Select_Name +=========== +*/ +void Select_Name(const char *pName) +{ + if (g_qeglobals.m_bBrushPrimitMode) + { + for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) + { + Brush_SetEpair(b, "Name", pName); + } + } +} + +/* +================= +Select_AddToGroup +add selected brushes to a group, update the tree +================= +*/ +void Select_AddToGroup(const char *pName) +{ + if (g_qeglobals.m_bBrushPrimitMode) + { + for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next) + { + Brush_SetEpair(b, "group", pName); + Group_AddToProperGroup(b); + } + } +} -- cgit v1.2.3