/* Copyright (c) 2002-2012 Croteam Ltd. This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "Engine/StdH.h" #include #include #include #include #include #include static PIX _pixSizeI; static PIX _pixSizeJ; UBYTE *_pubLassoBuffer = NULL; // init select-on-render functionality void InitSelectOnRender(PIX pixSizeI, PIX pixSizeJ) { _pixSizeI = pixSizeI; _pixSizeJ = pixSizeJ; // if entity selecting not required if (_pselenSelectOnRender==NULL) { // if vertex selecting not requred if (_pselbvxtSelectOnRender==NULL) { // do nothing return; } // if not lasso and not alternative else if (_pavpixSelectLasso==NULL && !_bSelectAlternative) { // deselect all vertices _pselbvxtSelectOnRender->Clear(); } } // if lasso selection is not on, or is invalid if (_pavpixSelectLasso==NULL || _pavpixSelectLasso->Count()<3 || pixSizeI<2 || pixSizeJ<2) { // do nothing return; } SLONG slMaxOffset = pixSizeI*pixSizeJ-1; // allocate lasso buffer _pubLassoBuffer = (UBYTE*)AllocMemory(_pixSizeI*_pixSizeJ); // clear it memset(_pubLassoBuffer, 0, _pixSizeI*_pixSizeJ); // for each line in lasso INDEX ctpt = _pavpixSelectLasso->Count(); for (INDEX ipt=0; ipt=_pixSizeI || pixI1<0 || pixI1>=_pixSizeI || pixJ0<0 || pixJ0>=_pixSizeJ || pixJ1<0 || pixJ1>=_pixSizeJ) { // skip this line continue; } // if line is horizontal if (pixJ0==pixJ1) { // skip it continue; // if line goes upwards } else if (pixJ0>pixJ1) { // make it go downwards Swap(pixI0, pixI1); Swap(pixJ0, pixJ1); } // calculate step FIX16_16 xStep = FIX16_16(FLOAT(pixI1-pixI0)/(pixJ1-pixJ0)); // start in first row FIX16_16 xI = FIX16_16(pixI0); // for each row for(PIX pixJ = pixJ0; pixJ=0 && slOffset<=slMaxOffset) { // invert the pixel in that row _pubLassoBuffer[slOffset] ^= 0xFF; } // step the line xI+=xStep; } } // for each row in lasso buffer for(PIX pixJ = 0; pixJ<_pixSizeJ; pixJ++) { // for each pixel in the row, except the last one UBYTE *pub = _pubLassoBuffer+pixJ*_pixSizeI; for(PIX pixI = 0; pixI<_pixSizeI-1; pixI++) { // xor it to the next one pub[1]^=pub[0]; pub++; } } } // end select-on-render functionality void EndSelectOnRender(void) { // free lasso buffer if (_pubLassoBuffer!=NULL) { FreeMemory(_pubLassoBuffer); _pubLassoBuffer = NULL; } } // check if a vertex is influenced by current select-on-render selection void SelectVertexOnRender(CBrushVertex &bvx, const PIX2D &vpix) { // if not selecting if (_pselbvxtSelectOnRender==NULL) { // do nothing return; } // if the vertex is out of screen if (vpix(1)<0 || vpix(1)>=_pixSizeI || vpix(2)<0 || vpix(2)>=_pixSizeJ) { // do nothing return; } // if selecting without lasso if (_pubLassoBuffer==NULL) { // if vertex is near point if ((vpix-_vpixSelectNearPoint).Length()<_pixDeltaAroundVertex) { // if selected if (bvx.IsSelected(BVXF_SELECTED)) { // deselect it _pselbvxtSelectOnRender->Deselect(bvx); // if not selected } else { // select it _pselbvxtSelectOnRender->Select(bvx); } } // if selecting with lasso } else { // if the vertex is set in lasso buffer if (_pubLassoBuffer[vpix(2)*_pixSizeI+vpix(1)]) { // if alternative if (_bSelectAlternative) { // deselect if (bvx.IsSelected(BVXF_SELECTED)) { _pselbvxtSelectOnRender->Deselect(bvx); } // if normal } else { // select if (!bvx.IsSelected(BVXF_SELECTED)) { _pselbvxtSelectOnRender->Select(bvx); } } } } } // check if given vertice is selected by lasso BOOL IsVertexInLasso( CProjection3D &prProjection, const FLOAT3D &vtx, FLOATmatrix3D *pmR, FLOAT3D &vOffset) { // convert from relative to absolute space FLOAT3D vAbsolute = vOffset+vtx*(*pmR); FLOAT3D vtxProjected; prProjection.ProjectCoordinate( vAbsolute, vtxProjected); PIX2D vpix; vpix(1) = (PIX) vtxProjected(1); // convert coordinate into screen representation vpix(2) = (PIX) (_pixSizeJ-vtxProjected(2)); // if the vertex is out of screen if (vpix(1)<0 || vpix(1)>=_pixSizeI || vpix(2)<0 || vpix(2)>=_pixSizeJ) { // no selecting return FALSE; } // if the vertex is set in lasso buffer if (_pubLassoBuffer!=NULL &&_pubLassoBuffer[vpix(2)*_pixSizeI+vpix(1)]) { return TRUE; } return FALSE; } // check if given bounding box is selected by lasso BOOL IsBoundingBoxInLasso( CProjection3D &prProjection, const FLOATaabbox3D &box, FLOATmatrix3D *pmR, FLOAT3D &vOffset) { FLOAT3D vMin = box.Min(); FLOAT3D vMax = box.Max(); // test lasso influence for all of bounding box's vertices if( IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMin(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMin(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMax(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMax(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMin(2), vMax(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMin(2), vMax(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMax(2), vMax(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMax(2), vMax(3)), pmR, vOffset) ) { return TRUE; } return FALSE; } // check if all of the corners of entity's bounding box are influenced by current select-on-render selection void SelectEntityOnRender(CProjection3D &prProjection, CEntity &en) { FLOATaabbox3D bbox; FLOATmatrix3D mOne = FLOATmatrix3D(0.0f); mOne.Diagonal(1.0f); FLOATmatrix3D *pmR; FLOAT3D vOffset; // if this entity is model if (en.en_RenderType==CEntity::RT_MODEL || en.en_RenderType==CEntity::RT_EDITORMODEL) { // get bbox of current frame CModelObject *pmo = en.GetModelObject(); pmo->GetCurrentFrameBBox( bbox); pmR = &en.en_mRotation; vOffset = en.GetPlacement().pl_PositionVector; } // if it is ska model else if(en.en_RenderType==CEntity::RT_SKAMODEL || en.en_RenderType==CEntity::RT_SKAEDITORMODEL) { en.GetModelInstance()->GetCurrentColisionBox( bbox); pmR = &en.en_mRotation; vOffset = en.GetPlacement().pl_PositionVector; } // if it is brush else { // get bbox of brush's first mip CBrush3D *pbr = en.GetBrush(); CBrushMip *pbrmip = pbr->GetFirstMip(); bbox = pbrmip->bm_boxBoundingBox; pmR = &mOne; vOffset = FLOAT3D( 0.0f, 0.0f, 0.0f); } if( IsBoundingBoxInLasso( prProjection, bbox, pmR, vOffset)) { if( _bSelectAlternative) { // deselect if (en.IsSelected(ENF_SELECTED)) { _pselenSelectOnRender->Deselect(en); } } else { // select if (!en.IsSelected(ENF_SELECTED)) { _pselenSelectOnRender->Select(en); } } } }