home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / SELECT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  39.6 KB  |  1,712 lines

  1. // select.c
  2. #include "stdafx.h"
  3. #include "qe3.h"
  4.  
  5.  
  6. // externs
  7. CPtrArray g_SelectedFaces;
  8. CPtrArray g_SelectedFaceBrushes;
  9. CPtrArray& g_ptrSelectedFaces = g_SelectedFaces;
  10. CPtrArray& g_ptrSelectedFaceBrushes = g_SelectedFaceBrushes;
  11.  
  12. /*
  13. ===========
  14. Test_Ray
  15. ===========
  16. */
  17. #define    DIST_START    999999
  18. trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags)
  19. {
  20.     brush_t    *brush;
  21.     face_t    *face;
  22.     float    dist;
  23.     trace_t    t;
  24.  
  25.     memset (&t, 0, sizeof(t));
  26.     t.dist = DIST_START;
  27.  
  28.     if (flags & SF_CYCLE)
  29.     {
  30.         CPtrArray array;
  31.         brush_t *pToSelect = (selected_brushes.next != &selected_brushes) ? selected_brushes.next : NULL;
  32.         Select_Deselect();
  33.  
  34.         // go through active brushes and accumulate all "hit" brushes
  35.         for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
  36.         {
  37.             //if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity)
  38.             //  continue;
  39.          
  40.             if (FilterBrush (brush))
  41.                 continue;
  42.  
  43.             if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush)
  44.                 continue;
  45.  
  46.             //if (!g_bShowPatchBounds && brush->patchBrush)
  47.             //  continue;
  48.  
  49.             face = Brush_Ray (origin, dir, brush, &dist);
  50.  
  51.             if (face)
  52.                 array.Add(brush);
  53.         }
  54.  
  55.         int nSize = array.GetSize();
  56.         if (nSize > 0)
  57.         {
  58.             bool bFound = false;
  59.             for (int i = 0; i < nSize; i++)
  60.             {
  61.                 brush_t *b = reinterpret_cast<brush_t*>(array.GetAt(i));
  62.                 // did we hit the last one selected yet ?
  63.                 if (b == pToSelect)
  64.                 {
  65.                     // yes we want to select the next one in the list 
  66.                     int n = (i > 0) ? i-1 : nSize-1;
  67.                     pToSelect = reinterpret_cast<brush_t*>(array.GetAt(n));
  68.                     bFound = true;
  69.                     break;
  70.                 }
  71.             }
  72.             if (!bFound)
  73.                 pToSelect = reinterpret_cast<brush_t*>(array.GetAt(0));
  74.         }
  75.         if (pToSelect)
  76.         {
  77.             face = Brush_Ray (origin, dir, pToSelect, &dist);
  78.             t.dist = dist;
  79.             t.brush = pToSelect;
  80.             t.face = face;
  81.             t.selected = false;
  82.             return t;
  83.         }
  84.     }
  85.  
  86.     if (! (flags & SF_SELECTED_ONLY) )
  87.     {
  88.         for (brush = active_brushes.next ; brush != &active_brushes ; brush=brush->next)
  89.         {
  90.             if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity)
  91.                 continue;
  92.             
  93.             if (FilterBrush (brush))
  94.                 continue;
  95.  
  96.             if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush)
  97.                 continue;
  98.  
  99.             //if (!g_bShowPatchBounds && brush->patchBrush)
  100.             //  continue;
  101.  
  102.             face = Brush_Ray (origin, dir, brush, &dist);
  103.             if (dist > 0 && dist < t.dist)
  104.             {
  105.                 t.dist = dist;
  106.                 t.brush = brush;
  107.                 t.face = face;
  108.                 t.selected = false;
  109.             }
  110.         }
  111.     }
  112.  
  113.  
  114.     for (brush = selected_brushes.next ; brush != &selected_brushes ; brush=brush->next)
  115.     {
  116.         if ( (flags & SF_ENTITIES_FIRST) && brush->owner == world_entity)
  117.             continue;
  118.  
  119.         if (FilterBrush (brush))
  120.             continue;
  121.  
  122.         if (!g_PrefsDlg.m_bSelectCurves && brush->patchBrush)
  123.             continue;
  124.  
  125.         face = Brush_Ray (origin, dir, brush, &dist);
  126.         if (dist > 0 && dist < t.dist)
  127.         {
  128.             t.dist = dist;
  129.             t.brush = brush;
  130.             t.face = face;
  131.             t.selected = true;
  132.         }
  133.     }
  134.  
  135.     // if entites first, but didn't find any, check regular
  136.  
  137.     if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL)
  138.         return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST);
  139.  
  140.     return t;
  141.  
  142. }
  143.  
  144.  
  145. /*
  146. ============
  147. Select_Brush
  148.  
  149. ============
  150. */
  151. void Select_Brush (brush_t *brush, bool bComplete, bool bStatus)
  152. {
  153.     brush_t    *b;
  154.     entity_t    *e;
  155.  
  156.   g_ptrSelectedFaces.RemoveAll();
  157.   g_ptrSelectedFaceBrushes.RemoveAll();
  158.     //selected_face = NULL;
  159.     if (g_qeglobals.d_select_count < 2)
  160.         g_qeglobals.d_select_order[g_qeglobals.d_select_count] = brush;
  161.     g_qeglobals.d_select_count++;
  162.  
  163.   //if (brush->patchBrush)
  164.   //  Patch_Select(brush->nPatchID);
  165.  
  166.     e = brush->owner;
  167.     if (e)
  168.     {
  169.         // select complete entity on first click
  170.         if (e != world_entity && bComplete == true)
  171.         {
  172.             for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  173.                 if (b->owner == e)
  174.                     goto singleselect;
  175.             for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
  176.             {
  177.         Brush_RemoveFromList (b);
  178.                 Brush_AddToList (b, &selected_brushes);
  179.             }
  180.         }
  181.         else
  182.         {
  183. singleselect:
  184.             Brush_RemoveFromList (brush);
  185.             Brush_AddToList (brush, &selected_brushes);
  186.       UpdateSurfaceDialog();
  187.       UpdatePatchInspector();
  188.         }
  189.  
  190.         if (e->eclass)
  191.         {
  192.             UpdateEntitySel(brush->owner->eclass);
  193.         }
  194.     }
  195.   if (bStatus)
  196.   {
  197.     vec3_t vMin, vMax, vSize;
  198.       Select_GetBounds (vMin, vMax);
  199.     VectorSubtract(vMax, vMin, vSize);
  200.     CString strStatus;
  201.     strStatus.Format("Selection X:: %.1f  Y:: %.1f  Z:: %.1f", vSize[0], vSize[1], vSize[2]);
  202.     g_pParentWnd->SetStatusText(2, strStatus);
  203.   }
  204. }
  205.  
  206.  
  207. /*
  208. ============
  209. Select_Ray
  210.  
  211. If the origin is inside a brush, that brush will be ignored.
  212. ============
  213. */
  214. void Select_Ray (vec3_t origin, vec3_t dir, int flags)
  215. {
  216.     trace_t    t;
  217.  
  218.     t = Test_Ray (origin, dir, flags);
  219.     if (!t.brush)
  220.         return;
  221.  
  222.     if (flags == SF_SINGLEFACE)
  223.     {
  224.         int nCount = g_SelectedFaces.GetSize();
  225.         bool bOk = true;
  226.         for (int i = 0; i < nCount; i++)
  227.         {
  228.             if (t.face == reinterpret_cast<face_t*>(g_SelectedFaces.GetAt(i)))
  229.             {
  230.                 bOk = false;
  231.                 // need to move remove i'th entry
  232.                 g_SelectedFaces.RemoveAt(i, 1);
  233.                 g_SelectedFaceBrushes.RemoveAt(i, 1);
  234.             }
  235.         }
  236.         if (bOk)
  237.         {
  238.             g_SelectedFaces.Add(t.face);
  239.             g_SelectedFaceBrushes.Add(t.brush);
  240.         }
  241.         //selected_face = t.face;
  242.         //selected_face_brush = t.brush;
  243.         Sys_UpdateWindows (W_ALL);
  244.         g_qeglobals.d_select_mode = sel_brush;
  245.         // Texture_SetTexture requires a brushprimit_texdef fitted to the default width=2 height=2 texture
  246.         brushprimit_texdef_t brushprimit_texdef;
  247.         ConvertTexMatWithQTexture ( &t.face->brushprimit_texdef, t.face->d_texture, &brushprimit_texdef, NULL );
  248.         Texture_SetTexture ( &t.face->texdef, &brushprimit_texdef, false, GETPLUGINTEXDEF(t.face), false );
  249.         UpdateSurfaceDialog();
  250.         return;
  251.     }
  252.  
  253.     // move the brush to the other list
  254.  
  255.      g_qeglobals.d_select_mode = sel_brush;
  256.  
  257.     if (t.selected)
  258.     {        
  259.         Brush_RemoveFromList (t.brush);
  260.         Brush_AddToList (t.brush, &active_brushes);
  261.         UpdatePatchInspector();
  262.     } 
  263.     else
  264.     {
  265.         Select_Brush (t.brush, !(GetKeyState(VK_MENU) & 0x8000));
  266.     }
  267.  
  268.     Sys_UpdateWindows (W_ALL);
  269. }
  270.  
  271.  
  272. void Select_Delete (void)
  273. {
  274.     brush_t    *brush;
  275.  
  276.   g_ptrSelectedFaces.RemoveAll();
  277.   g_ptrSelectedFaceBrushes.RemoveAll();
  278.     //selected_face = NULL;
  279.     
  280.   g_qeglobals.d_select_mode = sel_brush;
  281.  
  282.     g_qeglobals.d_select_count = 0;
  283.     g_qeglobals.d_num_move_points = 0;
  284.     while (selected_brushes.next != &selected_brushes)
  285.     {
  286.         brush = selected_brushes.next;
  287.     if (brush->patchBrush)
  288.     {
  289.       //Patch_Delete(brush->nPatchID);
  290.       Patch_Delete(brush->pPatch);
  291.     }
  292.         Brush_Free (brush);
  293.     }
  294.  
  295.     // FIXME: remove any entities with no brushes
  296.  
  297.     Sys_UpdateWindows (W_ALL);
  298. }
  299.  
  300. void Select_Deselect (bool bDeselectFaces)
  301. {
  302.     brush_t    *b;
  303.  
  304.   Patch_Deselect();
  305.  
  306.   g_pParentWnd->ActiveXY()->UndoClear();
  307.  
  308.   g_qeglobals.d_workcount++;
  309.     g_qeglobals.d_select_count = 0;
  310.     g_qeglobals.d_num_move_points = 0;
  311.     b = selected_brushes.next;
  312.  
  313.     if (b == &selected_brushes)
  314.     {
  315.         if (bDeselectFaces)
  316.         {
  317.             g_ptrSelectedFaces.RemoveAll();
  318.       g_ptrSelectedFaceBrushes.RemoveAll();
  319.       //selected_face = NULL;
  320.         }
  321.          Sys_UpdateWindows (W_ALL);
  322.         return;
  323.     }
  324.  
  325.   if (bDeselectFaces)
  326.   {
  327.       g_ptrSelectedFaces.RemoveAll();
  328.     g_ptrSelectedFaceBrushes.RemoveAll();
  329.       //selected_face = NULL;
  330.   }
  331.  
  332.     g_qeglobals.d_select_mode = sel_brush;
  333.  
  334.     // grab top / bottom height for new brushes
  335.     if (b->mins[2] < b->maxs[2])
  336.     {
  337.         g_qeglobals.d_new_brush_bottom_z = b->mins[2];
  338.         g_qeglobals.d_new_brush_top_z = b->maxs[2];
  339.     }
  340.  
  341.     selected_brushes.next->prev = &active_brushes;
  342.     selected_brushes.prev->next = active_brushes.next;
  343.     active_brushes.next->prev = selected_brushes.prev;
  344.     active_brushes.next = selected_brushes.next;
  345.     selected_brushes.prev = selected_brushes.next = &selected_brushes;    
  346.  
  347.     Sys_UpdateWindows (W_ALL);
  348. }
  349.  
  350. /*
  351. ============
  352. Select_Move
  353. ============
  354. */
  355. void Select_Move (vec3_t delta, bool bSnap)
  356. {
  357.     brush_t    *b;
  358.   
  359.  
  360. // actually move the selected brushes
  361.     for (b = selected_brushes.next ; b != &selected_brushes ; b=b->next)
  362.         Brush_Move (b, delta, bSnap);
  363.  
  364.   vec3_t vMin, vMax;
  365.     Select_GetBounds (vMin, vMax);
  366.   CString strStatus;
  367.   strStatus.Format("Origin X:: %.1f  Y:: %.1f  Z:: %.1f", vMin[0], vMax[1], vMax[2]);
  368.   g_pParentWnd->SetStatusText(2, strStatus);
  369.  
  370. //    Sys_UpdateWindows (W_ALL);
  371. }
  372.  
  373. /*
  374. ============
  375. Select_Clone
  376.  
  377. Creates an exact duplicate of the selection in place, then moves
  378. the selected brushes off of their old positions
  379. ============
  380. */
  381. void Select_Clone (void)
  382. {
  383. #if 1
  384.   ASSERT(g_pParentWnd->ActiveXY());
  385.   g_bScreenUpdates = false;  
  386.   g_pParentWnd->ActiveXY()->Copy();
  387.   g_pParentWnd->ActiveXY()->Paste();
  388.   g_pParentWnd->NudgeSelection(2, g_qeglobals.d_gridsize);
  389.   g_pParentWnd->NudgeSelection(3, g_qeglobals.d_gridsize);
  390.   g_bScreenUpdates = true;  
  391.   Sys_UpdateWindows(W_ALL);
  392. #else
  393.  
  394.     brush_t        *b, *b2, *n, *next, *next2;
  395.     vec3_t        delta;
  396.     entity_t    *e;
  397.  
  398.     g_qeglobals.d_workcount++;
  399.     g_qeglobals.d_select_mode = sel_brush;
  400.  
  401.     delta[0] = g_qeglobals.d_gridsize;
  402.     delta[1] = g_qeglobals.d_gridsize;
  403.     delta[2] = 0;
  404.  
  405.     for (b=selected_brushes.next ; b != &selected_brushes ; b=next)
  406.     {
  407.         next = b->next;
  408.         // if the brush is a world brush, handle simply
  409.         if (b->owner == world_entity)
  410.         {
  411.             n = Brush_Clone (b);
  412.             Brush_AddToList (n, &active_brushes);
  413.             Entity_LinkBrush (world_entity, n);
  414.             Brush_Build( n );
  415.             Brush_Move (b, delta);
  416.             continue;
  417.         }
  418.  
  419.         e = Entity_Clone (b->owner);
  420.         // clear the target / targetname
  421.         DeleteKey (e, "target");
  422.         DeleteKey (e, "targetname");
  423.  
  424.         // if the brush is a fixed size entity, create a new entity
  425.         if (b->owner->eclass->fixedsize)
  426.         {
  427.             n = Brush_Clone (b);
  428.             Brush_AddToList (n, &active_brushes);
  429.             Entity_LinkBrush (e, n);
  430.             Brush_Build( n );
  431.             Brush_Move (b, delta);
  432.             continue;
  433.         }
  434.         
  435.         // brush is a complex entity, grab all the other ones now
  436.  
  437.         next = &selected_brushes;
  438.  
  439.         for ( b2 = b ; b2 != &selected_brushes ; b2=next2)
  440.         {
  441.             next2 = b2->next;
  442.             if (b2->owner != b->owner)
  443.             {
  444.                 if (next == &selected_brushes)
  445.                     next = b2;
  446.                 continue;
  447.             }
  448.  
  449.             // move b2 to the start of selected_brushes,
  450.             // so it won't be hit again
  451.             Brush_RemoveFromList (b2);
  452.             Brush_AddToList (b2, &selected_brushes);
  453.             
  454.             n = Brush_Clone (b2);
  455.             Brush_AddToList (n, &active_brushes);
  456.             Entity_LinkBrush (e, n);
  457.             Brush_Build( n );
  458.             Brush_Move (b2, delta, true);
  459.         }
  460.  
  461.     }
  462.     Sys_UpdateWindows (W_ALL);
  463. #endif
  464. }
  465.  
  466.  
  467.  
  468. /*
  469. ============
  470. Select_SetTexture
  471. Timo : bFitScale to compute scale on the plane and counteract plane / axial plane snapping
  472. Timo :    brush primitive texturing
  473.         the brushprimit_texdef given must be understood as a qtexture_t width=2 height=2 ( HiRes )
  474. Timo :  texture plugin, added an IPluginTexdef* parameter
  475.         must be casted to an IPluginTexdef!
  476.         if not NULL, get ->Copy() of it into each face or brush ( and remember to hook )
  477.         if NULL, means we have no information, ask for a default
  478. ============
  479. */
  480. void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef )
  481. {
  482.     brush_t    *b;
  483.     int nCount = g_ptrSelectedFaces.GetSize();
  484.     if (nCount > 0)
  485.     {
  486.         Undo_Start("set face textures");
  487.         ASSERT(g_ptrSelectedFaces.GetSize() == g_ptrSelectedFaceBrushes.GetSize());
  488.         for (int i = 0; i < nCount; i++)
  489.         {
  490.             face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
  491.             brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
  492.             Undo_AddBrush(selBrush);
  493.             SetFaceTexdef (selBrush, selFace, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef *>(pPlugTexdef) );
  494.             Brush_Build(selBrush, bFitScale);
  495.             Undo_EndBrush(selBrush);
  496.         }
  497.         Undo_End();
  498.     }
  499.     else if (selected_brushes.next != &selected_brushes)
  500.     {
  501.         Undo_Start("set brush textures");
  502.         for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  503.             if (!b->owner->eclass->fixedsize)
  504.             {
  505.                 Undo_AddBrush(b);
  506.                 Brush_SetTexture (b, texdef, brushprimit_texdef, bFitScale, static_cast<IPluginTexdef *>(pPlugTexdef) );
  507.                 Undo_EndBrush(b);
  508.             }
  509.         Undo_End();
  510.     }
  511.     Sys_UpdateWindows (W_ALL);
  512. }
  513.  
  514.  
  515. /*
  516. ================================================================
  517.  
  518.   TRANSFORMATIONS
  519.  
  520. ================================================================
  521. */
  522.  
  523. void Select_GetBounds (vec3_t mins, vec3_t maxs)
  524. {
  525.     brush_t    *b;
  526.     int        i;
  527.  
  528.     for (i=0 ; i<3 ; i++)
  529.     {
  530.         mins[i] = 99999;
  531.         maxs[i] = -99999;
  532.     }
  533.  
  534.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  535.         for (i=0 ; i<3 ; i++)
  536.         {
  537.             if (b->mins[i] < mins[i])
  538.                 mins[i] = b->mins[i];
  539.             if (b->maxs[i] > maxs[i])
  540.                 maxs[i] = b->maxs[i];
  541.         }
  542. }
  543.  
  544.  
  545. void Select_GetTrueMid (vec3_t mid)
  546. {
  547.     vec3_t    mins, maxs;
  548.     Select_GetBounds (mins, maxs);
  549.  
  550.   for (int i=0 ; i<3 ; i++)
  551.     mid[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
  552. }
  553.  
  554.  
  555. void Select_GetMid (vec3_t mid)
  556. {
  557.     vec3_t    mins, maxs;
  558.     int        i;
  559.  
  560.   if (g_PrefsDlg.m_bNoClamp)
  561.   {
  562.     Select_GetTrueMid(mid);
  563.     return;
  564.   }
  565.  
  566.   Select_GetBounds (mins, maxs);
  567.  
  568.   for (i=0 ; i<3 ; i++)
  569.         mid[i] = g_qeglobals.d_gridsize*floor ( ( (mins[i] + maxs[i])*0.5 )/g_qeglobals.d_gridsize );
  570.  
  571. }
  572.  
  573. vec3_t    select_origin;
  574. vec3_t    select_matrix[3];
  575. qboolean    select_fliporder;
  576.  
  577. void Select_ApplyMatrix (bool bSnap, bool bRotation, int nAxis, float fDeg)
  578. {
  579.     brush_t    *b;
  580.     face_t    *f;
  581.     int        i, j;
  582.     vec3_t    temp;
  583.  
  584.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  585.     {
  586.         for (f=b->brush_faces ; f ; f=f->next)
  587.         {
  588.             for (i=0 ; i<3 ; i++)
  589.             {
  590.                 VectorSubtract (f->planepts[i], select_origin, temp);
  591.                 for (j=0 ; j<3 ; j++)
  592.                     f->planepts[i][j] = DotProduct(temp, select_matrix[j]) + select_origin[j];
  593.             }
  594.             if (select_fliporder)
  595.             {
  596.                 VectorCopy (f->planepts[0], temp);
  597.                 VectorCopy (f->planepts[2], f->planepts[0]);
  598.                 VectorCopy (temp, f->planepts[2]);
  599.             }
  600.         }
  601.  
  602.     if(b->owner->eclass->fixedsize)
  603.     {
  604.       if (bRotation && b->owner->md3Class)
  605.       {
  606.         b->owner->vRotation[nAxis] += fDeg;
  607.       }
  608.     }
  609.  
  610.     Brush_Build(b, bSnap);
  611.     
  612.         if (b->patchBrush)
  613.         {
  614.             //Patch_ApplyMatrix(b->nPatchID, select_origin, select_matrix);
  615.             Patch_ApplyMatrix(b->pPatch, select_origin, select_matrix, bSnap);
  616.         }
  617.     }
  618. }
  619.  
  620. void ProjectOnPlane(vec3_t& normal,float dist,vec3_t& ez, vec3_t& p)
  621. {
  622.     if (fabs(ez[0]) == 1)
  623.         p[0] = (dist - normal[1] * p[1] - normal[2] * p[2]) / normal[0];
  624.     else if (fabs(ez[1]) == 1)
  625.         p[1] = (dist - normal[0] * p[0] - normal[2] * p[2]) / normal[1];
  626.     else
  627.         p[2] = (dist - normal[0] * p[0] - normal[1] * p[1]) / normal[2];
  628. }
  629.  
  630. void Back(vec3_t& dir, vec3_t& p)
  631. {
  632.     if (fabs(dir[0]) == 1)
  633.         p[0] = 0;
  634.     else if (fabs(dir[1]) == 1)
  635.         p[1] = 0;
  636.     else p[2] = 0;
  637. }
  638.  
  639.  
  640.  
  641. // using scale[0] and scale[1]
  642. void ComputeScale(vec3_t& rex, vec3_t& rey, vec3_t& p, face_t* f)
  643. {
  644.     float px = DotProduct(rex, p);
  645.     float py = DotProduct(rey, p);
  646.     px *= f->texdef.scale[0];
  647.     py *= f->texdef.scale[1];
  648.   vec3_t aux;
  649.   VectorCopy(rex, aux);
  650.   VectorScale(aux, px, aux);
  651.   VectorCopy(aux, p);
  652.   VectorCopy(rey, aux);
  653.   VectorScale(aux, py, aux);
  654.   VectorAdd(p, aux, p);
  655. }
  656.  
  657. void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3)
  658. {
  659.     vec3_t ex,ey,ez;            // local axis base
  660.  
  661. #ifdef _DEBUG
  662.     if (g_qeglobals.m_bBrushPrimitMode)
  663.         Sys_Printf("Warning : illegal call of ComputeAbsolute in brush primitive mode\n");
  664. #endif
  665.  
  666.   // compute first local axis base
  667.   TextureAxisFromPlane(&f->plane, ex, ey);
  668.   CrossProduct(ex, ey, ez);
  669.         
  670.     vec3_t aux;
  671.   VectorCopy(ex, aux);
  672.   VectorScale(aux, -f->texdef.shift[0], aux);
  673.   VectorCopy(aux, p1);
  674.   VectorCopy(ey, aux);
  675.   VectorScale(aux, -f->texdef.shift[1], aux);
  676.   VectorAdd(p1, aux, p1);
  677.   VectorCopy(p1, p2);
  678.   VectorAdd(p2, ex, p2);
  679.   VectorCopy(p1, p3);
  680.   VectorAdd(p3, ey, p3);
  681.   VectorCopy(ez, aux);
  682.   VectorScale(aux, -f->texdef.rotate, aux);
  683.   VectorRotate(p1, aux, p1);
  684.   VectorRotate(p2, aux, p2);
  685.   VectorRotate(p3, aux, p3);
  686.     // computing rotated local axis base
  687.     vec3_t rex,rey;
  688.   VectorCopy(ex, rex);
  689.   VectorRotate(rex, aux, rex);
  690.   VectorCopy(ey, rey);
  691.   VectorRotate(rey, aux, rey);
  692.  
  693.   ComputeScale(rex,rey,p1,f);
  694.     ComputeScale(rex,rey,p2,f);
  695.     ComputeScale(rex,rey,p3,f);
  696.  
  697.     // project on normal plane
  698.     // along ez 
  699.     // assumes plane normal is normalized
  700.     ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p1);
  701.     ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p2);
  702.     ProjectOnPlane(f->plane.normal,f->plane.dist,ez,p3);
  703. };
  704.  
  705.  
  706. void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3)
  707. {
  708.     vec3_t ex,ey,ez;
  709.  
  710. #ifdef _DEBUG
  711.     if (g_qeglobals.m_bBrushPrimitMode)
  712.         Sys_Printf("Warning : illegal call of AbsoluteToLocal in brush primitive mode\n");
  713. #endif
  714.  
  715.     // computing new local axis base
  716.   TextureAxisFromPlane(&normal2, ex, ey);
  717.   CrossProduct(ex, ey, ez);
  718.  
  719.   // projecting back on (ex,ey)
  720.     Back(ez,p1);
  721.     Back(ez,p2);
  722.     Back(ez,p3);
  723.  
  724.     vec3_t aux;
  725.     // rotation
  726.   VectorCopy(p2, aux);
  727.   VectorSubtract(aux, p1,aux);
  728.     
  729.     float x = DotProduct(aux,ex);
  730.     float y = DotProduct(aux,ey);
  731.   f->texdef.rotate = 180 * atan2(y,x) / Q_PI;
  732.  
  733.     vec3_t rex,rey;
  734.     // computing rotated local axis base
  735.   VectorCopy(ez, aux);
  736.   VectorScale(aux, f->texdef.rotate, aux);
  737.   VectorCopy(ex, rex);
  738.   VectorRotate(rex, aux, rex);
  739.   VectorCopy(ey, rey);
  740.   VectorRotate(rey, aux, rey);
  741.  
  742.     // scale
  743.   VectorCopy(p2, aux);
  744.   VectorSubtract(aux, p1, aux);
  745.   f->texdef.scale[0] = DotProduct(aux, rex);
  746.   VectorCopy(p3, aux);
  747.   VectorSubtract(aux, p1, aux);
  748.   f->texdef.scale[1] = DotProduct(aux, rey);
  749.  
  750.     // shift
  751.     // only using p1
  752.     x = DotProduct(rex,p1);
  753.     y = DotProduct(rey,p1);                 
  754.     x /= f->texdef.scale[0];
  755.     y /= f->texdef.scale[1];
  756.  
  757.   VectorCopy(rex, p1);
  758.   VectorScale(p1, x, p1);
  759.   VectorCopy(rey, aux);
  760.   VectorScale(aux, y, aux);
  761.   VectorAdd(p1, aux, p1);
  762.   VectorCopy(ez, aux);
  763.   VectorScale(aux, -f->texdef.rotate, aux);
  764.   VectorRotate(p1, aux, p1);
  765.     f->texdef.shift[0] = -DotProduct(p1, ex);
  766.     f->texdef.shift[1] = -DotProduct(p1, ey);
  767.  
  768.     // stored rot is good considering local axis base
  769.     // change it if necessary
  770.     f->texdef.rotate = -f->texdef.rotate;
  771.  
  772.   Clamp(f->texdef.shift[0], f->d_texture->width);
  773.   Clamp(f->texdef.shift[1], f->d_texture->height);
  774.   Clamp(f->texdef.rotate, 360);
  775.  
  776. }
  777.  
  778. void RotateFaceTexture(face_t* f, int nAxis, float fDeg)
  779. {
  780.     vec3_t p1,p2,p3, rota;   
  781.     p1[0] = p1[1] = p1[2] = 0;
  782.     VectorCopy(p1, p2);
  783.     VectorCopy(p1, p3);
  784.     VectorCopy(p1, rota);
  785.     ComputeAbsolute(f, p1, p2, p3);
  786.   
  787.     rota[nAxis] = fDeg;
  788.     VectorRotate(p1, rota, select_origin, p1);
  789.     VectorRotate(p2, rota, select_origin, p2);
  790.     VectorRotate(p3, rota, select_origin, p3);
  791.  
  792.     plane_t normal2;
  793.     vec3_t vNormal;
  794.     vNormal[0] = f->plane.normal[0];
  795.     vNormal[1] = f->plane.normal[1];
  796.     vNormal[2] = f->plane.normal[2];
  797.     VectorRotate(vNormal, rota, vNormal);
  798.     normal2.normal[0] = vNormal[0];
  799.     normal2.normal[1] = vNormal[1];
  800.     normal2.normal[2] = vNormal[2];
  801.     AbsoluteToLocal(normal2, f, p1, p2 ,p3);
  802.  
  803. }
  804.  
  805. void RotateTextures(int nAxis, float fDeg, vec3_t vOrigin)
  806. {
  807.     for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  808.     {
  809.         for (face_t* f=b->brush_faces ; f ; f=f->next)
  810.         {
  811.             if (g_qeglobals.m_bBrushPrimitMode)
  812.                 RotateFaceTexture_BrushPrimit( f, nAxis, fDeg, vOrigin );
  813.             else
  814.                 RotateFaceTexture(f, nAxis, fDeg);
  815.             //++timo removed that call .. works fine .. ???????
  816. //            Brush_Build(b, false);
  817.         }
  818.         Brush_Build(b, false);
  819.     }
  820. }
  821.  
  822.  
  823. void Select_FlipAxis (int axis)
  824. {
  825.     int        i;
  826.  
  827.     Select_GetMid (select_origin);
  828.     for (i=0 ; i<3 ; i++)
  829.     {
  830.         VectorCopy (vec3_origin, select_matrix[i]);
  831.         select_matrix[i][i] = 1;
  832.     }
  833.     select_matrix[axis][axis] = -1;
  834.  
  835.     select_fliporder = true;
  836.     Select_ApplyMatrix (true, false, 0, 0);
  837.     Sys_UpdateWindows (W_ALL);
  838. }
  839.  
  840.  
  841. void Select_Scale(float x, float y, float z)
  842. {
  843.   Select_GetMid (select_origin);
  844.     for (brush_t* b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  845.     {
  846.         for (face_t* f=b->brush_faces ; f ; f=f->next)
  847.         {
  848.             for (int i=0 ; i<3 ; i++)
  849.             {
  850.         f->planepts[i][0] -= select_origin[0];
  851.         f->planepts[i][1] -= select_origin[1];
  852.         f->planepts[i][2] -= select_origin[2];
  853.         f->planepts[i][0] *= x;
  854.         //f->planepts[i][0] = floor(f->planepts[i][0] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  855.  
  856.         f->planepts[i][1] *= y;
  857.         //f->planepts[i][1] = floor(f->planepts[i][1] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  858.  
  859.         f->planepts[i][2] *= z;
  860.         //f->planepts[i][2] = floor(f->planepts[i][2] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
  861.         
  862.         f->planepts[i][0] += select_origin[0];
  863.         f->planepts[i][1] += select_origin[1];
  864.         f->planepts[i][2] += select_origin[2];
  865.             }
  866.         }
  867.         Brush_Build(b, false);
  868.     if (b->patchBrush)
  869.     {
  870.       vec3_t v;
  871.       v[0] = x;
  872.       v[1] = y;
  873.       v[2] = z;
  874.       //Patch_Scale(b->nPatchID, select_origin, v);
  875.       Patch_Scale(b->pPatch, select_origin, v);
  876.     }
  877.     }
  878. }
  879.  
  880. void Select_RotateAxis (int axis, float deg, bool bPaint, bool bMouse)
  881. {
  882.     vec3_t    temp;
  883.     int        i, j;
  884.     vec_t    c, s;
  885.  
  886.     if (deg == 0)
  887.   {
  888.     //Sys_Printf("0 deg\n");
  889.         return;
  890.   }
  891.  
  892.   if (bMouse)
  893.   {
  894.     VectorCopy(g_pParentWnd->ActiveXY()->RotateOrigin(), select_origin);
  895.   }
  896.   else
  897.   {
  898.       Select_GetMid (select_origin);
  899.   }
  900.  
  901.     select_fliporder = false;
  902.  
  903.     if (deg == 90)
  904.     {
  905.         for (i=0 ; i<3 ; i++)
  906.         {
  907.             VectorCopy (vec3_origin, select_matrix[i]);
  908.             select_matrix[i][i] = 1;
  909.         }
  910.         i = (axis+1)%3;
  911.         j = (axis+2)%3;
  912.         VectorCopy (select_matrix[i], temp);
  913.         VectorCopy (select_matrix[j], select_matrix[i]);
  914.         VectorSubtract (vec3_origin, temp, select_matrix[j]);
  915.     }
  916.     else
  917.     {
  918.         deg = -deg;
  919.         if (deg == -180.0)
  920.         {
  921.             c = -1;
  922.             s = 0;
  923.         }
  924.         else if (deg == -270.0)
  925.         {
  926.             c = 0;
  927.             s = -1;
  928.         }
  929.         else
  930.         {
  931.             c = cos(deg * Q_PI / 180.0);
  932.             s = sin(deg * Q_PI / 180.0);
  933.         }
  934.  
  935.         for (i=0 ; i<3 ; i++)
  936.         {
  937.             VectorCopy (vec3_origin, select_matrix[i]);
  938.             select_matrix[i][i] = 1;
  939.         }
  940.  
  941.         switch (axis)
  942.         {
  943.         case 0:
  944.             select_matrix[1][1] = c;
  945.             select_matrix[1][2] = -s;
  946.             select_matrix[2][1] = s;
  947.             select_matrix[2][2] = c;
  948.             break;
  949.         case 1:
  950.             select_matrix[0][0] = c;
  951.             select_matrix[0][2] = s;
  952.             select_matrix[2][0] = -s;
  953.             select_matrix[2][2] = c;
  954.             break;
  955.         case 2:
  956.             select_matrix[0][0] = c;
  957.             select_matrix[0][1] = -s;
  958.             select_matrix[1][0] = s;
  959.             select_matrix[1][1] = c;
  960.             break;
  961.         }
  962.     }
  963.  
  964.     if (g_PrefsDlg.m_bRotateLock)
  965.         RotateTextures(axis, deg, select_origin);
  966.     Select_ApplyMatrix(!bMouse, true, axis, deg);
  967.  
  968.     if (bPaint)
  969.         Sys_UpdateWindows (W_ALL);
  970. }
  971.  
  972. /*
  973. ================================================================
  974.  
  975. GROUP SELECTIONS
  976.  
  977. ================================================================
  978. */
  979.  
  980. void Select_CompleteTall (void)
  981. {
  982.     brush_t    *b, *next;
  983.     //int        i;
  984.     vec3_t    mins, maxs;
  985.  
  986.     if (!QE_SingleBrush ())
  987.         return;
  988.  
  989.     g_qeglobals.d_select_mode = sel_brush;
  990.  
  991.     VectorCopy (selected_brushes.next->mins, mins);
  992.     VectorCopy (selected_brushes.next->maxs, maxs);
  993.     Select_Delete ();
  994.  
  995.   int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
  996.   int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
  997.  
  998.     for (b=active_brushes.next ; b != &active_brushes ; b=next)
  999.     {
  1000.         next = b->next;
  1001.  
  1002.     if ( (b->maxs[nDim1] > maxs[nDim1] || b->mins[nDim1] < mins[nDim1]) 
  1003.       || (b->maxs[nDim2] > maxs[nDim2] || b->mins[nDim2] < mins[nDim2]) )
  1004.       continue;
  1005.  
  1006.          if (FilterBrush (b))
  1007.              continue;
  1008.  
  1009.         Brush_RemoveFromList (b);
  1010.         Brush_AddToList (b, &selected_brushes);
  1011. #if 0
  1012.     // old stuff
  1013.     for (i=0 ; i<2 ; i++)
  1014.             if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i])
  1015.                 break;
  1016.         if (i == 2)
  1017.         {
  1018.             Brush_RemoveFromList (b);
  1019.             Brush_AddToList (b, &selected_brushes);
  1020.         }
  1021. #endif
  1022.     }
  1023.     Sys_UpdateWindows (W_ALL);
  1024. }
  1025.  
  1026. void Select_PartialTall (void)
  1027. {
  1028.     brush_t    *b, *next;
  1029.     //int        i;
  1030.     vec3_t    mins, maxs;
  1031.  
  1032.     if (!QE_SingleBrush ())
  1033.         return;
  1034.  
  1035.     g_qeglobals.d_select_mode = sel_brush;
  1036.  
  1037.     VectorCopy (selected_brushes.next->mins, mins);
  1038.     VectorCopy (selected_brushes.next->maxs, maxs);
  1039.     Select_Delete ();
  1040.  
  1041.   int nDim1 = (g_pParentWnd->ActiveXY()->GetViewType() == YZ) ? 1 : 0;
  1042.   int nDim2 = (g_pParentWnd->ActiveXY()->GetViewType() == XY) ? 1 : 2;
  1043.  
  1044.     for (b=active_brushes.next ; b != &active_brushes ; b=next)
  1045.     {
  1046.         next = b->next;
  1047.  
  1048.     if ( (b->mins[nDim1] > maxs[nDim1] || b->maxs[nDim1] < mins[nDim1]) 
  1049.       || (b->mins[nDim2] > maxs[nDim2] || b->maxs[nDim2] < mins[nDim2]) )
  1050.       continue;
  1051.  
  1052.          if (FilterBrush (b))
  1053.              continue;
  1054.  
  1055.       Brush_RemoveFromList (b);
  1056.         Brush_AddToList (b, &selected_brushes);
  1057.  
  1058.  
  1059. #if 0
  1060. // old stuff
  1061.         for (i=0 ; i<2 ; i++)
  1062.             if (b->mins[i] > maxs[i] || b->maxs[i] < mins[i])
  1063.                 break;
  1064.         if (i == 2)
  1065.         {
  1066.             Brush_RemoveFromList (b);
  1067.             Brush_AddToList (b, &selected_brushes);
  1068.         }
  1069. #endif
  1070.     }
  1071.     Sys_UpdateWindows (W_ALL);
  1072. }
  1073.  
  1074. void Select_Touching (void)
  1075. {
  1076.     brush_t    *b, *next;
  1077.     int        i;
  1078.     vec3_t    mins, maxs;
  1079.  
  1080.     if (!QE_SingleBrush ())
  1081.         return;
  1082.  
  1083.     g_qeglobals.d_select_mode = sel_brush;
  1084.  
  1085.     VectorCopy (selected_brushes.next->mins, mins);
  1086.     VectorCopy (selected_brushes.next->maxs, maxs);
  1087.  
  1088.     for (b=active_brushes.next ; b != &active_brushes ; b=next)
  1089.     {
  1090.         next = b->next;
  1091.  
  1092.          if (FilterBrush (b))
  1093.              continue;
  1094.  
  1095.         for (i=0 ; i<3 ; i++)
  1096.             if (b->mins[i] > maxs[i]+1 || b->maxs[i] < mins[i]-1)
  1097.                 break;
  1098.  
  1099.         if (i == 3)
  1100.         {
  1101.             Brush_RemoveFromList (b);
  1102.             Brush_AddToList (b, &selected_brushes);
  1103.         }
  1104.     }
  1105.     Sys_UpdateWindows (W_ALL);
  1106. }
  1107.  
  1108. void Select_Inside (void)
  1109. {
  1110.     brush_t    *b, *next;
  1111.     int        i;
  1112.     vec3_t    mins, maxs;
  1113.  
  1114.     if (!QE_SingleBrush ())
  1115.         return;
  1116.  
  1117.     g_qeglobals.d_select_mode = sel_brush;
  1118.  
  1119.     VectorCopy (selected_brushes.next->mins, mins);
  1120.     VectorCopy (selected_brushes.next->maxs, maxs);
  1121.     Select_Delete ();
  1122.  
  1123.     for (b=active_brushes.next ; b != &active_brushes ; b=next)
  1124.     {
  1125.         next = b->next;
  1126.  
  1127.          if (FilterBrush (b))
  1128.              continue;
  1129.  
  1130.         for (i=0 ; i<3 ; i++)
  1131.             if (b->maxs[i] > maxs[i] || b->mins[i] < mins[i])
  1132.                 break;
  1133.         if (i == 3)
  1134.         {
  1135.             Brush_RemoveFromList (b);
  1136.             Brush_AddToList (b, &selected_brushes);
  1137.         }
  1138.     }
  1139.     Sys_UpdateWindows (W_ALL);
  1140. }
  1141.  
  1142. /*
  1143. =============
  1144. Select_Ungroup
  1145.  
  1146. Turn the currently selected entity back into normal brushes
  1147. =============
  1148. */
  1149. void Select_Ungroup(void)
  1150. {
  1151.     int numselectedgroups;
  1152.     entity_t    *e;
  1153.     brush_t        *b, *sb;
  1154.  
  1155.     numselectedgroups = 0;
  1156.     for (sb = selected_brushes.next; sb != &selected_brushes; sb = sb->next)
  1157.     {
  1158.         e = sb->owner;
  1159.  
  1160.         if (!e || e == world_entity || e->eclass->fixedsize)
  1161.         {
  1162.             continue;
  1163.         }
  1164.  
  1165.         for (b = e->brushes.onext; b != &e->brushes; b = e->brushes.onext)
  1166.         {
  1167.             //Brush_RemoveFromList (b);
  1168.             //Brush_AddToList (b, &active_brushes);
  1169.             Entity_UnlinkBrush (b);
  1170.             Entity_LinkBrush (world_entity, b);
  1171.             Brush_Build( b );
  1172.             b->owner = world_entity;
  1173.         }
  1174.         Entity_Free (e);
  1175.         numselectedgroups++;
  1176.     }
  1177.  
  1178.     if (numselectedgroups <= 0)
  1179.     {
  1180.         Sys_Printf("No grouped entities selected.\n");
  1181.         return;
  1182.     }
  1183.     Sys_Printf("Ungrouped %d entit%s.\n", numselectedgroups, (numselectedgroups == 1)?"y":"ies");
  1184.     Sys_UpdateWindows (W_ALL);
  1185. }
  1186.  
  1187.  
  1188. /*
  1189. ====================
  1190. Select_MakeStructural
  1191. ====================
  1192. */
  1193. void Select_MakeStructural (void)
  1194. {
  1195.     brush_t    *b;
  1196.     face_t    *f;
  1197.  
  1198.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  1199.         for (f=b->brush_faces ; f ; f=f->next)
  1200.             f->texdef.contents &= ~CONTENTS_DETAIL;
  1201.     Select_Deselect ();
  1202.     Sys_UpdateWindows (W_ALL);
  1203. }
  1204.  
  1205. void Select_MakeDetail (void)
  1206. {
  1207.     brush_t    *b;
  1208.     face_t    *f;
  1209.  
  1210.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  1211.         for (f=b->brush_faces ; f ; f=f->next)
  1212.             f->texdef.contents |= CONTENTS_DETAIL;
  1213.     Select_Deselect ();
  1214.     Sys_UpdateWindows (W_ALL);
  1215. }
  1216.  
  1217. void Select_ShiftTexture(int x, int y)
  1218. {
  1219.     brush_t        *b;
  1220.     face_t        *f;
  1221.  
  1222.   int nFaceCount = g_ptrSelectedFaces.GetSize();
  1223.  
  1224.     if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
  1225.         return;
  1226.  
  1227.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  1228.     {
  1229.         for (f=b->brush_faces ; f ; f=f->next)
  1230.         {
  1231.             if (g_qeglobals.m_bBrushPrimitMode)
  1232.             {
  1233.                 // use face normal to compute a true translation
  1234.                 Select_ShiftTexture_BrushPrimit( f, x, y );
  1235.             }
  1236.             else
  1237.             {
  1238.                 f->texdef.shift[0] += x;
  1239.                 f->texdef.shift[1] += y;
  1240.             }
  1241.         }
  1242.         Brush_Build(b);
  1243.         if (b->patchBrush)
  1244.         {
  1245.             //Patch_ShiftTexture(b->nPatchID, x, y);
  1246.             Patch_ShiftTexture(b->pPatch, x, y);
  1247.         }
  1248.     }
  1249.  
  1250.     if (nFaceCount > 0)
  1251.     {
  1252.     for (int i = 0; i < nFaceCount; i++)
  1253.     {
  1254.       face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
  1255.       brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
  1256.           if (g_qeglobals.m_bBrushPrimitMode)
  1257.           {
  1258.  
  1259.               // use face normal to compute a true translation
  1260.         // Select_ShiftTexture_BrushPrimit( selected_face, x, y );
  1261.               // use camera view to compute texture shift
  1262.               g_pParentWnd->GetCamera()->ShiftTexture_BrushPrimit( selFace, x, y );
  1263.       }
  1264.           else
  1265.           {
  1266.               selFace->texdef.shift[0] += x;
  1267.               selFace->texdef.shift[1] += y;
  1268.           }
  1269.           Brush_Build(selBrush);
  1270.     }
  1271.     }
  1272.  
  1273.     Sys_UpdateWindows (W_CAMERA);
  1274. }
  1275.  
  1276. void Select_ScaleTexture(int x, int y)
  1277. {
  1278.     brush_t        *b;
  1279.     face_t        *f;
  1280.  
  1281.   int nFaceCount = g_ptrSelectedFaces.GetSize();
  1282.  
  1283.   if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
  1284.     {
  1285.         return;
  1286.     }
  1287.  
  1288.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  1289.     {
  1290.         for (f=b->brush_faces ; f ; f=f->next)
  1291.         {
  1292.             if (g_qeglobals.m_bBrushPrimitMode)
  1293.             {
  1294.                 // apply same scale as the spinner button of the surface inspector
  1295.                 float    shift[2];
  1296.                 float    rotate;
  1297.                 float    scale[2];
  1298.                 brushprimit_texdef_t bp; 
  1299.                 // compute normalized texture matrix
  1300.                 ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL );
  1301.                 // compute fake shift scale rot
  1302.                 TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
  1303.                 // update
  1304.                 scale[0]+=static_cast<float>(x)*0.1;
  1305.                 scale[1]+=static_cast<float>(y)*0.1;
  1306.                 // compute new normalized texture matrix
  1307.                 FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
  1308.                 // apply to face texture matrix
  1309.                 ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture );
  1310.             }
  1311.             else
  1312.             {
  1313.                 f->texdef.scale[0] += x;
  1314.                 f->texdef.scale[1] += y;
  1315.             }
  1316.         }
  1317.         Brush_Build(b);
  1318.         if (b->patchBrush)
  1319.         {
  1320.             Patch_ScaleTexture(b->pPatch, x, y);
  1321.         }
  1322.     }
  1323.  
  1324.     if (nFaceCount > 0)
  1325.     {
  1326.     for (int i = 0; i < nFaceCount; i++)
  1327.     {
  1328.       face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
  1329.       brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
  1330.           if (g_qeglobals.m_bBrushPrimitMode)
  1331.           {
  1332.               float    shift[2];
  1333.               float    rotate;
  1334.               float    scale[2];
  1335.               brushprimit_texdef_t bp; 
  1336.               ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL );
  1337.               TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
  1338.               scale[0]+=static_cast<float>(x)*0.1;
  1339.               scale[1]+=static_cast<float>(y)*0.1;
  1340.               FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
  1341.               ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture );
  1342.           }
  1343.           else
  1344.           {
  1345.               selFace->texdef.scale[0] += x;
  1346.               selFace->texdef.scale[1] += y;
  1347.           }
  1348.           Brush_Build(selBrush);
  1349.     }
  1350.     }
  1351.  
  1352.     Sys_UpdateWindows (W_CAMERA);
  1353. }
  1354.  
  1355. void Select_RotateTexture(int amt)
  1356. {
  1357.     brush_t        *b;
  1358.     face_t        *f;
  1359.  
  1360.   int nFaceCount = g_ptrSelectedFaces.GetSize();
  1361.  
  1362.   if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
  1363.     {
  1364.         return;
  1365.     }
  1366.  
  1367.     for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  1368.     {
  1369.         for (f=b->brush_faces ; f ; f=f->next)
  1370.         {
  1371.             if (g_qeglobals.m_bBrushPrimitMode)
  1372.             {
  1373.                 // apply same scale as the spinner button of the surface inspector
  1374.                 float    shift[2];
  1375.                 float    rotate;
  1376.                 float    scale[2];
  1377.                 brushprimit_texdef_t bp; 
  1378.                 // compute normalized texture matrix
  1379.                 ConvertTexMatWithQTexture( &f->brushprimit_texdef, f->d_texture, &bp, NULL );
  1380.                 // compute fake shift scale rot
  1381.                 TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
  1382.                 // update
  1383.                 rotate += amt;
  1384.                 // compute new normalized texture matrix
  1385.                 FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
  1386.                 // apply to face texture matrix
  1387.                 ConvertTexMatWithQTexture( &bp, NULL, &f->brushprimit_texdef, f->d_texture );
  1388.             }
  1389.             else
  1390.             {
  1391.                 f->texdef.rotate += amt;
  1392.                 f->texdef.rotate = static_cast<int>(f->texdef.rotate) % 360;
  1393.             }
  1394.         }
  1395.         Brush_Build(b);
  1396.         if (b->patchBrush)
  1397.         {
  1398.             //Patch_RotateTexture(b->nPatchID, amt);
  1399.             Patch_RotateTexture(b->pPatch, amt);
  1400.         }
  1401.     }
  1402.     
  1403.     if (nFaceCount > 0)
  1404.     {
  1405.     for (int i = 0; i < nFaceCount; i++)
  1406.     {
  1407.       face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
  1408.       brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
  1409.           if (g_qeglobals.m_bBrushPrimitMode)
  1410.           {
  1411.               float    shift[2];
  1412.               float    rotate;
  1413.               float    scale[2];
  1414.               brushprimit_texdef_t bp; 
  1415.               ConvertTexMatWithQTexture( &selFace->brushprimit_texdef, selFace->d_texture, &bp, NULL );
  1416.               TexMatToFakeTexCoords( bp.coords, shift, &rotate, scale );
  1417.               rotate += amt;
  1418.               FakeTexCoordsToTexMat( shift, rotate, scale, bp.coords );
  1419.               ConvertTexMatWithQTexture( &bp, NULL, &selFace->brushprimit_texdef, selFace->d_texture );
  1420.           }
  1421.           else
  1422.           {
  1423.               selFace->texdef.rotate += amt;
  1424.               selFace->texdef.rotate = static_cast<int>(selFace->texdef.rotate) % 360;
  1425.           }
  1426.           Brush_Build(selBrush);
  1427.     }
  1428.     }
  1429.  
  1430.     Sys_UpdateWindows (W_CAMERA);
  1431. }
  1432.  
  1433.  
  1434. void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce)
  1435. {
  1436.   brush_t* pList = (bSelected) ? &selected_brushes : &active_brushes;
  1437.   if (!bSelected)
  1438.     Select_Deselect();
  1439.  
  1440.   for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next)
  1441.     {
  1442.     if (pBrush->patchBrush)
  1443.     {
  1444.       Patch_FindReplaceTexture(pBrush, pFind, pReplace, bForce);
  1445.     }
  1446.  
  1447.     for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next)
  1448.     {
  1449.           if(bForce || strcmpi(pFace->texdef.name, pFind) == 0)
  1450.       {
  1451.         pFace->d_texture = Texture_ForName(pReplace);
  1452.         //strcpy(pFace->texdef.name, pReplace);
  1453.         pFace->texdef.SetName(pReplace);
  1454.       }
  1455.     }
  1456.     Brush_Build(pBrush);
  1457.     }
  1458.     Sys_UpdateWindows (W_CAMERA);
  1459. }
  1460.  
  1461.  
  1462. void Select_AllOfType()
  1463. {
  1464.     brush_t    *b, *next;
  1465.     entity_t    *e;
  1466.     if ( (selected_brushes.next == &selected_brushes)
  1467.         || (selected_brushes.next->next != &selected_brushes) )
  1468.     {
  1469.  
  1470.     CString strName;
  1471.     if (g_ptrSelectedFaces.GetSize() == 0)
  1472.     {
  1473.       strName = g_qeglobals.d_texturewin.texdef.name;
  1474.     }
  1475.     else
  1476.     {
  1477.       face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(0));
  1478.       strName = selFace->texdef.name;
  1479.     }
  1480.  
  1481.     Select_Deselect();
  1482.       for (b=active_brushes.next ; b != &active_brushes ; b=next)
  1483.     {
  1484.           next = b->next;
  1485.         
  1486.       if (FilterBrush (b))
  1487.              continue;
  1488.  
  1489.       if (b->patchBrush)
  1490.       {
  1491.         if (strcmpi(strName, b->pPatch->d_texture->name) == 0)
  1492.         {
  1493.                 Brush_RemoveFromList (b);
  1494.                 Brush_AddToList (b, &selected_brushes);
  1495.         }
  1496.       }
  1497.       else
  1498.       {
  1499.         for (face_t* pFace = b->brush_faces; pFace; pFace = pFace->next)
  1500.         {
  1501.           if (strcmpi(strName, pFace->texdef.name) == 0)
  1502.           {
  1503.                   Brush_RemoveFromList (b);
  1504.                   Brush_AddToList (b, &selected_brushes);
  1505.           }
  1506.         }
  1507.       }
  1508.     }
  1509.     Sys_UpdateWindows(W_ALL);
  1510.     return;
  1511.   }
  1512.  
  1513.   
  1514.   b = selected_brushes.next;
  1515.     e = b->owner;
  1516.  
  1517.   if (e != NULL)
  1518.   {
  1519.     if (e != world_entity)
  1520.     {
  1521.       CString strName = e->eclass->name;
  1522.       CString strKey, strVal;
  1523.       bool bCriteria = GetSelectAllCriteria(strKey, strVal);
  1524.       Sys_Printf("Selecting all %s(s)\n", strName);
  1525.       Select_Deselect();
  1526.  
  1527.         for (b=active_brushes.next ; b != &active_brushes ; b=next)
  1528.         {
  1529.             next = b->next;
  1530.              
  1531.         if (FilterBrush (b))
  1532.                  continue;
  1533.  
  1534.         e = b->owner;
  1535.         if (e != NULL)
  1536.         {
  1537.           if (strcmpi(e->eclass->name, strName) == 0)
  1538.           {
  1539.             bool doIt = true;
  1540.             if (bCriteria) {
  1541.               CString str = ValueForKey (e, strKey);
  1542.               if (str.CompareNoCase(strVal) != 0) {
  1543.                 doIt = false;
  1544.               }
  1545.             }
  1546.             if (doIt) {
  1547.                   Brush_RemoveFromList (b);
  1548.                   Brush_AddToList (b, &selected_brushes);
  1549.             }
  1550.           }
  1551.         }
  1552.       }
  1553.     }
  1554.   }
  1555.     Sys_UpdateWindows (W_ALL);
  1556.  
  1557. }
  1558.  
  1559. void Select_Reselect()
  1560. {
  1561.   CPtrArray holdArray;
  1562.     for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
  1563.     {
  1564.     holdArray.Add(reinterpret_cast<void*>(b));
  1565.     }
  1566.  
  1567.   int n = holdArray.GetSize();
  1568.   while (n-- > 0)
  1569.   {
  1570.     b = reinterpret_cast<brush_t*>(holdArray.GetAt(n));
  1571.     Select_Brush(b);
  1572.   }
  1573.     Sys_UpdateWindows (W_ALL);
  1574. }
  1575.  
  1576.  
  1577. void Select_FitTexture(int nHeight, int nWidth)
  1578. {
  1579.     brush_t        *b;
  1580.  
  1581.   int nFaceCount = g_ptrSelectedFaces.GetSize();
  1582.  
  1583.   if(selected_brushes.next == &selected_brushes && nFaceCount == 0)
  1584.         return;
  1585.  
  1586.   for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  1587.     {
  1588.     Brush_FitTexture(b, nHeight, nWidth);
  1589.         Brush_Build(b);
  1590.     }
  1591.  
  1592.     if (nFaceCount > 0)
  1593.     {
  1594.     for (int i = 0; i < nFaceCount; i++)
  1595.     {
  1596.       face_t *selFace = reinterpret_cast<face_t*>(g_ptrSelectedFaces.GetAt(i));
  1597.       brush_t *selBrush = reinterpret_cast<brush_t*>(g_ptrSelectedFaceBrushes.GetAt(i));
  1598.       Face_FitTexture(selFace, nHeight, nWidth);
  1599.           Brush_Build(selBrush);
  1600.     }
  1601.     }
  1602.  
  1603.     Sys_UpdateWindows (W_CAMERA);
  1604. }
  1605.  
  1606. void Select_AxialTexture()
  1607. {
  1608.  
  1609. }
  1610.  
  1611. void Select_Hide()
  1612. {
  1613.     for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
  1614.     {
  1615.     b->hiddenBrush = true;
  1616.     }
  1617.     Sys_UpdateWindows (W_ALL);
  1618. }
  1619.  
  1620. void Select_ShowAllHidden()
  1621. {
  1622.   brush_t* b;
  1623.     for (b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
  1624.     {
  1625.     b->hiddenBrush = false;
  1626.     }
  1627.     for (b=active_brushes.next ; b && b != &active_brushes ; b=b->next)
  1628.     {
  1629.     b->hiddenBrush = false;
  1630.     }
  1631.     Sys_UpdateWindows (W_ALL);
  1632. }
  1633.  
  1634.  
  1635. /*
  1636. ============
  1637. Select_Invert
  1638. ============
  1639. */
  1640. void Select_Invert(void)
  1641. {
  1642.     brush_t *next, *prev;
  1643.  
  1644.     Sys_Printf("inverting selection...\n");
  1645.  
  1646.     next = active_brushes.next;
  1647.     prev = active_brushes.prev;
  1648.     if (selected_brushes.next != &selected_brushes)
  1649.     {
  1650.         active_brushes.next = selected_brushes.next;
  1651.         active_brushes.prev = selected_brushes.prev;
  1652.         active_brushes.next->prev = &active_brushes;
  1653.         active_brushes.prev->next = &active_brushes;
  1654.     }
  1655.     else
  1656.     {
  1657.         active_brushes.next = &active_brushes;
  1658.         active_brushes.prev = &active_brushes;
  1659.     }
  1660.     if (next != &active_brushes)
  1661.     {
  1662.         selected_brushes.next = next;
  1663.         selected_brushes.prev = prev;
  1664.         selected_brushes.next->prev = &selected_brushes;
  1665.         selected_brushes.prev->next = &selected_brushes;
  1666.     }
  1667.     else
  1668.     {
  1669.         selected_brushes.next = &selected_brushes;
  1670.         selected_brushes.prev = &selected_brushes;
  1671.     }
  1672.  
  1673.     Sys_UpdateWindows(W_ALL);
  1674.  
  1675.     Sys_Printf("done.\n");
  1676. }
  1677.  
  1678.  
  1679. /* 
  1680. ===========
  1681. Select_Name
  1682. ===========
  1683. */
  1684. void Select_Name(const char *pName)
  1685. {
  1686.     if (g_qeglobals.m_bBrushPrimitMode)
  1687.   {
  1688.       for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
  1689.       {
  1690.       Brush_SetEpair(b, "Name", pName);
  1691.       }
  1692.   }
  1693. }
  1694.  
  1695. /* 
  1696. =================
  1697. Select_AddToGroup
  1698. add selected brushes to a group, update the tree
  1699. =================
  1700. */
  1701. void Select_AddToGroup(const char *pName)
  1702. {
  1703.     if (g_qeglobals.m_bBrushPrimitMode)
  1704.   {
  1705.       for (brush_t* b=selected_brushes.next ; b && b != &selected_brushes ; b=b->next)
  1706.       {
  1707.       Brush_SetEpair(b, "group", pName);
  1708.             Group_AddToProperGroup(b);
  1709.       }
  1710.   }
  1711. }
  1712.