float CStructure::VisibleRange() const { if (IsConstructing()) return GetBoundingRadius()*2; return BaseClass::VisibleRange(); }
float CSupplier::AvailableArea(int iArea) const { if (iArea == 1) return GetDataFlowRadius() + GetBoundingRadius(); return BaseClass::AvailableArea(iArea); }
void CDigitanksEntity::InterceptSupplyLines() { // Haha... no. if (dynamic_cast<CSupplyLine*>(this)) return; if (!GetPlayerOwner()) return; for (size_t i = 0; i < GameServer()->GetMaxEntities(); i++) { CBaseEntity* pEntity = CBaseEntity::GetEntity(i); if (!pEntity) continue; CSupplyLine* pSupplyLine = dynamic_cast<CSupplyLine*>(pEntity); if (!pSupplyLine) continue; if (pSupplyLine->GetPlayerOwner() == GetPlayerOwner()) continue; if (!pSupplyLine->GetPlayerOwner()) continue; if (!pSupplyLine->GetSupplier() || !pSupplyLine->GetEntity()) continue; Vector vecEntity = GetGlobalOrigin(); vecEntity.z = 0; Vector vecSupplier = pSupplyLine->GetSupplier()->GetGlobalOrigin(); vecSupplier.z = 0; Vector vecUnit = pSupplyLine->GetEntity()->GetGlobalOrigin(); vecUnit.z = 0; if (DistanceToLineSegment(vecEntity, vecSupplier, vecUnit) > GetBoundingRadius()+4) continue; bool bFound = false; for (size_t j = 0; j < m_ahSupplyLinesIntercepted.size(); j++) { if (pSupplyLine == m_ahSupplyLinesIntercepted[j]) { bFound = true; break; } } if (!bFound) { pSupplyLine->Intercept(0.2f); m_ahSupplyLinesIntercepted.push_back(pSupplyLine); } } }
bool Entity::HasCollidedWith(Entity* other) { double distanceSqr = GetPosition().DistanceToSqr(other->GetPosition()); double totalRadius = GetBoundingRadius() + other->GetBoundingRadius(); double totalRadiusSqr = totalRadius * totalRadius; return distanceSqr < totalRadiusSqr; }
void CStructure::FindGround() { float flHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x, GetGlobalOrigin().y); float flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x + GetBoundingRadius(), GetGlobalOrigin().y + GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x + GetBoundingRadius(), GetGlobalOrigin().y - GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x - GetBoundingRadius(), GetGlobalOrigin().y + GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; flCornerHeight = DigitanksGame()->GetTerrain()->GetHeight(GetGlobalOrigin().x - GetBoundingRadius(), GetGlobalOrigin().y - GetBoundingRadius()); if (flCornerHeight > flHeight) flHeight = flCornerHeight; SetGlobalOrigin(Vector(GetGlobalOrigin().x, GetGlobalOrigin().y, flHeight + GetBoundingRadius()/2 + 2)); }
bool D_PAD::HitTest( const wxPoint& aPosition ) { int dx, dy; double dist; wxPoint shape_pos = ReturnShapePos(); wxPoint delta = aPosition - shape_pos; // first test: a test point must be inside a minimum sized bounding circle. int radius = GetBoundingRadius(); if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) ) return false; dx = m_Size.x >> 1; // dx also is the radius for rounded pads dy = m_Size.y >> 1; switch( m_PadShape & 0x7F ) { case PAD_CIRCLE: dist = hypot( delta.x, delta.y ); if( KiROUND( dist ) <= dx ) return true; break; case PAD_TRAPEZOID: { wxPoint poly[4]; BuildPadPolygon( poly, wxSize(0,0), 0 ); RotatePoint( &delta, -m_Orient ); return TestPointInsidePolygon( poly, 4, delta ); } default: RotatePoint( &delta, -m_Orient ); if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) ) return true; break; } return false; }
void DynamicBody::CalcExternalForce() { // gravity Body *body = GetFrame()->GetBodyFor(); if (body && !body->IsType(Object::SPACESTATION)) { // they ought to have mass though... vector3d b1b2 = GetPosition(); double m1m2 = GetMass() * body->GetMass(); double invrsqr = 1.0 / b1b2.LengthSqr(); double force = G*m1m2 * invrsqr; m_externalForce = -b1b2 * sqrt(invrsqr) * force; } else m_externalForce = vector3d(0.0); m_gravityForce = m_externalForce; // atmospheric drag const double speed = m_vel.Length(); if ((speed > 0) && body && body->IsType(Object::PLANET)) { Planet *planet = static_cast<Planet*>(body); double dist = GetPosition().Length(); double pressure, density; planet->GetAtmosphericState(dist, &pressure, &density); const double radius = GetBoundingRadius(); const double AREA = radius; // ^^^ yes that is as stupid as it looks const double DRAG_COEFF = 0.1; // 'smooth sphere' vector3d dragDir = -m_vel.Normalized(); vector3d fDrag = 0.5*density*speed*speed*AREA*DRAG_COEFF*dragDir; // make this a bit less daft at high time accel // only allow atmosForce to increase by .1g per frame vector3d f1g = m_atmosForce + dragDir * GetMass(); if (fDrag.LengthSqr() > f1g.LengthSqr()) m_atmosForce = f1g; else m_atmosForce = fDrag; m_externalForce += m_atmosForce; } // centrifugal and coriolis forces for rotating frames vector3d angRot = GetFrame()->GetAngVelocity(); if (angRot.LengthSqr() > 0.0) { m_externalForce -= m_mass * angRot.Cross(angRot.Cross(GetPosition())); // centrifugal m_externalForce -= 2 * m_mass * angRot.Cross(GetVelocity()); // coriolis } }
bool D_PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const { EDA_RECT arect = aRect; arect.Normalize(); arect.Inflate( aAccuracy ); wxPoint shapePos = ShapePos(); EDA_RECT shapeRect; int r; EDA_RECT bb = GetBoundingBox(); wxPoint endCenter; int radius; if( !arect.Intersects( bb ) ) return false; // This covers total containment for all test cases if( arect.Contains( bb ) ) return true; switch( GetShape() ) { case PAD_SHAPE_CIRCLE: return arect.IntersectsCircle( GetPosition(), GetBoundingRadius() ); case PAD_SHAPE_RECT: shapeRect.SetOrigin( shapePos ); shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 ); return arect.Intersects( shapeRect, m_Orient ); case PAD_SHAPE_OVAL: // Circlular test if dimensions are equal if( m_Size.x == m_Size.y ) return arect.IntersectsCircle( shapePos, GetBoundingRadius() ); shapeRect.SetOrigin( shapePos ); // Horizontal dimension is greater if( m_Size.x > m_Size.y ) { radius = m_Size.y / 2; shapeRect.Inflate( m_Size.x / 2 - radius, radius ); endCenter = wxPoint( m_Size.x / 2 - radius, 0 ); RotatePoint( &endCenter, m_Orient ); // Test circular ends if( arect.IntersectsCircle( shapePos + endCenter, radius ) || arect.IntersectsCircle( shapePos - endCenter, radius ) ) { return true; } } else { radius = m_Size.x / 2; shapeRect.Inflate( radius, m_Size.y / 2 - radius ); endCenter = wxPoint( 0, m_Size.y / 2 - radius ); RotatePoint( &endCenter, m_Orient ); // Test circular ends if( arect.IntersectsCircle( shapePos + endCenter, radius ) || arect.IntersectsCircle( shapePos - endCenter, radius ) ) { return true; } } // Test rectangular portion between rounded ends if( arect.Intersects( shapeRect, m_Orient ) ) { return true; } break; case PAD_SHAPE_TRAPEZOID: /* Trapezoid intersection tests: * A) Any points of rect inside trapezoid * B) Any points of trapezoid inside rect * C) Any sides of trapezoid cross rect */ { wxPoint poly[4]; BuildPadPolygon( poly, wxSize( 0, 0 ), 0 ); wxPoint corners[4]; corners[0] = wxPoint( arect.GetLeft(), arect.GetTop() ); corners[1] = wxPoint( arect.GetRight(), arect.GetTop() ); corners[2] = wxPoint( arect.GetRight(), arect.GetBottom() ); corners[3] = wxPoint( arect.GetLeft(), arect.GetBottom() ); for( int i=0; i<4; i++ ) { RotatePoint( &poly[i], m_Orient ); poly[i] += shapePos; } for( int ii=0; ii<4; ii++ ) { if( TestPointInsidePolygon( poly, 4, corners[ii] ) ) { return true; } if( arect.Contains( poly[ii] ) ) { return true; } if( arect.Intersects( poly[ii], poly[(ii+1) % 4] ) ) { return true; } } return false; } case PAD_SHAPE_ROUNDRECT: /* RoundRect intersection can be broken up into simple tests: * a) Test intersection of horizontal rect * b) Test intersection of vertical rect * c) Test intersection of each corner */ r = GetRoundRectCornerRadius(); /* Test A - intersection of horizontal rect */ shapeRect.SetSize( 0, 0 ); shapeRect.SetOrigin( shapePos ); shapeRect.Inflate( m_Size.x / 2, m_Size.y / 2 - r ); // Short-circuit test for zero width or height if( shapeRect.GetWidth() > 0 && shapeRect.GetHeight() > 0 && arect.Intersects( shapeRect, m_Orient ) ) { return true; } /* Test B - intersection of vertical rect */ shapeRect.SetSize( 0, 0 ); shapeRect.SetOrigin( shapePos ); shapeRect.Inflate( m_Size.x / 2 - r, m_Size.y / 2 ); // Short-circuit test for zero width or height if( shapeRect.GetWidth() > 0 && shapeRect.GetHeight() > 0 && arect.Intersects( shapeRect, m_Orient ) ) { return true; } /* Test C - intersection of each corner */ endCenter = wxPoint( m_Size.x / 2 - r, m_Size.y / 2 - r ); RotatePoint( &endCenter, m_Orient ); if( arect.IntersectsCircle( shapePos + endCenter, r ) || arect.IntersectsCircle( shapePos - endCenter, r ) ) { return true; } endCenter = wxPoint( m_Size.x / 2 - r, -m_Size.y / 2 + r ); RotatePoint( &endCenter, m_Orient ); if( arect.IntersectsCircle( shapePos + endCenter, r ) || arect.IntersectsCircle( shapePos - endCenter, r ) ) { return true; } break; default: break; } return false; }
bool D_PAD::HitTest( const wxPoint& aPosition ) const { int dx, dy; wxPoint shape_pos = ShapePos(); wxPoint delta = aPosition - shape_pos; // first test: a test point must be inside a minimum sized bounding circle. int radius = GetBoundingRadius(); if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) ) return false; dx = m_Size.x >> 1; // dx also is the radius for rounded pads dy = m_Size.y >> 1; switch( GetShape() ) { case PAD_SHAPE_CIRCLE: if( KiROUND( EuclideanNorm( delta ) ) <= dx ) return true; break; case PAD_SHAPE_TRAPEZOID: { wxPoint poly[4]; BuildPadPolygon( poly, wxSize(0,0), 0 ); RotatePoint( &delta, -m_Orient ); return TestPointInsidePolygon( poly, 4, delta ); } case PAD_SHAPE_OVAL: { RotatePoint( &delta, -m_Orient ); // An oval pad has the same shape as a segment with rounded ends // After rotation, the test point is relative to an horizontal pad int dist; wxPoint offset; if( dy > dx ) // shape is a vertical oval { offset.y = dy - dx; dist = dx; } else //if( dy <= dx ) shape is an horizontal oval { offset.x = dy - dx; dist = dy; } return TestSegmentHit( delta, - offset, offset, dist ); } break; case PAD_SHAPE_RECT: RotatePoint( &delta, -m_Orient ); if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) ) return true; break; case PAD_SHAPE_ROUNDRECT: { // Check for hit in polygon SHAPE_POLY_SET outline; const int segmentToCircleCount = 32; TransformRoundRectToPolygon( outline, wxPoint(0,0), GetSize(), m_Orient, GetRoundRectCornerRadius(), segmentToCircleCount ); const SHAPE_LINE_CHAIN &poly = outline.COutline( 0 ); return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta ); } break; case PAD_SHAPE_CUSTOM: // Check for hit in polygon RotatePoint( &delta, -m_Orient ); if( m_customShapeAsPolygon.OutlineCount() ) { const SHAPE_LINE_CHAIN& poly = m_customShapeAsPolygon.COutline( 0 ); return TestPointInsidePolygon( (const wxPoint*)&poly.CPoint(0), poly.PointCount(), delta ); } break; } return false; }
void CDigitanksEntity::OnRender(CGameRenderingContext* pContext) const { BaseClass::OnRender(pContext); if (GameServer()->GetRenderer()->IsRenderingTransparent() && IsImprisoned()) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBackCulling(false); c.SetBlend(BLEND_ADDITIVE); c.Scale(GetBoundingRadius(), GetBoundingRadius(), GetBoundingRadius()); c.Rotate((float)GameServer()->GetGameTime() * 90, Vector(0, 0, 1)); float flVisibility = GetVisibility() * 0.6f; c.UseProgram("scroll"); c.SetUniform("iTexture", 0); c.SetUniform("flAlpha", flVisibility); c.SetUniform("flTime", (float)-GameServer()->GetGameTime()); c.SetUniform("flSpeed", 1.0f); c.RenderModel(m_iCageModel, this); } if (GameServer()->GetRenderer()->IsRenderingTransparent() && IsImprisoned()) { CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBackCulling(false); c.SetBlend(BLEND_ADDITIVE); c.Scale(GetBoundingRadius()+1, GetBoundingRadius()+1, GetBoundingRadius()+1); c.Rotate(-(float)GameServer()->GetGameTime() * 90, Vector(0, 0, 1)); float flVisibility = GetVisibility() * 0.6f; c.UseProgram("scroll"); c.SetUniform("iTexture", 0); c.SetUniform("flAlpha", flVisibility); c.SetUniform("flTime", (float)-GameServer()->GetGameTime()); c.SetUniform("flSpeed", 1.0f); c.RenderModel(m_iCageModel); } if (!GameServer()->GetRenderer()->IsRenderingTransparent()) return; if (!DigitanksGame()->GetTerrain()->GetBit(CTerrain::WorldToArraySpace(GetGlobalOrigin().x), CTerrain::WorldToArraySpace(GetGlobalOrigin().y), TB_TREE)) return; if (GetVisibility() < 0.6f) return; CGameRenderingContext c(GameServer()->GetRenderer(), true); c.SetBlend(BLEND_NONE); c.SetAlpha(1); c.BindTexture(0); TStubbed("Tank outlines in trees"); /* // Draw outlines of objects in trees. glPushAttrib( GL_ALL_ATTRIB_BITS ); glDisable( GL_TEXTURE_2D ); glEnable( GL_POLYGON_OFFSET_FILL ); glPolygonOffset( -3.5f, -3.5f ); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(true); glEnable(GL_DEPTH_TEST); pContext->RenderModel(GetModel()); glDisable( GL_POLYGON_OFFSET_FILL ); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(false); glEnable(GL_DEPTH_TEST); glLineWidth( 2.0f ); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); glColor3ubv( Color(0, 0, 0) ); pContext->RenderModel(GetModel()); glPopAttrib(); */ }
void CSupplier::PostRender() const { BaseClass::PostRender(); if (!GameServer()->GetRenderer()->IsRenderingTransparent()) return; float flGrowthTime = (float)(GameServer()->GetGameTime() - m_flTendrilGrowthStartTime); if (flGrowthTime < 0) return; if (m_flTendrilGrowthStartTime == 0) { DigitanksGame()->GetDigitanksRenderer()->AddTendrilBatch(this); return; } COverheadCamera* pCamera = DigitanksGame()->GetOverheadCamera(); Vector vecCamera = pCamera->GetGlobalOrigin(); float flDistanceSqr = GetGlobalOrigin().DistanceSqr(vecCamera); float flFadeDistance = tendril_fade_distance.GetFloat(); float flFadeAlpha = RemapValClamped(flDistanceSqr, flFadeDistance*flFadeDistance, (flFadeDistance+20)*(flFadeDistance+20), 1.0f, 0.0f); if (flFadeAlpha <= 0) return; float flTreeAlpha = 1.0f; if (DigitanksGame()->GetTerrain()->GetBit(CTerrain::WorldToArraySpace(GetGlobalOrigin().x), CTerrain::WorldToArraySpace(GetGlobalOrigin().y), TB_TREE)) flTreeAlpha = 0.3f; CRenderingContext r(GameServer()->GetRenderer(), true); if (DigitanksGame()->ShouldRenderFogOfWar()) r.UseFrameBuffer(DigitanksGame()->GetDigitanksRenderer()->GetVisibilityMaskedBuffer()); r.SetDepthMask(false); r.UseMaterial(s_hTendrilBeam); r.SetUniform("flTime", (float)GameServer()->GetGameTime()); r.SetUniform("iTexture", 0); r.SetUniform("flAlpha", flFadeAlpha * flTreeAlpha); Color clrTeam = GetPlayerOwner()?GetPlayerOwner()->GetColor():Color(255,255,255,255); clrTeam = (Vector(clrTeam) + Vector(1,1,1))/2; if (m_flTendrilGrowthStartTime > 0) { float flTotalSize = (float)m_aTendrils.size() + GetBoundingRadius(); for (size_t i = 0; i < m_aTendrils.size(); i++) { if (i < m_aTendrils.size() - 15) continue; const CTendril* pTendril = &m_aTendrils[i]; float flGrowthLength = RemapVal(flGrowthTime, 0, GROWTH_TIME, pTendril->m_flLength-flTotalSize, pTendril->m_flLength); if (flGrowthLength < 0) continue; Vector vecDestination = GetGlobalOrigin() + (pTendril->m_vecEndPoint - GetGlobalOrigin()).Normalized() * flGrowthLength; Vector vecPath = vecDestination - GetGlobalOrigin(); vecPath.y = 0; float flDistance = vecPath.Length2D(); Vector vecDirection = vecPath.Normalized(); size_t iSegments = (size_t)(flDistance/3); r.SetUniform("flSpeed", pTendril->m_flSpeed); clrTeam.SetAlpha(105); CRopeRenderer oRope(GameServer()->GetRenderer(), s_hTendrilBeam, DigitanksGame()->GetTerrain()->GetPointHeight(GetGlobalOrigin()) + Vector(0, 0, 1), 1.0f); oRope.SetColor(clrTeam); oRope.SetTextureScale(pTendril->m_flScale); oRope.SetTextureOffset(pTendril->m_flOffset); oRope.SetForward(Vector(0, 0, -1)); for (size_t i = 1; i < iSegments; i++) { clrTeam.SetAlpha((int)RemapVal((float)i, 1, (float)iSegments, 100, 30)); oRope.SetColor(clrTeam); float flCurrentDistance = ((float)i*flDistance)/iSegments; oRope.AddLink(DigitanksGame()->GetTerrain()->GetPointHeight(GetGlobalOrigin() + vecDirection*flCurrentDistance) + Vector(0, 0, 1)); } oRope.Finish(DigitanksGame()->GetTerrain()->GetPointHeight(vecDestination) + Vector(0, 0, 1)); } } }
void CSupplier::UpdateTendrils() { if (IsConstructing()) return; TStubbed("Tendrils"); #if 0 if (!GetPlayerOwner()) { if (m_iTendrilsCallList) glDeleteLists((GLuint)m_iTendrilsCallList, 1); m_iTendrilsCallList = 0; DigitanksGame()->GetTerrain()->DirtyChunkTexturesWithinDistance(GetGlobalOrigin(), GetDataFlowRadius() + GetBoundingRadius()); return; } if (GameServer()->IsLoading()) return; bool bUpdateTerrain = false; size_t iRadius = (size_t)GetDataFlowRadius(); while (m_aTendrils.size() < iRadius) { m_aTendrils.push_back(CTendril()); CTendril* pTendril = &m_aTendrils[m_aTendrils.size()-1]; pTendril->m_flLength = (float)m_aTendrils.size() + GetBoundingRadius(); pTendril->m_vecEndPoint = DigitanksGame()->GetTerrain()->GetPointHeight(GetGlobalOrigin() + AngleVector(EAngle(0, RandomFloat(0, 360), 0)) * pTendril->m_flLength); pTendril->m_flScale = RandomFloat(3, 7); pTendril->m_flOffset = RandomFloat(0, 1); pTendril->m_flSpeed = RandomFloat(0.5f, 2); bUpdateTerrain = true; } if (bUpdateTerrain) DigitanksGame()->GetTerrain()->DirtyChunkTexturesWithinDistance(GetGlobalOrigin(), GetDataFlowRadius() + GetBoundingRadius()); if (m_iTendrilsCallList) glDeleteLists((GLuint)m_iTendrilsCallList, 1); m_iTendrilsCallList = glGenLists(1); Color clrTeam = GetPlayerOwner()->GetColor(); clrTeam = (Vector(clrTeam) + Vector(1,1,1))/2; glNewList((GLuint)m_iTendrilsCallList, GL_COMPILE); for (size_t i = 0; i < m_aTendrils.size(); i++) { // Only show the longest tendrils, for perf reasons. if (i < iRadius - 15) continue; CTendril* pTendril = &m_aTendrils[i]; Vector vecDestination = pTendril->m_vecEndPoint; Vector vecPath = vecDestination - GetGlobalOrigin(); vecPath.y = 0; float flDistance = vecPath.Length2D(); Vector vecDirection = vecPath.Normalized(); size_t iSegments = (size_t)(flDistance/3); GLuint iScrollingTextureProgram = (GLuint)CShaderLibrary::GetScrollingTextureProgram(); GLuint flSpeed = glGetUniformLocation(iScrollingTextureProgram, "flSpeed"); glUniform1f(flSpeed, pTendril->m_flSpeed); clrTeam.SetAlpha(105); CRopeRenderer oRope(GameServer()->GetRenderer(), s_iTendrilBeam, DigitanksGame()->GetTerrain()->GetPointHeight(GetGlobalOrigin()) + Vector(0, 0, 1), 1.0f); oRope.SetColor(clrTeam); oRope.SetTextureScale(pTendril->m_flScale); oRope.SetTextureOffset(pTendril->m_flOffset); oRope.SetForward(Vector(0, 0, -1)); for (size_t i = 1; i < iSegments; i++) { clrTeam.SetAlpha((int)RemapVal((float)i, 1, (float)iSegments, 100, 30)); oRope.SetColor(clrTeam); float flCurrentDistance = ((float)i*flDistance)/iSegments; oRope.AddLink(DigitanksGame()->GetTerrain()->GetPointHeight(GetGlobalOrigin() + vecDirection*flCurrentDistance) + Vector(0, 0, 1)); } oRope.Finish(DigitanksGame()->GetTerrain()->GetPointHeight(vecDestination) + Vector(0, 0, 1)); } glEndList(); #endif }
float CSupplier::GetDataFlow(Vector vecPoint) const { return RemapValClamped((vecPoint - GetGlobalOrigin()).Length(), GetBoundingRadius(), GetDataFlowRadius()+GetBoundingRadius(), (float)m_iDataStrength, 0); }
float CSupplier::GetDataFlowRadius() const { // Opposite of formula for area of a circle. return sqrt((float)m_iDataStrength.Get()/M_PI) + GetBoundingRadius(); }
float CStructure::AvailableArea(int iArea) const { return GetBoundingRadius(); }
bool D_PAD::HitTest( const wxPoint& aPosition ) const { int dx, dy; wxPoint shape_pos = ShapePos(); wxPoint delta = aPosition - shape_pos; // first test: a test point must be inside a minimum sized bounding circle. int radius = GetBoundingRadius(); if( ( abs( delta.x ) > radius ) || ( abs( delta.y ) > radius ) ) return false; dx = m_Size.x >> 1; // dx also is the radius for rounded pads dy = m_Size.y >> 1; switch( GetShape() ) { case PAD_SHAPE_CIRCLE: if( KiROUND( EuclideanNorm( delta ) ) <= dx ) return true; break; case PAD_SHAPE_TRAPEZOID: { wxPoint poly[4]; BuildPadPolygon( poly, wxSize(0,0), 0 ); RotatePoint( &delta, -m_Orient ); return TestPointInsidePolygon( poly, 4, delta ); } case PAD_SHAPE_OVAL: { RotatePoint( &delta, -m_Orient ); // An oval pad has the same shape as a segment with rounded ends // After rotation, the test point is relative to an horizontal pad int dist; wxPoint offset; if( dy > dx ) // shape is a vertical oval { offset.y = dy - dx; dist = dx; } else //if( dy <= dx ) shape is an horizontal oval { offset.x = dy - dx; dist = dy; } return TestSegmentHit( delta, - offset, offset, dist ); } break; case PAD_SHAPE_RECT: RotatePoint( &delta, -m_Orient ); if( (abs( delta.x ) <= dx ) && (abs( delta.y ) <= dy) ) return true; break; } return false; }
void CSupplier::OnTeamChange() { if (!GetPlayerOwner()) { for (size_t i = 0; i < m_ahChildren.size(); i++) { if (!m_ahChildren[i]) continue; m_ahChildren[i]->SetSupplier(NULL); CStructure* pStructure = dynamic_cast<CStructure*>(m_ahChildren[i].GetPointer()); if (!pStructure) continue; if (pStructure->GetPlayerOwner()) { pStructure->GetPlayerOwner()->RemoveUnit(pStructure); DigitanksGame()->OnDisabled(pStructure, NULL, NULL); } } } BaseClass::OnTeamChange(); UpdateTendrils(); // This happens in UpdateTendrils() but do it again here anyway because UpdateTendrils only does it if there's a new tendril created. DigitanksGame()->GetTerrain()->DirtyChunkTexturesWithinDistance(GetGlobalOrigin(), GetDataFlowRadius() + GetBoundingRadius()); }